which
Advanced tools
Comparing version 1.3.1 to 2.0.0
# Changes | ||
## 2.0.0 | ||
* Parallel tests, modern JavaScript, and drop support for node < 8 | ||
## 1.3.1 | ||
@@ -5,0 +9,0 @@ |
@@ -5,3 +5,3 @@ { | ||
"description": "Like which(1) unix command. Find the first instance of an executable in the PATH.", | ||
"version": "1.3.1", | ||
"version": "2.0.0", | ||
"repository": { | ||
@@ -20,3 +20,3 @@ "type": "git", | ||
"rimraf": "^2.6.2", | ||
"tap": "^12.0.1" | ||
"tap": "^14.6.9" | ||
}, | ||
@@ -31,3 +31,6 @@ "scripts": { | ||
"bin/which" | ||
] | ||
], | ||
"engines": { | ||
"node": ">= 8" | ||
} | ||
} |
137
which.js
@@ -1,35 +0,32 @@ | ||
module.exports = which | ||
which.sync = whichSync | ||
var isWindows = process.platform === 'win32' || | ||
const isWindows = process.platform === 'win32' || | ||
process.env.OSTYPE === 'cygwin' || | ||
process.env.OSTYPE === 'msys' | ||
var path = require('path') | ||
var COLON = isWindows ? ';' : ':' | ||
var isexe = require('isexe') | ||
const path = require('path') | ||
const COLON = isWindows ? ';' : ':' | ||
const isexe = require('isexe') | ||
function getNotFoundError (cmd) { | ||
var er = new Error('not found: ' + cmd) | ||
er.code = 'ENOENT' | ||
const getNotFoundError = (cmd) => | ||
Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' }) | ||
return er | ||
} | ||
const getPathInfo = (cmd, opt) => { | ||
const colon = opt.colon || COLON | ||
function getPathInfo (cmd, opt) { | ||
var colon = opt.colon || COLON | ||
var pathEnv = opt.path || process.env.PATH || '' | ||
var pathExt = [''] | ||
// If it has a slash, then we don't bother searching the pathenv. | ||
// just check the file itself, and that's it. | ||
const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [''] | ||
: ( | ||
[ | ||
// windows always checks the cwd first | ||
...(isWindows ? [process.cwd()] : []), | ||
...(opt.path || process.env.PATH || | ||
/* istanbul ignore next: very unusual */ '').split(colon), | ||
] | ||
) | ||
const pathExtExe = isWindows | ||
? opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM' | ||
: '' | ||
const pathExt = isWindows ? pathExtExe.split(colon) : [''] | ||
pathEnv = pathEnv.split(colon) | ||
var pathExtExe = '' | ||
if (isWindows) { | ||
pathEnv.unshift(process.cwd()) | ||
pathExtExe = (opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM') | ||
pathExt = pathExtExe.split(colon) | ||
// Always test the cmd itself first. isexe will check to make sure | ||
// it's found in the pathExt set. | ||
if (cmd.indexOf('.') !== -1 && pathExt[0] !== '') | ||
@@ -39,15 +36,10 @@ pathExt.unshift('') | ||
// If it has a slash, then we don't bother searching the pathenv. | ||
// just check the file itself, and that's it. | ||
if (cmd.match(/\//) || isWindows && cmd.match(/\\/)) | ||
pathEnv = [''] | ||
return { | ||
env: pathEnv, | ||
ext: pathExt, | ||
extExe: pathExtExe | ||
pathEnv, | ||
pathExt, | ||
pathExtExe, | ||
} | ||
} | ||
function which (cmd, opt, cb) { | ||
const which = (cmd, opt, cb) => { | ||
if (typeof opt === 'function') { | ||
@@ -58,10 +50,7 @@ cb = opt | ||
var info = getPathInfo(cmd, opt) | ||
var pathEnv = info.env | ||
var pathExt = info.ext | ||
var pathExtExe = info.extExe | ||
var found = [] | ||
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) | ||
const found = [] | ||
;(function F (i, l) { | ||
if (i === l) { | ||
const F = i => { | ||
if (i === pathEnv.length) { | ||
if (opt.all && found.length) | ||
@@ -73,14 +62,14 @@ return cb(null, found) | ||
var pathPart = pathEnv[i] | ||
if (pathPart.charAt(0) === '"' && pathPart.slice(-1) === '"') | ||
pathPart = pathPart.slice(1, -1) | ||
const ppRaw = pathEnv[i] | ||
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw | ||
var p = path.join(pathPart, cmd) | ||
if (!pathPart && (/^\.[\\\/]/).test(cmd)) { | ||
p = cmd.slice(0, 2) + p | ||
} | ||
;(function E (ii, ll) { | ||
if (ii === ll) return F(i + 1, l) | ||
var ext = pathExt[ii] | ||
isexe(p + ext, { pathExt: pathExtExe }, function (er, is) { | ||
const pCmd = path.join(pathPart, cmd) | ||
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd | ||
: pCmd | ||
const E = (ii) => { | ||
if (ii === pathExt.length) | ||
return F(i + 1) | ||
const ext = pathExt[ii] | ||
isexe(p + ext, { pathExt: pathExtExe }, (er, is) => { | ||
if (!er && is) { | ||
@@ -92,31 +81,28 @@ if (opt.all) | ||
} | ||
return E(ii + 1, ll) | ||
return E(ii + 1, pathExt.length) | ||
}) | ||
})(0, pathExt.length) | ||
})(0, pathEnv.length) | ||
} | ||
return E(0) | ||
} | ||
return F(0) | ||
} | ||
function whichSync (cmd, opt) { | ||
const whichSync = (cmd, opt) => { | ||
opt = opt || {} | ||
var info = getPathInfo(cmd, opt) | ||
var pathEnv = info.env | ||
var pathExt = info.ext | ||
var pathExtExe = info.extExe | ||
var found = [] | ||
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) | ||
const found = [] | ||
for (var i = 0, l = pathEnv.length; i < l; i ++) { | ||
var pathPart = pathEnv[i] | ||
if (pathPart.charAt(0) === '"' && pathPart.slice(-1) === '"') | ||
pathPart = pathPart.slice(1, -1) | ||
for (let i = 0; i < pathEnv.length; i ++) { | ||
const ppRaw = pathEnv[i] | ||
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw | ||
var p = path.join(pathPart, cmd) | ||
if (!pathPart && /^\.[\\\/]/.test(cmd)) { | ||
p = cmd.slice(0, 2) + p | ||
} | ||
for (var j = 0, ll = pathExt.length; j < ll; j ++) { | ||
var cur = p + pathExt[j] | ||
var is | ||
const pCmd = path.join(pathPart, cmd) | ||
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd | ||
: pCmd | ||
for (let j = 0; j < pathExt.length; j ++) { | ||
const cur = p + pathExt[j] | ||
try { | ||
is = isexe.sync(cur, { pathExt: pathExtExe }) | ||
const is = isexe.sync(cur, { pathExt: pathExtExe }) | ||
if (is) { | ||
@@ -140,1 +126,4 @@ if (opt.all) | ||
} | ||
module.exports = which | ||
which.sync = whichSync |
9386
103