index.js 2.0 KB

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