Skip to content

Commit

Permalink
feat: noThrow to ignore specific exit codes on commands (#200)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsherret committed Dec 17, 2023
1 parent 0c7dc79 commit c1028da
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 5 deletions.
12 changes: 12 additions & 0 deletions mod.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,18 @@ Deno.test("exit command", async () => {
assertEquals(result.code, 2);
assertEquals(result.stderr, "exit: too many arguments\n");
}
// test noThrow with exit code
{
const result = await $`exit 255`.noThrow(255);
assertEquals(result.code, 255);
}
{
const result = await $`exit 255`.noThrow(254, 255);
assertEquals(result.code, 255);
}
{
await assertRejects(() => $`exit 255`.noThrow(254));
}
});

Deno.test("should provide result from one command to another", async () => {
Expand Down
18 changes: 13 additions & 5 deletions src/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ interface CommandBuilderState {
combinedStdoutStderr: boolean;
stdoutKind: ShellPipeWriterKind;
stderrKind: ShellPipeWriterKind;
noThrow: boolean;
noThrow: boolean | number[];
env: Record<string, string | undefined>;
commands: Record<string, CommandHandler>;
cwd: string | undefined;
Expand Down Expand Up @@ -120,7 +120,7 @@ export class CommandBuilder implements PromiseLike<CommandResult> {
stdin: state.stdin,
stdoutKind: state.stdoutKind,
stderrKind: state.stderrKind,
noThrow: state.noThrow,
noThrow: state.noThrow instanceof Array ? [...state.noThrow] : state.noThrow,
env: { ...state.env },
cwd: state.cwd,
commands: { ...state.commands },
Expand Down Expand Up @@ -200,10 +200,17 @@ export class CommandBuilder implements PromiseLike<CommandResult> {
});
}

/** The command should not throw for the provided non-zero exit codes. */
noThrow(exclusionExitCode: number, ...additional: number[]): CommandBuilder;
/** The command should not throw when it fails or times out. */
noThrow(value = true): CommandBuilder {
noThrow(value?: boolean): CommandBuilder;
noThrow(value?: boolean | number, ...additional: number[]): CommandBuilder {
return this.#newWithState((state) => {
state.noThrow = value;
if (typeof value === "boolean" || value == null) {
state.noThrow = value ?? true;
} else {
state.noThrow = [value, ...additional];
}
});
}

Expand Down Expand Up @@ -621,7 +628,8 @@ export function parseAndSpawnCommand(state: CommandBuilderState) {
// override the code in the case of a timeout that resulted in a failure
code = 124;
}
if (!state.noThrow) {
const noThrow = state.noThrow instanceof Array ? state.noThrow.includes(code) : state.noThrow;
if (!noThrow) {
if (stdin instanceof ReadableStream) {
if (!stdin.locked) {
stdin.cancel();
Expand Down

0 comments on commit c1028da

Please sign in to comment.