aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-09-19 23:37:08 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-09-19 23:37:08 -0700
commitda7b648971ef0f3077d4b8230d4cf2fcc1bb7719 (patch)
tree41fcb9e04289ad1eb1a48ef9333224a4eb88ff31
parent8b7f43f8553eb0f012b7507ff1d2025bc646cc1c (diff)
downloadbun-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.zig3
-rw-r--r--src/cli.zig6
-rw-r--r--src/cli/run_command.zig47
-rw-r--r--src/deps/zig-clap/clap.zig8
-rw-r--r--src/deps/zig-clap/clap/args.zig2
-rw-r--r--src/deps/zig-clap/clap/comptime.zig25
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| {