diff options
author | 2022-09-19 23:37:08 -0700 | |
---|---|---|
committer | 2022-09-19 23:37:08 -0700 | |
commit | da7b648971ef0f3077d4b8230d4cf2fcc1bb7719 (patch) | |
tree | 41fcb9e04289ad1eb1a48ef9333224a4eb88ff31 | |
parent | 8b7f43f8553eb0f012b7507ff1d2025bc646cc1c (diff) | |
download | bun-da7b648971ef0f3077d4b8230d4cf2fcc1bb7719.tar.gz bun-da7b648971ef0f3077d4b8230d4cf2fcc1bb7719.tar.zst bun-da7b648971ef0f3077d4b8230d4cf2fcc1bb7719.zip |
Pass through arguments unmodified after `bun run <script>` or `bun <script>`
Fixes https://github.com/oven-sh/bun/issues/231
-rw-r--r-- | src/bun_js.zig | 3 | ||||
-rw-r--r-- | src/cli.zig | 6 | ||||
-rw-r--r-- | src/cli/run_command.zig | 47 | ||||
-rw-r--r-- | src/deps/zig-clap/clap.zig | 8 | ||||
-rw-r--r-- | src/deps/zig-clap/clap/args.zig | 2 | ||||
-rw-r--r-- | src/deps/zig-clap/clap/comptime.zig | 25 |
6 files changed, 42 insertions, 49 deletions
diff --git a/src/bun_js.zig b/src/bun_js.zig index 87b618309..118cf00f9 100644 --- a/src/bun_js.zig +++ b/src/bun_js.zig @@ -57,10 +57,9 @@ pub const Run = struct { .ctx = ctx, .entry_path = entry_path, }; + run.vm.argv = ctx.passthrough; run.vm.arena = &run.arena; - run.vm.argv = ctx.positionals; - if (ctx.debug.macros) |macros| { run.vm.bundler.options.macro_remap = macros; } diff --git a/src/cli.zig b/src/cli.zig index 013b45f31..23082e2ae 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -327,6 +327,10 @@ pub const Arguments = struct { var args = clap.parse(clap.Help, params_to_use, .{ .diagnostic = &diag, .allocator = allocator, + .stop_after_positional_at = if (cmd == .RunCommand) 2 else if (cmd == .AutoCommand) + 1 + else + 0, }) catch |err| { // Report useful error and exit clap.help(Output.errorWriter(), params_to_use) catch {}; @@ -399,6 +403,7 @@ pub const Arguments = struct { opts.generate_node_module_bundle = cmd == .BunCommand; opts.inject = args.options("--inject"); opts.extension_order = args.options("--extension-order"); + ctx.passthrough = args.remaining(); opts.no_summary = args.flag("--no-summary"); opts.disable_hmr = args.flag("--disable-hmr"); @@ -789,6 +794,7 @@ pub const Command = struct { log: *logger.Log, allocator: std.mem.Allocator, positionals: []const string = &[_]string{}, + passthrough: []const string = &[_]string{}, install: ?*Api.BunInstall = null, debug: DebugOptions = DebugOptions{}, diff --git a/src/cli/run_command.zig b/src/cli/run_command.zig index c4653e853..6b5946764 100644 --- a/src/cli/run_command.zig +++ b/src/cli/run_command.zig @@ -231,7 +231,8 @@ pub const RunCommand = struct { var combined_script_buf = try allocator.alloc(u8, combined_script_len); std.mem.copy(u8, combined_script_buf, script); var remaining_script_buf = combined_script_buf[script.len..]; - for (passthrough) |p| { + for (passthrough) |part| { + var p = part; remaining_script_buf[0] = ' '; std.mem.copy(u8, remaining_script_buf[1..], p); remaining_script_buf = remaining_script_buf[p.len + 1 ..]; @@ -715,49 +716,7 @@ pub const RunCommand = struct { script_name_to_search = positionals[0]; } - var passthrough: []const string = &[_]string{}; - - var passthrough_list = std.ArrayList(string).init(ctx.allocator); - if (script_name_to_search.len > 0) { - get_passthrough: { - - // If they explicitly pass "--", that means they want everything after that to be passed through. - for (std.os.argv) |argv, i| { - if (strings.eqlComptime(std.mem.span(argv), "--")) { - if (std.os.argv.len > i + 1) { - var count: usize = 0; - for (std.os.argv[i + 1 ..]) |_| { - count += 1; - } - try passthrough_list.ensureTotalCapacity(count); - - for (std.os.argv[i + 1 ..]) |arg| { - passthrough_list.appendAssumeCapacity(std.mem.span(arg)); - } - - passthrough = passthrough_list.toOwnedSlice(); - break :get_passthrough; - } - } - } - - // If they do not pass "--", assume they want everything after the script name to be passed through. - for (std.os.argv) |argv, i| { - if (strings.eql(std.mem.span(argv), script_name_to_search)) { - if (std.os.argv.len > i + 1) { - try passthrough_list.ensureTotalCapacity(std.os.argv[i + 1 ..].len); - - for (std.os.argv[i + 1 ..]) |arg| { - passthrough_list.appendAssumeCapacity(std.mem.span(arg)); - } - - passthrough = passthrough_list.toOwnedSlice(); - break :get_passthrough; - } - } - } - } - } + const passthrough = ctx.passthrough; if (comptime log_errors) { if (script_name_to_search.len > 0) { diff --git a/src/deps/zig-clap/clap.zig b/src/deps/zig-clap/clap.zig index 6a49f6a15..eb1a5e452 100644 --- a/src/deps/zig-clap/clap.zig +++ b/src/deps/zig-clap/clap.zig @@ -265,6 +265,10 @@ pub fn Args(comptime Id: type, comptime params: []const Param(Id)) type { return a.clap.positionals(); } + pub fn remaining(a: @This()) []const []const u8 { + return a.clap.remaining(); + } + pub fn hasFlag(comptime name: []const u8) bool { return ComptimeClap(Id, params).hasFlag(name); } @@ -280,6 +284,7 @@ pub const ParseOptions = struct { /// is fine, as it wraps it in an arena) allocator: mem.Allocator = heap.page_allocator, diagnostic: ?*Diagnostic = null, + stop_after_positional_at: usize = 0, }; /// Same as `parseEx` but uses the `args.OsIterator` by default. @@ -288,7 +293,7 @@ pub fn parse( comptime params: []const Param(Id), opt: ParseOptions, ) !Args(Id, params) { - var iter = try args.OsIterator.init(opt.allocator); + var iter = args.OsIterator.init(opt.allocator); var res = Args(Id, params){ .arena = iter.arena, .exe_arg = iter.exe_arg, @@ -300,6 +305,7 @@ pub fn parse( res.clap = try parseEx(Id, params, &iter, .{ .allocator = res.arena.allocator(), .diagnostic = opt.diagnostic, + .stop_after_positional_at = opt.stop_after_positional_at, }); return res; } diff --git a/src/deps/zig-clap/clap/args.zig b/src/deps/zig-clap/clap/args.zig index 6f98e33a6..b5f79889f 100644 --- a/src/deps/zig-clap/clap/args.zig +++ b/src/deps/zig-clap/clap/args.zig @@ -56,7 +56,7 @@ pub const OsIterator = struct { /// return an error when we have no exe. exe_arg: ?[:0]const u8, - pub fn init(allocator: mem.Allocator) Error!OsIterator { + pub fn init(allocator: mem.Allocator) OsIterator { var res = OsIterator{ .arena = heap.ArenaAllocator.init(allocator), .args = process.args(), diff --git a/src/deps/zig-clap/clap/comptime.zig b/src/deps/zig-clap/clap/comptime.zig index 9631c9ca7..8bcb91cd3 100644 --- a/src/deps/zig-clap/clap/comptime.zig +++ b/src/deps/zig-clap/clap/comptime.zig @@ -44,6 +44,7 @@ pub fn ComptimeClap( multi_options: [multi_options][]const []const u8, flags: [flags]bool, pos: []const []const u8, + passthrough_positionals: []const []const u8, allocator: mem.Allocator, pub fn parse(iter: anytype, opt: clap.ParseOptions) !@This() { @@ -54,6 +55,7 @@ pub fn ComptimeClap( } var pos = std.ArrayList([]const u8).init(allocator); + var passthrough_positionals = std.ArrayList([]const u8).init(allocator); var res = @This(){ .single_options = [_]?[]const u8{null} ** single_options, @@ -61,16 +63,33 @@ pub fn ComptimeClap( .flags = [_]bool{false} ** flags, .pos = undefined, .allocator = allocator, + .passthrough_positionals = undefined, }; var stream = clap.StreamingClap(usize, @typeInfo(@TypeOf(iter)).Pointer.child){ .params = converted_params, .iter = iter, }; + while (try stream.next()) |arg| { const param = arg.param; if (param.names.long == null and param.names.short == null) { try pos.append(arg.value.?); + if (opt.stop_after_positional_at > 0 and pos.items.len >= opt.stop_after_positional_at) { + const bun = @import("../../../global.zig"); + if (comptime bun.Environment.isWindows) @compileError( + "TODO: implement stop_after_positional_at on windows", + ); + + const remaining_ = std.os.argv[@minimum(std.os.argv.len, stream.iter.args.inner.index)..]; + try passthrough_positionals.ensureTotalCapacityPrecise(remaining_.len); + + for (remaining_) |arg_| { + // use bun.span due to the optimization for long strings + passthrough_positionals.appendAssumeCapacity(bun.span(arg_)); + } + break; + } } else if (param.takes_value == .one or param.takes_value == .one_optional) { debug.assert(res.single_options.len != 0); if (res.single_options.len != 0) @@ -89,7 +108,7 @@ pub fn ComptimeClap( for (multis) |*multi, i| res.multi_options[i] = multi.toOwnedSlice(); res.pos = pos.toOwnedSlice(); - + res.passthrough_positionals = passthrough_positionals.toOwnedSlice(); return res; } @@ -130,6 +149,10 @@ pub fn ComptimeClap( return parser.pos; } + pub fn remaining(parser: @This()) []const []const u8 { + return parser.passthrough_positionals; + } + pub fn hasFlag(comptime name: []const u8) bool { comptime { for (converted_params) |param| { |