Skip to content

Commit

Permalink
Support multiple commands with same name
Browse files Browse the repository at this point in the history
  • Loading branch information
gustavohenke committed May 13, 2022
1 parent 28cec90 commit 2660b38
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 9 deletions.
5 changes: 3 additions & 2 deletions bin/concurrently.ts
Expand Up @@ -53,8 +53,9 @@ const args = yargs(argsBeforeSep)
'- "first" for the first command to exit;\n' +
'- "last" for the last command to exit;\n' +
'- "all" for all commands;\n' +
'- "command-{name}"/"command-{index}" for the command with that name or index;\n' +
'- "!command-{name}"/"!command-{index}" for all commands but the one with that ' +
// Note: not a typo. Multiple commands can have the same name.
'- "command-{name}"/"command-{index}" for the commands with that name or index;\n' +
'- "!command-{name}"/"!command-{index}" for all commands but the ones with that ' +
'name or index.\n',
default: defaults.success,
},
Expand Down
26 changes: 26 additions & 0 deletions src/completion-listener.spec.ts
Expand Up @@ -122,6 +122,19 @@ describe.each([
return expect(result).resolves.toEqual(expect.anything());
});

it(`succeeds if all commands ${nameOrIndex} exit with code 0`, () => {
commands = [commands[0], commands[1], commands[1]];
const result = createController(condition).listen(commands);

emitFakeCloseEvent(commands[0], { exitCode: 1 });
emitFakeCloseEvent(commands[1], { exitCode: 0 });
emitFakeCloseEvent(commands[2], { exitCode: 0 });

scheduler.flush();

return expect(result).resolves.toEqual(expect.anything());
});

it(`fails if command ${nameOrIndex} exits with non-0 code`, () => {
const result = createController(condition).listen(commands);

Expand All @@ -134,6 +147,19 @@ describe.each([
return expect(result).rejects.toEqual(expect.anything());
});

it(`fails if some commands ${nameOrIndex} exit with non-0 code`, () => {
commands = [commands[0], commands[1], commands[1]];
const result = createController(condition).listen(commands);

emitFakeCloseEvent(commands[0], { exitCode: 1 });
emitFakeCloseEvent(commands[1], { exitCode: 0 });
emitFakeCloseEvent(commands[2], { exitCode: 1 });

scheduler.flush();

return expect(result).resolves.toEqual(expect.anything());
});

it(`fails if command ${nameOrIndex} doesn't exist`, () => {
const result = createController(condition).listen([commands[0]]);

Expand Down
21 changes: 14 additions & 7 deletions src/completion-listener.ts
Expand Up @@ -48,17 +48,24 @@ export class CompletionListener {
return events.every(({ exitCode }) => exitCode === 0);
}

// Check `command-` syntax condition
// Check `command-` syntax condition.
// Note that a command's `name` is not necessarily unique,
// in which case all of them must meet the success condition.
const [, nameOrIndex] = this.successCondition.split('-');
const targetCommandEvent = events.find(({ command, index }) => (
const targetCommandsEvents = events.filter(({ command, index }) => (
command.name === nameOrIndex
|| index === Number(nameOrIndex)
));
return this.successCondition.startsWith('!')
// All commands except the specified one must exit succesfully
? events.every((event) => event === targetCommandEvent || event.exitCode === 0)
// Only the specified command must exit succesfully
: targetCommandEvent && targetCommandEvent.exitCode === 0;
if (this.successCondition.startsWith('!')) {
// All commands except the specified ones must exit succesfully
return events.every((event) => (
targetCommandsEvents.includes(event)
|| event.exitCode === 0
));
}
// Only the specified commands must exit succesfully
return targetCommandsEvents.length > 0
&& targetCommandsEvents.every(event => event.exitCode === 0);
}

/**
Expand Down

0 comments on commit 2660b38

Please sign in to comment.