deps: upgrade to npm 2.14.4
[platform/upstream/nodejs.git] / deps / npm / node_modules / which / which.js
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
11 var fs = require('fs')
12 var isAbsolute = require('is-absolute')
13
14 var G =  parseInt('0010', 8)
15 var U =  parseInt('0100', 8)
16 var UG = parseInt('0110', 8)
17
18 if (isWindows) {
19   // On windows, there is no good way to check that a file is executable
20   isExe = function isExe () { return true }
21 } else {
22   isExe = function isExe (mod, uid, gid) {
23     var ret = (mod & 1)
24         || (mod & U)  && process.getgid && gid === process.getgid()
25         || (mod & G)  && process.getuid && uid === process.getuid()
26         || (mod & UG) && process.getuid && 0   === process.getuid()
27
28     if (!ret && process.getgroups && (mod & G)) {
29       var groups = process.getgroups()
30       for (var g = 0; g < groups.length; g++) {
31         if (groups[g] === gid)
32           return true
33       }
34     }
35
36     return ret
37   }
38 }
39
40 function getPathInfo(cmd, opt) {
41   var colon = opt.colon || COLON
42   var pathEnv = opt.path || process.env.PATH || ''
43   var pathExt = ['']
44
45   pathEnv = pathEnv.split(colon)
46
47   if (isWindows) {
48     pathEnv.unshift(process.cwd())
49     pathExt = (opt.pathExt || process.env.PATHEXT || '.EXE').split(colon)
50     if (cmd.indexOf('.') !== -1 && pathExt[0] !== '')
51       pathExt.unshift('')
52   }
53
54   // If it's absolute, then we don't bother searching the pathenv.
55   // just check the file itself, and that's it.
56   if (isAbsolute(cmd))
57     pathEnv = ['']
58
59   return {env: pathEnv, ext: pathExt}
60 }
61
62 function which (cmd, opt, cb) {
63   if (typeof opt === 'function') {
64     cb = opt
65     opt = {}
66   }
67
68   var info = getPathInfo(cmd, opt)
69   var pathEnv = info.env
70   var pathExt = info.ext
71
72   ;(function F (i, l) {
73     if (i === l) return cb(new Error('not found: '+cmd))
74     var p = path.resolve(pathEnv[i], cmd)
75     ;(function E (ii, ll) {
76       if (ii === ll) return F(i + 1, l)
77       var ext = pathExt[ii]
78       fs.stat(p + ext, function (er, stat) {
79         if (!er &&
80             stat.isFile() &&
81             isExe(stat.mode, stat.uid, stat.gid)) {
82           return cb(null, p + ext)
83         }
84         return E(ii + 1, ll)
85       })
86     })(0, pathExt.length)
87   })(0, pathEnv.length)
88 }
89
90 function whichSync (cmd, opt) {
91   opt = opt || {}
92
93   var info = getPathInfo(cmd, opt)
94   var pathEnv = info.env
95   var pathExt = info.ext
96
97   for (var i = 0, l = pathEnv.length; i < l; i ++) {
98     var p = path.join(pathEnv[i], cmd)
99     for (var j = 0, ll = pathExt.length; j < ll; j ++) {
100       var cur = p + pathExt[j]
101       var stat
102       try {
103         stat = fs.statSync(cur)
104         if (stat.isFile() && isExe(stat.mode, stat.uid, stat.gid))
105           return cur
106       } catch (ex) {}
107     }
108   }
109
110   throw new Error('not found: '+cmd)
111 }