Skip to content

Commit 12337cc

Browse files
committed
1 parent b1ad3ad commit 12337cc

File tree

30 files changed

+1250
-21
lines changed

30 files changed

+1250
-21
lines changed

node_modules/.gitignore

+12
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,24 @@
2222
!/@npmcli/disparity-colors
2323
!/@npmcli/fs
2424
!/@npmcli/git
25+
!/@npmcli/git/node_modules/
26+
/@npmcli/git/node_modules/*
27+
!/@npmcli/git/node_modules/which
2528
!/@npmcli/installed-package-contents
2629
!/@npmcli/map-workspaces
2730
!/@npmcli/metavuln-calculator
2831
!/@npmcli/name-from-folder
2932
!/@npmcli/node-gyp
3033
!/@npmcli/package-json
3134
!/@npmcli/promise-spawn
35+
!/@npmcli/promise-spawn/node_modules/
36+
/@npmcli/promise-spawn/node_modules/*
37+
!/@npmcli/promise-spawn/node_modules/which
3238
!/@npmcli/query
3339
!/@npmcli/run-script
40+
!/@npmcli/run-script/node_modules/
41+
/@npmcli/run-script/node_modules/*
42+
!/@npmcli/run-script/node_modules/which
3443
!/@pkgjs/
3544
/@pkgjs/*
3645
!/@pkgjs/parseargs
@@ -281,6 +290,9 @@
281290
!/walk-up-path
282291
!/wcwidth
283292
!/which
293+
!/which/node_modules/
294+
/which/node_modules/*
295+
!/which/node_modules/isexe
284296
!/wide-align
285297
!/wrap-ansi-cjs
286298
!/wrap-ansi
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
The ISC License
2+
3+
Copyright (c) Isaac Z. Schlueter and Contributors
4+
5+
Permission to use, copy, modify, and/or distribute this software for any
6+
purpose with or without fee is hereby granted, provided that the above
7+
copyright notice and this permission notice appear in all copies.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15+
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/usr/bin/env node
2+
3+
const which = require('../lib')
4+
const argv = process.argv.slice(2)
5+
6+
const usage = (err) => {
7+
if (err) {
8+
console.error(`which: ${err}`)
9+
}
10+
console.error('usage: which [-as] program ...')
11+
process.exit(1)
12+
}
13+
14+
if (!argv.length) {
15+
return usage()
16+
}
17+
18+
let dashdash = false
19+
const [commands, flags] = argv.reduce((acc, arg) => {
20+
if (dashdash || arg === '--') {
21+
dashdash = true
22+
return acc
23+
}
24+
25+
if (!/^-/.test(arg)) {
26+
acc[0].push(arg)
27+
return acc
28+
}
29+
30+
for (const flag of arg.slice(1).split('')) {
31+
if (flag === 's') {
32+
acc[1].silent = true
33+
} else if (flag === 'a') {
34+
acc[1].all = true
35+
} else {
36+
usage(`illegal option -- ${flag}`)
37+
}
38+
}
39+
40+
return acc
41+
}, [[], {}])
42+
43+
for (const command of commands) {
44+
try {
45+
const res = which.sync(command, { all: flags.all })
46+
if (!flags.silent) {
47+
console.log([].concat(res).join('\n'))
48+
}
49+
} catch (err) {
50+
process.exitCode = 1
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
const isexe = require('isexe')
2+
const { join, delimiter, sep, posix } = require('path')
3+
4+
const isWindows = process.platform === 'win32'
5+
6+
// used to check for slashed in commands passed in. always checks for the posix
7+
// seperator on all platforms, and checks for the current separator when not on
8+
// a posix platform. don't use the isWindows check for this since that is mocked
9+
// in tests but we still need the code to actually work when called. that is also
10+
// why it is ignored from coverage.
11+
/* istanbul ignore next */
12+
const rSlash = new RegExp(`[${posix.sep}${sep === posix.sep ? '' : sep}]`.replace(/(\\)/g, '\\$1'))
13+
const rRel = new RegExp(`^\\.${rSlash.source}`)
14+
15+
const getNotFoundError = (cmd) =>
16+
Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' })
17+
18+
const getPathInfo = (cmd, {
19+
path: optPath = process.env.PATH,
20+
pathExt: optPathExt = process.env.PATHEXT,
21+
delimiter: optDelimiter = delimiter,
22+
}) => {
23+
// If it has a slash, then we don't bother searching the pathenv.
24+
// just check the file itself, and that's it.
25+
const pathEnv = cmd.match(rSlash) ? [''] : [
26+
// windows always checks the cwd first
27+
...(isWindows ? [process.cwd()] : []),
28+
...(optPath || /* istanbul ignore next: very unusual */ '').split(optDelimiter),
29+
]
30+
31+
if (isWindows) {
32+
const pathExtExe = optPathExt ||
33+
['.EXE', '.CMD', '.BAT', '.COM'].join(optDelimiter)
34+
const pathExt = pathExtExe.split(optDelimiter).reduce((acc, item) => {
35+
acc.push(item)
36+
acc.push(item.toLowerCase())
37+
return acc
38+
}, [])
39+
if (cmd.includes('.') && pathExt[0] !== '') {
40+
pathExt.unshift('')
41+
}
42+
return { pathEnv, pathExt, pathExtExe }
43+
}
44+
45+
return { pathEnv, pathExt: [''] }
46+
}
47+
48+
const getPathPart = (raw, cmd) => {
49+
const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw
50+
const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : ''
51+
return prefix + join(pathPart, cmd)
52+
}
53+
54+
const which = async (cmd, opt = {}) => {
55+
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt)
56+
const found = []
57+
58+
for (const envPart of pathEnv) {
59+
const p = getPathPart(envPart, cmd)
60+
61+
for (const ext of pathExt) {
62+
const withExt = p + ext
63+
const is = await isexe(withExt, { pathExt: pathExtExe, ignoreErrors: true })
64+
if (is) {
65+
if (!opt.all) {
66+
return withExt
67+
}
68+
found.push(withExt)
69+
}
70+
}
71+
}
72+
73+
if (opt.all && found.length) {
74+
return found
75+
}
76+
77+
if (opt.nothrow) {
78+
return null
79+
}
80+
81+
throw getNotFoundError(cmd)
82+
}
83+
84+
const whichSync = (cmd, opt = {}) => {
85+
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt)
86+
const found = []
87+
88+
for (const pathEnvPart of pathEnv) {
89+
const p = getPathPart(pathEnvPart, cmd)
90+
91+
for (const ext of pathExt) {
92+
const withExt = p + ext
93+
const is = isexe.sync(withExt, { pathExt: pathExtExe, ignoreErrors: true })
94+
if (is) {
95+
if (!opt.all) {
96+
return withExt
97+
}
98+
found.push(withExt)
99+
}
100+
}
101+
}
102+
103+
if (opt.all && found.length) {
104+
return found
105+
}
106+
107+
if (opt.nothrow) {
108+
return null
109+
}
110+
111+
throw getNotFoundError(cmd)
112+
}
113+
114+
module.exports = which
115+
which.sync = whichSync
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
"author": "GitHub Inc.",
3+
"name": "which",
4+
"description": "Like which(1) unix command. Find the first instance of an executable in the PATH.",
5+
"version": "3.0.1",
6+
"repository": {
7+
"type": "git",
8+
"url": "https://github.com/npm/node-which.git"
9+
},
10+
"main": "lib/index.js",
11+
"bin": {
12+
"node-which": "./bin/which.js"
13+
},
14+
"license": "ISC",
15+
"dependencies": {
16+
"isexe": "^2.0.0"
17+
},
18+
"devDependencies": {
19+
"@npmcli/eslint-config": "^4.0.0",
20+
"@npmcli/template-oss": "4.14.1",
21+
"tap": "^16.3.0"
22+
},
23+
"scripts": {
24+
"test": "tap",
25+
"lint": "eslint \"**/*.js\"",
26+
"postlint": "template-oss-check",
27+
"template-oss-apply": "template-oss-apply --force",
28+
"lintfix": "npm run lint -- --fix",
29+
"snap": "tap",
30+
"posttest": "npm run lint"
31+
},
32+
"files": [
33+
"bin/",
34+
"lib/"
35+
],
36+
"tap": {
37+
"check-coverage": true,
38+
"nyc-arg": [
39+
"--exclude",
40+
"tap-snapshots/**"
41+
]
42+
},
43+
"engines": {
44+
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
45+
},
46+
"templateOSS": {
47+
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
48+
"version": "4.14.1",
49+
"publish": "true"
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
The ISC License
2+
3+
Copyright (c) Isaac Z. Schlueter and Contributors
4+
5+
Permission to use, copy, modify, and/or distribute this software for any
6+
purpose with or without fee is hereby granted, provided that the above
7+
copyright notice and this permission notice appear in all copies.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15+
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/usr/bin/env node
2+
3+
const which = require('../lib')
4+
const argv = process.argv.slice(2)
5+
6+
const usage = (err) => {
7+
if (err) {
8+
console.error(`which: ${err}`)
9+
}
10+
console.error('usage: which [-as] program ...')
11+
process.exit(1)
12+
}
13+
14+
if (!argv.length) {
15+
return usage()
16+
}
17+
18+
let dashdash = false
19+
const [commands, flags] = argv.reduce((acc, arg) => {
20+
if (dashdash || arg === '--') {
21+
dashdash = true
22+
return acc
23+
}
24+
25+
if (!/^-/.test(arg)) {
26+
acc[0].push(arg)
27+
return acc
28+
}
29+
30+
for (const flag of arg.slice(1).split('')) {
31+
if (flag === 's') {
32+
acc[1].silent = true
33+
} else if (flag === 'a') {
34+
acc[1].all = true
35+
} else {
36+
usage(`illegal option -- ${flag}`)
37+
}
38+
}
39+
40+
return acc
41+
}, [[], {}])
42+
43+
for (const command of commands) {
44+
try {
45+
const res = which.sync(command, { all: flags.all })
46+
if (!flags.silent) {
47+
console.log([].concat(res).join('\n'))
48+
}
49+
} catch (err) {
50+
process.exitCode = 1
51+
}
52+
}

0 commit comments

Comments
 (0)