Skip to content

Commit

Permalink
Improve error messages and ensure throws when cwd doesn't exist in no…
Browse files Browse the repository at this point in the history
…de.js
  • Loading branch information
dsherret committed Feb 3, 2024
1 parent 960367d commit 1c08ee2
Show file tree
Hide file tree
Showing 19 changed files with 97 additions and 50 deletions.
20 changes: 15 additions & 5 deletions mod.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
assertRejects,
assertStringIncludes,
assertThrows,
isNode,
toWritableStream,
usingTempDir,
withTempDir,
Expand Down Expand Up @@ -1602,7 +1603,9 @@ Deno.test("test remove", async () => {
{
const error = await $`rm ${nonEmptyDir}`.noThrow().stderr("piped").spawn()
.then((r) => r.stderr);
const expectedText = Deno.build.os === "linux" || Deno.build.os === "darwin"
const expectedText = isNode
? "rm: directory not empty, rmdir"
: Deno.build.os === "linux" || Deno.build.os === "darwin"
? "rm: Directory not empty"
: "rm: The directory is not empty";
assertEquals(error.substring(0, expectedText.length), expectedText);
Expand All @@ -1616,7 +1619,9 @@ Deno.test("test remove", async () => {
{
const [error, code] = await $`rm ${notExists}`.noThrow().stderr("piped").spawn()
.then((r) => [r.stderr, r.code] as const);
const expectedText = Deno.build.os === "linux" || Deno.build.os === "darwin"
const expectedText = isNode
? "rm: no such file or directory, lstat"
: Deno.build.os === "linux" || Deno.build.os === "darwin"
? "rm: No such file or directory"
: "rm: The system cannot find the file specified";
assertEquals(error.substring(0, expectedText.length), expectedText);
Expand Down Expand Up @@ -1650,7 +1655,9 @@ Deno.test("test mkdir", async () => {
.then(
(r) => r.stderr,
);
const expectedError = Deno.build.os === "windows"
const expectedError = isNode
? "mkdir: no such file or directory, mkdir"
: Deno.build.os === "windows"
? "mkdir: The system cannot find the path specified."
: "mkdir: No such file or directory";
assertEquals(error.slice(0, expectedError.length), expectedError);
Expand Down Expand Up @@ -1771,7 +1778,7 @@ Deno.test("pwd: pwd", async () => {
assertEquals(await $`pwd`.text(), Deno.cwd());
});

Deno.test("progress", async () => {
Deno.test.only("progress", async () => {
const logs: string[] = [];
$.setInfoLogger((...data) => logs.push(data.join(" ")));
const pb = $.progress("Downloading Test");
Expand Down Expand Up @@ -1867,7 +1874,10 @@ Deno.test("cd", () => {
try {
$.cd("./src");
assert(Deno.cwd().endsWith("src"));
$.cd(import.meta.url);
// todo: this originally passed in import.meta, but that
// didn't work in the node cjs tests, so now it's doing this
// thing that doesn't really test it
$.cd($.path(new URL(import.meta.url)).parentOrThrow());
$.cd("./src");
assert(Deno.cwd().endsWith("src"));
const path = $.path(import.meta.url).parentOrThrow();
Expand Down
8 changes: 4 additions & 4 deletions src/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { sleepCommand } from "./commands/sleep.ts";
import { testCommand } from "./commands/test.ts";
import { touchCommand } from "./commands/touch.ts";
import { unsetCommand } from "./commands/unset.ts";
import { Box, delayToMs, LoggerTreeBox } from "./common.ts";
import { Box, delayToMs, errorToString, LoggerTreeBox } from "./common.ts";
import { Delay } from "./common.ts";
import { Buffer, colors, path, readerFromStreamReader, writerFromStreamWriter } from "./deps.ts";
import {
Expand Down Expand Up @@ -1304,7 +1304,7 @@ function templateInner(
} catch (err) {
throw new Error(
`Error getting ReadableStream from function at ` +
`expression ${i + 1}/${exprsCount}. ${err?.message ?? err}`,
`expression ${i + 1}/${exprsCount}. ${errorToString(err)}`,
);
}
});
Expand Down Expand Up @@ -1354,7 +1354,7 @@ function templateInner(
} catch (err) {
throw new Error(
`Error getting WritableStream from function at ` +
`expression ${i + 1}/${exprsCount}. ${err?.message ?? err}`,
`expression ${i + 1}/${exprsCount}. ${errorToString(err)}`,
);
}
});
Expand All @@ -1372,7 +1372,7 @@ function templateInner(
const startMessage = exprsCount === 1
? "Failed resolving expression in command."
: `Failed resolving expression ${i + 1}/${exprsCount} in command.`;
throw new Error(`${startMessage} ${err?.message ?? err}`);
throw new Error(`${startMessage} ${errorToString(err)}`);
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/commands/cat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CommandContext } from "../command_handler.ts";
import { ExecuteResult } from "../result.ts";
import { bailUnsupported, parseArgKinds } from "./args.ts";
import { path as pathUtils } from "../deps.ts";
import { errorToString } from "../common.ts";

interface CatFlags {
paths: string[];
Expand All @@ -14,7 +15,7 @@ export async function catCommand(
const code = await executeCat(context);
return { code };
} catch (err) {
return context.error(`cat: ${err?.message ?? err}`);
return context.error(`cat: ${errorToString(err)}`);
}
}

Expand Down Expand Up @@ -60,7 +61,7 @@ async function executeCat(context: CommandContext) {
}
exitCode = context.signal.abortedExitCode ?? 0;
} catch (err) {
const maybePromise = context.stderr.writeLine(`cat ${path}: ${err?.message ?? err}`);
const maybePromise = context.stderr.writeLine(`cat ${path}: ${errorToString(err)}`);
if (maybePromise instanceof Promise) {
await maybePromise;
}
Expand Down
4 changes: 2 additions & 2 deletions src/commands/cd.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CommandContext } from "../command_handler.ts";
import { resolvePath } from "../common.ts";
import { errorToString, resolvePath } from "../common.ts";
import { ExecuteResult } from "../result.ts";

export async function cdCommand(context: CommandContext): Promise<ExecuteResult> {
Expand All @@ -13,7 +13,7 @@ export async function cdCommand(context: CommandContext): Promise<ExecuteResult>
}],
};
} catch (err) {
return context.error(`cd: ${err?.message ?? err}`);
return context.error(`cd: ${errorToString(err)}`);
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/commands/cp_mv.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { CommandContext } from "../command_handler.ts";
import { ExecuteResult } from "../result.ts";
import { bailUnsupported, parseArgKinds } from "./args.ts";
import { resolvePath, safeLstat } from "../common.ts";
import { errorToString, resolvePath, safeLstat } from "../common.ts";
import { path } from "../deps.ts";

export async function cpCommand(
Expand All @@ -11,7 +11,7 @@ export async function cpCommand(
await executeCp(context.cwd, context.args);
return { code: 0 };
} catch (err) {
return context.error(`cp: ${err?.message ?? err}`);
return context.error(`cp: ${errorToString(err)}`);
}
}

Expand Down Expand Up @@ -100,7 +100,7 @@ export async function mvCommand(
await executeMove(context.cwd, context.args);
return { code: 0 };
} catch (err) {
return context.error(`mv: ${err?.message ?? err}`);
return context.error(`mv: ${errorToString(err)}`);
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/commands/echo.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CommandContext } from "../command_handler.ts";
import { errorToString } from "../common.ts";
import { ExecuteResult } from "../result.ts";

export function echoCommand(context: CommandContext): ExecuteResult | Promise<ExecuteResult> {
Expand All @@ -15,5 +16,5 @@ export function echoCommand(context: CommandContext): ExecuteResult | Promise<Ex
}

function handleFailure(context: CommandContext, err: any) {
return context.error(`echo: ${err?.message ?? err}`);
return context.error(`echo: ${errorToString(err)}`);
}
3 changes: 2 additions & 1 deletion src/commands/exit.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CommandContext } from "../command_handler.ts";
import { errorToString } from "../common.ts";
import { ExecuteResult } from "../result.ts";

export function exitCommand(context: CommandContext): ExecuteResult | Promise<ExecuteResult> {
Expand All @@ -9,7 +10,7 @@ export function exitCommand(context: CommandContext): ExecuteResult | Promise<Ex
code,
};
} catch (err) {
return context.error(2, `exit: ${err?.message ?? err}`);
return context.error(2, `exit: ${errorToString(err)}`);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/commands/mkdir.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CommandContext } from "../command_handler.ts";
import { resolvePath } from "../common.ts";
import { errorToString, resolvePath } from "../common.ts";
import { ExecuteResult } from "../result.ts";
import { safeLstat } from "../common.ts";
import { bailUnsupported, parseArgKinds } from "./args.ts";
Expand All @@ -11,7 +11,7 @@ export async function mkdirCommand(
await executeMkdir(context.cwd, context.args);
return { code: 0 };
} catch (err) {
return context.error(`mkdir: ${err?.message ?? err}`);
return context.error(`mkdir: ${errorToString(err)}`);
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/commands/printenv.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CommandContext } from "../command_handler.ts";
import { errorToString } from "../common.ts";
import { ExecuteResult } from "../result.ts";

export function printEnvCommand(context: CommandContext): ExecuteResult | Promise<ExecuteResult> {
Expand All @@ -25,7 +26,7 @@ export function printEnvCommand(context: CommandContext): ExecuteResult | Promis
}

function handleError(context: CommandContext, err: any): ExecuteResult | Promise<ExecuteResult> {
return context.error(`printenv: ${err?.message ?? err}`);
return context.error(`printenv: ${errorToString(err)}`);
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/commands/pwd.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CommandContext } from "../command_handler.ts";
import { errorToString } from "../common.ts";
import { path } from "../deps.ts";
import { ExecuteResult } from "../result.ts";
import { bailUnsupported, parseArgKinds } from "./args.ts";
Expand All @@ -19,7 +20,7 @@ export function pwdCommand(context: CommandContext): ExecuteResult | Promise<Exe
}

function handleError(context: CommandContext, err: any) {
return context.error(`pwd: ${err?.message ?? err}`);
return context.error(`pwd: ${errorToString(err)}`);
}

function executePwd(cwd: string, args: string[]) {
Expand Down
4 changes: 2 additions & 2 deletions src/commands/rm.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CommandContext } from "../command_handler.ts";
import { resolvePath } from "../common.ts";
import { errorToString, resolvePath } from "../common.ts";
import { ExecuteResult } from "../result.ts";
import { ArgKind, parseArgKinds } from "./args.ts";

Expand All @@ -10,7 +10,7 @@ export async function rmCommand(
await executeRemove(context.cwd, context.args);
return { code: 0 };
} catch (err) {
return context.error(`rm: ${err?.message ?? err}`);
return context.error(`rm: ${errorToString(err)}`);
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/commands/sleep.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CommandContext } from "../command_handler.ts";
import { errorToString } from "../common.ts";
import { ExecuteResult, getAbortedResult } from "../result.ts";

export async function sleepCommand(context: CommandContext): Promise<ExecuteResult> {
Expand Down Expand Up @@ -26,7 +27,7 @@ export async function sleepCommand(context: CommandContext): Promise<ExecuteResu
}
return { code: 0 };
} catch (err) {
return context.error(`sleep: ${err?.message ?? err}`);
return context.error(`sleep: ${errorToString(err)}`);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/commands/test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CommandContext } from "../command_handler.ts";
import { resolvePath, safeLstat } from "../common.ts";
import { errorToString, resolvePath, safeLstat } from "../common.ts";
import { fs } from "../deps.ts";
import { ExecuteResult } from "../result.ts";

Expand Down Expand Up @@ -34,7 +34,7 @@ export async function testCommand(context: CommandContext): Promise<ExecuteResul
return { code: result ? 0 : 1 };
} catch (err) {
// bash test returns 2 on error, e.g. -bash: test: -8: unary operator expected
return context.error(2, `test: ${err?.message ?? err}`);
return context.error(2, `test: ${errorToString(err)}`);
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/commands/touch.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { CommandContext } from "../command_handler.ts";
import { errorToString } from "../common.ts";
import { bailUnsupported, parseArgKinds } from "./args.ts";

export async function touchCommand(context: CommandContext) {
try {
await executetouch(context.args);
return { code: 0 };
} catch (err) {
return context.error(`touch: ${err?.message ?? err}`);
return context.error(`touch: ${errorToString(err)}`);
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/commands/unset.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CommandContext } from "../command_handler.ts";
import { errorToString } from "../common.ts";
import { ExecuteResult } from "../result.ts";

export function unsetCommand(context: CommandContext): ExecuteResult | Promise<ExecuteResult> {
Expand All @@ -8,7 +9,7 @@ export function unsetCommand(context: CommandContext): ExecuteResult | Promise<E
changes: parseNames(context.args).map((name) => ({ kind: "unsetvar", name })),
};
} catch (err) {
return context.error(`unset: ${err?.message ?? err}`);
return context.error(`unset: ${errorToString(err)}`);
}
}

Expand Down
19 changes: 19 additions & 0 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,22 @@ export function abortSignalToPromise(signal: AbortSignal) {
promise,
};
}

const nodeENotEmpty = "ENOTEMPTY: ";
const nodeENOENT = "ENOENT: ";

export function errorToString(err: unknown) {
let message: string;
if (err instanceof Error) {
message = err.message;
} else {
message = String(err);
}
if (message.startsWith(nodeENotEmpty)) {
return message.slice(nodeENotEmpty.length);
} else if (message.startsWith(nodeENOENT)) {
return message.slice(nodeENOENT.length);
} else {
return message;
}
}
1 change: 1 addition & 0 deletions src/deps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export {
} from "https://deno.land/[email protected]/assert/mod.ts";
export { toWritableStream } from "https://deno.land/[email protected]/io/to_writable_stream.ts";
export { toReadableStream } from "https://deno.land/[email protected]/io/to_readable_stream.ts";
export { isNode } from "https://deno.land/x/[email protected]/mod.ts";

/**
* Creates a temporary directory, changes the cwd to this directory,
Expand Down
20 changes: 11 additions & 9 deletions src/runtimes/process.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@ export const spawnCommand: SpawnCommand = (path, options) => {
toNodeStdio(options.stderr),
],
});
const exitCode = new Promise<number>((resolve, reject) => {
child.on("exit", (code) => {
if (code == null && receivedSignal != null) {
resolve(getSignalAbortCode(receivedSignal) ?? 1);
} else {
resolve(code ?? 0);
}
});
const exitResolvers = Promise.withResolvers<number>();
child.on("exit", (code) => {
if (code == null && receivedSignal != null) {
exitResolvers.resolve(getSignalAbortCode(receivedSignal) ?? 1);
} else {
exitResolvers.resolve(code ?? 0);
}
});
child.on("error", (err) => {
exitResolvers.reject(err);
});
return {
getWritableStdin() {
Expand All @@ -45,7 +47,7 @@ export const spawnCommand: SpawnCommand = (path, options) => {
child.kill(signo as any);
},
waitExitCode() {
return exitCode;
return exitResolvers.promise;
},
async pipeStdoutTo(writer: ShellPipeWriter, signal: AbortSignal) {
const stdout = child.stdout!;
Expand Down
Loading

0 comments on commit 1c08ee2

Please sign in to comment.