aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Ashcon Partovi <ashcon@partovi.net> 2023-10-03 17:39:45 -0700
committerGravatar GitHub <noreply@github.com> 2023-10-03 17:39:45 -0700
commit9308e1bf09637a75d4c99ddd056addd7fbb00f6f (patch)
tree4e9f1c737269e5d0e308942cf8678494166b0956
parentaa8ccce952f5dfa91c84f282b5abbb184c17dfc2 (diff)
downloadbun-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.zig7
-rw-r--r--src/cli/run_command.zig4
-rw-r--r--test/cli/run/if-present.test.ts119
-rw-r--r--test/harness.ts2
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");