codekingpro/portable-devtools
114k
1const fs = require('fs')
2const { promisify } = require('util')
3const { readFileSync } = fs
4const readFile = promisify(fs.readFile)
5
6const extractPath = (path, cmdshimContents) => {
7 if (/[.]cmd$/.test(path)) {
8 return extractPathFromCmd(cmdshimContents)
9 } else if (/[.]ps1$/.test(path)) {
10 return extractPathFromPowershell(cmdshimContents)
11 } else {
12 return extractPathFromCygwin(cmdshimContents)
13 }
14}
15
16const extractPathFromPowershell = cmdshimContents => {
17 const matches = cmdshimContents.match(/"[$]basedir[/]([^"]+?)"\s+[$]args/)
18 return matches && matches[1]
19}
20
21const extractPathFromCmd = cmdshimContents => {
22 const matches = cmdshimContents.match(/"%(?:~dp0|dp0%)\\([^"]+?)"\s+%[*]/)
23 return matches && matches[1]
24}
25
26const extractPathFromCygwin = cmdshimContents => {
27 const matches = cmdshimContents.match(/"[$]basedir[/]([^"]+?)"\s+"[$]@"/)
28 return matches && matches[1]
29}
30
31const wrapError = (thrown, newError) => {
32 newError.message = thrown.message
33 newError.code = thrown.code
34 newError.path = thrown.path
35 return newError
36}
37
38const notaShim = (path, er) => {
39 if (!er) {
40 er = new Error()
41 Error.captureStackTrace(er, notaShim)
42 }
43 er.code = 'ENOTASHIM'
44 er.message = `Can't read shim path from '${path}', ` +
45 `it doesn't appear to be a cmd-shim`
46 return er
47}
48
49const readCmdShim = path => {
50 // create a new error to capture the stack trace from this point,
51 // instead of getting some opaque stack into node's internals
52 const er = new Error()
53 Error.captureStackTrace(er, readCmdShim)
54 return readFile(path).then(contents => {
55 const destination = extractPath(path, contents.toString())
56 if (destination) {
57 return destination
58 }
59 throw notaShim(path, er)
60 }, readFileEr => {
61 throw wrapError(readFileEr, er)
62 })
63}
64
65const readCmdShimSync = path => {
66 const contents = readFileSync(path)
67 const destination = extractPath(path, contents.toString())
68 if (!destination) {
69 throw notaShim(path)
70 }
71 return destination
72}
73
74readCmdShim.sync = readCmdShimSync
75module.exports = readCmdShim
76 