diff options
author | 2023-10-03 17:39:45 -0700 | |
---|---|---|
committer | 2023-10-03 17:39:45 -0700 | |
commit | 9308e1bf09637a75d4c99ddd056addd7fbb00f6f (patch) | |
tree | 4e9f1c737269e5d0e308942cf8678494166b0956 | |
parent | aa8ccce952f5dfa91c84f282b5abbb184c17dfc2 (diff) | |
download | bun-9308e1bf09637a75d4c99ddd056addd7fbb00f6f.tar.gz bun-9308e1bf09637a75d4c99ddd056addd7fbb00f6f.tar.zst bun-9308e1bf09637a75d4c99ddd056addd7fbb00f6f.zip |
Support `bun run --if-present` (#6248)
* Support --if-present
Closes #5670
* More robust tests, handle more cases
-rw-r--r-- | src/cli.zig | 7 | ||||
-rw-r--r-- | src/cli/run_command.zig | 4 | ||||
-rw-r--r-- | test/cli/run/if-present.test.ts | 119 | ||||
-rw-r--r-- | test/harness.ts | 2 |
4 files changed, 131 insertions, 1 deletions
diff --git a/src/cli.zig b/src/cli.zig index 9982e5e7f..a05fb3768 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -196,6 +196,7 @@ pub const Arguments = struct { clap.parseParam("--inspect <STR>? Activate Bun's Debugger") catch unreachable, clap.parseParam("--inspect-wait <STR>? Activate Bun's Debugger, wait for a connection before executing") catch unreachable, clap.parseParam("--inspect-brk <STR>? Activate Bun's Debugger, set breakpoint on first line of code and wait") catch unreachable, + clap.parseParam("--if-present Exit if the entrypoint does not exist") catch unreachable, clap.parseParam("<POS>... ") catch unreachable, }; @@ -538,6 +539,7 @@ pub const Arguments = struct { ctx.preloads = preloads; } + ctx.runtime_options.if_present = args.flag("--if-present"); ctx.runtime_options.smol = args.flag("--smol"); if (args.option("--inspect")) |inspect_flag| { ctx.runtime_options.debugger = if (inspect_flag.len == 0) @@ -1022,6 +1024,7 @@ pub const Command = struct { pub const RuntimeOptions = struct { smol: bool = false, debugger: Debugger = .{ .unspecified = {} }, + if_present: bool = false, }; pub const Context = struct { @@ -1666,6 +1669,10 @@ pub const Command = struct { Global.exit(1); } + if (ctx.runtime_options.if_present) { + return; + } + if (was_js_like) { Output.prettyErrorln("<r><red>error<r><d>:<r> module not found \"<b>{s}<r>\"", .{ ctx.positionals[0], diff --git a/src/cli/run_command.zig b/src/cli/run_command.zig index 1ef1342c0..19046e292 100644 --- a/src/cli/run_command.zig +++ b/src/cli/run_command.zig @@ -1160,6 +1160,10 @@ pub const RunCommand = struct { } } + if (ctx.runtime_options.if_present) { + return true; + } + if (comptime log_errors) { Output.prettyError("<r><red>error<r><d>:<r> missing script \"<b>{s}<r>\"\n", .{script_name_to_search}); Global.exit(1); diff --git a/test/cli/run/if-present.test.ts b/test/cli/run/if-present.test.ts new file mode 100644 index 000000000..120970b46 --- /dev/null +++ b/test/cli/run/if-present.test.ts @@ -0,0 +1,119 @@ +import { describe, test, expect, beforeAll } from "bun:test"; +import { spawnSync } from "bun"; +import { bunEnv, bunExe, tempDirWithFiles } from "harness"; + +let cwd: string; + +beforeAll(() => { + cwd = tempDirWithFiles("--if-present", { + "present.js": "console.log('Here!');", + "package.json": JSON.stringify({ + "name": "present", + "scripts": { + "present": "echo 'Here!'", + }, + }), + }); +}); + +describe("bun", () => { + test("should error with missing script", () => { + const { exitCode, stdout, stderr } = spawnSync({ + cwd, + cmd: [bunExe(), "notpresent"], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(stdout.toString()).toBeEmpty(); + expect(stderr.toString()).toMatch(/script not found/); + expect(exitCode).toBe(1); + }); + test("should error with missing module", () => { + const { exitCode, stdout, stderr } = spawnSync({ + cwd, + cmd: [bunExe(), "./notpresent.js"], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(stdout.toString()).toBeEmpty(); + expect(stderr.toString()).toMatch(/module not found/); + expect(exitCode).toBe(1); + }); + test("should error with missing file", () => { + const { exitCode, stdout, stderr } = spawnSync({ + cwd, + cmd: [bunExe(), "/path/to/notpresent.txt"], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(stdout.toString()).toBeEmpty(); + expect(stderr.toString()).toMatch(/file not found/); + expect(exitCode).toBe(1); + }); +}); + +describe("bun --if-present", () => { + test("should not error with missing script", () => { + const { exitCode, stdout, stderr } = spawnSync({ + cwd, + cmd: [bunExe(), "--if-present", "notpresent"], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(stdout.toString()).toBeEmpty(); + expect(stderr.toString()).toBeEmpty(); + expect(exitCode).toBe(0); + }); + test("should not error with missing module", () => { + const { exitCode, stdout, stderr } = spawnSync({ + cwd, + cmd: [bunExe(), "--if-present", "./notpresent.js"], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(stdout.toString()).toBeEmpty(); + expect(stderr.toString()).toBeEmpty(); + expect(exitCode).toBe(0); + }); + test("should not error with missing file", () => { + const { exitCode, stdout, stderr } = spawnSync({ + cwd, + cmd: [bunExe(), "--if-present", "/path/to/notpresent.txt"], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(stdout.toString()).toBeEmpty(); + expect(stderr.toString()).toBeEmpty(); + expect(exitCode).toBe(0); + }); + test("should run present script", () => { + const { exitCode, stdout, stderr } = spawnSync({ + cwd, + cmd: [bunExe(), "run", "present"], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(stdout.toString()).toMatch(/Here!/); + expect(stderr.toString()).not.toBeEmpty(); + expect(exitCode).toBe(0); + }); + test("should run present module", () => { + const { exitCode, stdout, stderr } = spawnSync({ + cwd, + cmd: [bunExe(), "run", "present.js"], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + expect(stdout.toString()).toMatch(/Here!/); + expect(stderr.toString()).toBeEmpty(); + expect(exitCode).toBe(0); + }); +}); diff --git a/test/harness.ts b/test/harness.ts index 16d04c1b4..77b4b4f43 100644 --- a/test/harness.ts +++ b/test/harness.ts @@ -84,7 +84,7 @@ export function hideFromStackTrace(block: CallableFunction) { }); } -export function tempDirWithFiles(basename: string, files: Record<string, string | Record<string, string>>) { +export function tempDirWithFiles(basename: string, files: Record<string, string | Record<string, string>>): string { var fs = require("fs"); var path = require("path"); var { tmpdir } = require("os"); |