Skip to content

Commit 35f86ae

Browse files
erikkempermanmysticatea
authored andcommitted
Fix: unexpected behavior of leading bang (#124)
1 parent c76db0e commit 35f86ae

File tree

4 files changed

+88
-3
lines changed

4 files changed

+88
-3
lines changed

lib/match-tasks.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ function createFilter(pattern) {
4343
const spacePos = trimmed.indexOf(" ")
4444
const task = spacePos < 0 ? trimmed : trimmed.slice(0, spacePos)
4545
const args = spacePos < 0 ? "" : trimmed.slice(spacePos)
46-
const matcher = new Minimatch(swapColonAndSlash(task))
46+
const matcher = new Minimatch(swapColonAndSlash(task), { nonegate: true })
4747
const match = matcher.match.bind(matcher)
4848

4949
return { match, task, args }

lib/run-task.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,22 @@ function detectStreamKind(stream, std) {
8282
)
8383
}
8484

85+
/**
86+
* Ensure the output of shell-quote's `parse()` is acceptable input to npm-cli.
87+
*
88+
* The `parse()` method of shell-quote sometimes returns special objects in its
89+
* output array, e.g. if it thinks some elements should be globbed. But npm-cli
90+
* only accepts strings and will throw an error otherwise.
91+
*
92+
* See https://github.com/substack/node-shell-quote#parsecmd-env
93+
*
94+
* @param {object|string} arg - Item in the output of shell-quote's `parse()`.
95+
* @returns {string} A valid argument for npm-cli.
96+
*/
97+
function cleanTaskArg(arg) {
98+
return arg.pattern || arg.op || arg
99+
}
100+
85101
//------------------------------------------------------------------------------
86102
// Interface
87103
//------------------------------------------------------------------------------
@@ -153,7 +169,7 @@ module.exports = function runTask(task, options) {
153169
else if (options.prefixOptions.indexOf("--silent") !== -1) {
154170
spawnArgs.push("--silent")
155171
}
156-
Array.prototype.push.apply(spawnArgs, parseArgs(task))
172+
Array.prototype.push.apply(spawnArgs, parseArgs(task).map(cleanTaskArg))
157173

158174
cp = spawn(execPath, spawnArgs, spawnOptions)
159175

test-workspace/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@
3838
"test-task:nest-append:run-s": "node ../bin/run-s/index.js test-task:append",
3939
"test-task:nest-append:run-p": "node ../bin/run-p/index.js test-task:append",
4040
"test-task:delayed": "node tasks/output-with-delay.js",
41-
"test-task:yarn": "node ../bin/npm-run-all/index.js test-task:append:{a,b} --npm-path yarn"
41+
"test-task:yarn": "node ../bin/npm-run-all/index.js test-task:append:{a,b} --npm-path yarn",
42+
"!test": "node tasks/append1.js X",
43+
"?test": "node tasks/append1.js Q"
4244
},
4345
"repository": {
4446
"type": "git",

test/pattern.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,71 @@ describe("[pattern] it should run matched tasks if glob like patterns are given.
143143
}
144144
})
145145
})
146+
147+
describe("\"!test-task:**\" should not match to anything", () => {
148+
it("Node API", async () => {
149+
try {
150+
await nodeApi("!test-task:**")
151+
assert(false, "should not match")
152+
}
153+
catch (err) {
154+
assert((/not found/i).test(err.message))
155+
}
156+
})
157+
158+
it("npm-run-all command", async () => {
159+
const stderr = new BufferStream()
160+
try {
161+
await runAll(["!test-task:**"], null, stderr)
162+
assert(false, "should not match")
163+
}
164+
catch (_err) {
165+
assert((/not found/i).test(stderr.value))
166+
}
167+
})
168+
169+
it("run-s command", async () => {
170+
const stderr = new BufferStream()
171+
try {
172+
await runSeq(["!test-task:**"], null, stderr)
173+
assert(false, "should not match")
174+
}
175+
catch (_err) {
176+
assert((/not found/i).test(stderr.value))
177+
}
178+
})
179+
180+
it("run-p command", async () => {
181+
const stderr = new BufferStream()
182+
try {
183+
await runPar(["!test-task:**"], null, stderr)
184+
assert(false, "should not match")
185+
}
186+
catch (_err) {
187+
assert((/not found/i).test(stderr.value))
188+
}
189+
})
190+
})
191+
192+
describe("\"!test\" \"?test\" to \"!test\", \"?test\"", () => {
193+
it("Node API", async () => {
194+
await nodeApi(["!test", "?test"])
195+
assert(result().trim() === "XQ")
196+
})
197+
198+
it("npm-run-all command", async () => {
199+
await runAll(["!test", "?test"])
200+
assert(result().trim() === "XQ")
201+
})
202+
203+
it("run-s command", async () => {
204+
await runSeq(["!test", "?test"])
205+
assert(result().trim() === "XQ")
206+
})
207+
208+
it("run-p command", async () => {
209+
await runPar(["!test", "?test"])
210+
assert(result().trim() === "XQ" || result().trim() === "QX")
211+
})
212+
})
146213
})

0 commit comments

Comments
 (0)