1 | module.exports = which
|
2 | which.sync = whichSync
|
3 |
|
4 | var isWindows = process.platform === 'win32' ||
|
5 | process.env.OSTYPE === 'cygwin' ||
|
6 | process.env.OSTYPE === 'msys'
|
7 |
|
8 | var path = require('path')
|
9 | var COLON = isWindows ? ';' : ':'
|
10 | var isexe = require('isexe')
|
11 | var fs = require('fs')
|
12 | var isAbsolute = require('is-absolute')
|
13 |
|
14 | function getNotFoundError (cmd) {
|
15 | var er = new Error('not found: ' + cmd)
|
16 | er.code = 'ENOENT'
|
17 |
|
18 | return er
|
19 | }
|
20 |
|
21 | function getPathInfo (cmd, opt) {
|
22 | var colon = opt.colon || COLON
|
23 | var pathEnv = opt.path || process.env.Path || process.env.PATH || ''
|
24 | var pathExt = ['']
|
25 |
|
26 | pathEnv = pathEnv.split(colon)
|
27 |
|
28 | var pathExtExe = ''
|
29 | if (isWindows) {
|
30 | pathEnv.unshift(process.cwd())
|
31 | pathExtExe = (opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM')
|
32 | pathExt = pathExtExe.split(colon)
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | if (cmd.indexOf('.') !== -1 && pathExt[0] !== '')
|
38 | pathExt.unshift('')
|
39 | }
|
40 |
|
41 |
|
42 |
|
43 | if (cmd.match(/\//) || isWindows && cmd.match(/\\/))
|
44 | pathEnv = ['']
|
45 |
|
46 | return {
|
47 | env: pathEnv,
|
48 | ext: pathExt,
|
49 | extExe: pathExtExe
|
50 | }
|
51 | }
|
52 |
|
53 | function which (cmd, opt, cb) {
|
54 | if (typeof opt === 'function') {
|
55 | cb = opt
|
56 | opt = {}
|
57 | }
|
58 |
|
59 | var info = getPathInfo(cmd, opt)
|
60 | var pathEnv = info.env
|
61 | var pathExt = info.ext
|
62 | var pathExtExe = info.extExe
|
63 | var found = []
|
64 |
|
65 | ;(function F (i, l) {
|
66 | if (i === l) {
|
67 | if (opt.all && found.length)
|
68 | return cb(null, found)
|
69 | else
|
70 | return cb(getNotFoundError(cmd))
|
71 | }
|
72 |
|
73 | var pathPart = pathEnv[i]
|
74 | if (pathPart.charAt(0) === '"' && pathPart.slice(-1) === '"')
|
75 | pathPart = pathPart.slice(1, -1)
|
76 |
|
77 | var p = path.join(pathPart, cmd)
|
78 | if (!pathPart && (/^\./).test(cmd)) {
|
79 | p = cmd.slice(0, 2) + p
|
80 | }
|
81 | ;(function E (ii, ll) {
|
82 | if (ii === ll) return F(i + 1, l)
|
83 | var ext = pathExt[ii]
|
84 | isexe(p + ext, { pathExt: pathExtExe }, function (er, is) {
|
85 | if (!er && is) {
|
86 | if (opt.all)
|
87 | found.push(p + ext)
|
88 | else
|
89 | return cb(null, p + ext)
|
90 | }
|
91 | return E(ii + 1, ll)
|
92 | })
|
93 | })(0, pathExt.length)
|
94 | })(0, pathEnv.length)
|
95 | }
|
96 |
|
97 | function whichSync (cmd, opt) {
|
98 | opt = opt || {}
|
99 |
|
100 | var info = getPathInfo(cmd, opt)
|
101 | var pathEnv = info.env
|
102 | var pathExt = info.ext
|
103 | var pathExtExe = info.extExe
|
104 | var found = []
|
105 |
|
106 | for (var i = 0, l = pathEnv.length; i < l; i ++) {
|
107 | var pathPart = pathEnv[i]
|
108 | if (pathPart.charAt(0) === '"' && pathPart.slice(-1) === '"')
|
109 | pathPart = pathPart.slice(1, -1)
|
110 |
|
111 | var p = path.join(pathPart, cmd)
|
112 | if (!pathPart && (/^\./).test(cmd)) {
|
113 | p = cmd.slice(0, 2) + p
|
114 | }
|
115 | for (var j = 0, ll = pathExt.length; j < ll; j ++) {
|
116 | var cur = p + pathExt[j]
|
117 | var is
|
118 | try {
|
119 | is = isexe.sync(cur, { pathExt: pathExtExe })
|
120 | if (is) {
|
121 | if (opt.all)
|
122 | found.push(cur)
|
123 | else
|
124 | return cur
|
125 | }
|
126 | } catch (ex) {}
|
127 | }
|
128 | }
|
129 |
|
130 | if (opt.all && found.length)
|
131 | return found
|
132 |
|
133 | throw getNotFoundError(cmd)
|
134 | }
|