diff --git a/.prettierignore b/.prettierignore index 6347a9bd76..d7360d9d2f 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,5 +2,6 @@ src/bun.js/WebKit src/deps test/snapshots test/js/deno +test/node.js src/react-refresh.js *.min.js diff --git a/src/cli.zig b/src/cli.zig index 8f27ddb1d1..a34cdb23f6 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -208,9 +208,8 @@ pub const Arguments = struct { pub const run_params = run_only_params ++ runtime_params_ ++ transpiler_params_ ++ base_params_; const bunx_commands = [_]ParamType{ - clap.parseParam("--silent Don't print the script command") catch unreachable, clap.parseParam("-b, --bun Force a script or package to use Bun's runtime instead of Node.js (via symlinking node)") catch unreachable, - }; + } ++ auto_only_params; const build_only_params = [_]ParamType{ clap.parseParam("--compile Generate a standalone Bun executable containing your bundled code") catch unreachable, @@ -251,18 +250,6 @@ pub const Arguments = struct { }; pub const test_params = test_only_params ++ runtime_params_ ++ transpiler_params_ ++ base_params_; - fn printVersionAndExit() noreturn { - @setCold(true); - Output.writer().writeAll(Global.package_json_version ++ "\n") catch {}; - Global.exit(0); - } - - fn printRevisionAndExit() noreturn { - @setCold(true); - Output.writer().writeAll(Global.package_json_version_with_revision ++ "\n") catch {}; - Global.exit(0); - } - pub fn loadConfigPath(allocator: std.mem.Allocator, auto_loaded: bool, config_path: [:0]const u8, ctx: Command.Context, comptime cmd: Command.Tag) !void { var config_file = switch (bun.sys.openA(config_path, std.os.O.RDONLY, 0)) { .result => |fd| fd.asFile(), @@ -2341,3 +2328,15 @@ pub const Command = struct { }); }; }; + +pub fn printVersionAndExit() noreturn { + @setCold(true); + Output.writer().writeAll(Global.package_json_version ++ "\n") catch {}; + Global.exit(0); +} + +pub fn printRevisionAndExit() noreturn { + @setCold(true); + Output.writer().writeAll(Global.package_json_version_with_revision ++ "\n") catch {}; + Global.exit(0); +} diff --git a/src/cli/bunx_command.zig b/src/cli/bunx_command.zig index 34558a1b6a..f0041dbd98 100644 --- a/src/cli/bunx_command.zig +++ b/src/cli/bunx_command.zig @@ -9,7 +9,8 @@ const stringZ = bun.stringZ; const default_allocator = bun.default_allocator; const C = bun.C; const std = @import("std"); -const Command = @import("../cli.zig").Command; +const cli = @import("../cli.zig"); +const Command = cli.Command; const Run = @import("./run_command.zig").RunCommand; const debug = Output.scoped(.bunx, false); @@ -220,6 +221,8 @@ pub const BunxCommand = struct { var maybe_package_name: ?string = null; var verbose_install = false; var silent_install = false; + var has_version = false; + var has_revision = false; { var found_subcommand_name = false; @@ -230,7 +233,11 @@ pub const BunxCommand = struct { } if (positional.len > 0 and positional[0] == '-') { - if (strings.eqlComptime(positional, "--verbose")) { + if (strings.eqlComptime(positional, "--version") or strings.eqlComptime(positional, "-v")) { + has_version = true; + } else if (strings.eqlComptime(positional, "--revision")) { + has_revision = true; + } else if (strings.eqlComptime(positional, "--verbose")) { verbose_install = true; } else if (strings.eqlComptime(positional, "--silent")) { silent_install = true; @@ -249,7 +256,13 @@ pub const BunxCommand = struct { // check if package_name_for_update_request is empty string or " " if (maybe_package_name == null or maybe_package_name.?.len == 0) { - exitWithUsage(); + if (has_revision) { + cli.printRevisionAndExit(); + } else if (has_version) { + cli.printVersionAndExit(); + } else { + exitWithUsage(); + } } const package_name = maybe_package_name.?; diff --git a/src/symbols.txt b/src/symbols.txt index 1d047fe7e2..157c0c5157 100644 --- a/src/symbols.txt +++ b/src/symbols.txt @@ -152,4 +152,4 @@ __ZN2v87Isolate10GetCurrentEv __ZN2v87Isolate13TryGetCurrentEv __ZN2v87Isolate17GetCurrentContextEv __ZN4node25AddEnvironmentCleanupHookEPN2v87IsolateEPFvPvES3_ -__ZN4node28RemoveEnvironmentCleanupHookEPN2v87IsolateEPFvPvES3_ \ No newline at end of file +__ZN4node28RemoveEnvironmentCleanupHookEPN2v87IsolateEPFvPvES3_ diff --git a/test/cli/install/bunx.test.ts b/test/cli/install/bunx.test.ts index fc5ea2e83b..e5e82bee0a 100644 --- a/test/cli/install/bunx.test.ts +++ b/test/cli/install/bunx.test.ts @@ -306,3 +306,70 @@ it("should work for github repository with committish", async () => { expect(out.trim()).toContain("hello bun!"); expect(exited).toBe(0); }); + +it.each(["--version", "-v"])("should print the version using %s and exit", async flag => { + const subprocess = spawn({ + cmd: [bunExe(), "x", flag], + cwd: x_dir, + stdout: "pipe", + stdin: "inherit", + stderr: "pipe", + env, + }); + + let [err, out, exited] = await Promise.all([ + new Response(subprocess.stderr).text(), + new Response(subprocess.stdout).text(), + subprocess.exited, + ]); + + expect(err).not.toContain("error:"); + expect(err).not.toContain("panic:"); + expect(out.trim()).toContain(Bun.version); + expect(exited).toBe(0); +}); + +it("should print the revision and exit", async () => { + const subprocess = spawn({ + cmd: [bunExe(), "x", "--revision"], + cwd: x_dir, + stdout: "pipe", + stdin: "inherit", + stderr: "pipe", + env, + }); + + let [err, out, exited] = await Promise.all([ + new Response(subprocess.stderr).text(), + new Response(subprocess.stdout).text(), + subprocess.exited, + ]); + + expect(err).not.toContain("error:"); + expect(err).not.toContain("panic:"); + expect(out.trim()).toContain(Bun.version); + expect(out.trim()).toContain(Bun.revision.slice(0, 7)); + expect(exited).toBe(0); +}); + +it("should pass --version to the package if specified", async () => { + const subprocess = spawn({ + cmd: [bunExe(), "x", "esbuild", "--version"], + cwd: x_dir, + stdout: "pipe", + stdin: "inherit", + stderr: "pipe", + env, + }); + + let [err, out, exited] = await Promise.all([ + new Response(subprocess.stderr).text(), + new Response(subprocess.stdout).text(), + subprocess.exited, + ]); + + expect(err).not.toContain("error:"); + expect(err).not.toContain("panic:"); + expect(out.trim()).not.toContain(Bun.version); + expect(exited).toBe(0); +});