forked from zautumnz/is-program-installed
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
98 lines (87 loc) · 2.34 KB
/
index.js
File metadata and controls
98 lines (87 loc) · 2.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
const { readdirSync } = require('fs')
const { execSync } = require('child_process')
const opts = {
stdio: 'ignore'
}
const exec = (cmd) => execSync(cmd, opts)
const isUnixInstalled = (program) => {
try {
exec(`hash ${program} 2>/dev/null`)
return true
} catch {
return false
}
}
const isDirectory = (path) => {
try {
readdirSync(path)
return true
} catch {
return false
}
}
const isDotDesktopInstalled = (program) => {
const dirs = [
process.env.XDG_DATA_HOME && process.env.XDG_DATA_HOME + '/applications',
process.env.HOME && process.env.HOME + '/.local/share/applications',
'/usr/share/applications',
'/usr/local/share/applications'
]
.filter(Boolean)
.filter(isDirectory)
const trimExtension = (x) => x.replace(/\.desktop$/, '')
const desktopFiles = dirs
.flatMap((x) => readdirSync(x))
.filter((x) => x.endsWith('.desktop'))
.map(trimExtension)
const programTrimmed = trimExtension(program)
return desktopFiles.includes(programTrimmed)
}
const isMacInstalled = (program) => {
try {
exec(`osascript -e 'id of application "${program}"' 2>&1>/dev/null`)
return true
} catch {
return false
}
}
const isWindowsInstalled = (program) => {
// Try a couple variants, depending on execution environment the .exe
// may or may not be required on both `where` and the program name.
const attempts = [
`where ${program}`,
`where ${program}.exe`,
`where.exe ${program}`,
`where.exe ${program}.exe`
]
let success = false
for (const a of attempts) {
try {
exec(a)
success = true
} catch {}
}
return success
}
const sanitize = (program) => {
// from https://github.com/parshap/node-sanitize-filename/ licensed WTFPL/ISC
/* eslint-disable no-useless-escape,no-control-regex */
const illegalRe = /[\/\?<>\\:\*\|"]/g
const controlRe = /[\x00-\x1f\x80-\x9f]/g
const reservedRe = /^\.+$/
const probablyTwoThingsRe = /\&\&/g
const beginsWithBgRe = /^&+/
/* eslint-enable no-useless-escape,no-control-regex */
return program
.replace(illegalRe, '')
.replace(controlRe, '')
.replace(reservedRe, '')
.replace(probablyTwoThingsRe, '')
.replace(beginsWithBgRe, '')
}
module.exports = (program) => [
isUnixInstalled,
isMacInstalled,
isWindowsInstalled,
isDotDesktopInstalled
].some((f) => f(sanitize(program)))