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