mirror of
https://github.com/oven-sh/bun
synced 2026-02-16 05:42:43 +00:00
Pass through arguments unmodified after bun run <script> or bun <script>
Fixes https://github.com/oven-sh/bun/issues/231
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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{},
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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| {
|
||||
|
||||
Reference in New Issue
Block a user