aboutsummaryrefslogtreecommitdiff
path: root/src/cli/bunx_command.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/cli/bunx_command.zig')
-rw-r--r--src/cli/bunx_command.zig193
1 files changed, 109 insertions, 84 deletions
diff --git a/src/cli/bunx_command.zig b/src/cli/bunx_command.zig
index f721eb98b..e7f35d10d 100644
--- a/src/cli/bunx_command.zig
+++ b/src/cli/bunx_command.zig
@@ -23,7 +23,8 @@ pub const BunxCommand = struct {
var new_str = try allocator.allocSentinel(u8, input.len + prefixLength, 0);
if (input[0] == '@') {
- if (strings.indexAnyComptime(input, "/")) |index| {
+ if (strings.indexAnyComptime(input, "/")) |slashIndex| {
+ const index = slashIndex + 1;
@memcpy(new_str[0..index], input[0..index]);
@memcpy(new_str[index .. index + prefixLength], "create-");
@memcpy(new_str[index + prefixLength ..], input[index..]);
@@ -159,7 +160,8 @@ pub const BunxCommand = struct {
Global.exit(1);
}
- pub fn exec(ctx: bun.CLI.Command.Context, argv: [][*:0]const u8) !void {
+ pub fn exec(ctx_: bun.CLI.Command.Context, argv: [][*:0]const u8) !void {
+ var ctx = ctx_;
var requests_buf = bun.PackageManager.UpdateRequest.Array.init(0) catch unreachable;
var run_in_bun = ctx.debug.run_in_bun;
@@ -220,6 +222,9 @@ pub const BunxCommand = struct {
Global.exit(1);
}
+ // Don't log stuff
+ ctx.debug.silent = true;
+
var update_request = update_requests[0];
// if you type "tsc" and TypeScript is not installed:
@@ -231,6 +236,8 @@ pub const BunxCommand = struct {
const initial_bin_name = if (strings.eqlComptime(update_request.name, "typescript"))
"tsc"
+ else if (update_request.version.tag == .github)
+ update_request.version.value.github.repo.slice(update_request.version_buf)
else if (strings.lastIndexOfChar(update_request.name, '/')) |index|
update_request.name[index + 1 ..]
else
@@ -257,94 +264,123 @@ pub const BunxCommand = struct {
else
update_request.version.literal.slice(update_request.version_buf);
+ const package_fmt = brk: {
+ if (update_request.version.tag == .github) {
+ break :brk update_request.version.literal.slice(update_request.version_buf);
+ }
+
+ break :brk try std.fmt.allocPrint(
+ ctx.allocator,
+ "{s}@{s}",
+ .{
+ update_request.name,
+ display_version,
+ },
+ );
+ };
+
const PATH_FOR_BIN_DIRS = PATH;
if (PATH.len > 0) {
PATH = try std.fmt.allocPrint(
ctx.allocator,
- bun.fs.FileSystem.RealFS.PLATFORM_TMP_DIR ++ "/{s}@{s}--bunx/node_modules/.bin:{s}",
- .{ update_request.name, display_version, PATH },
+ bun.fs.FileSystem.RealFS.PLATFORM_TMP_DIR ++ "/{s}--bunx/node_modules/.bin:{s}",
+ .{ package_fmt, PATH },
);
} else {
PATH = try std.fmt.allocPrint(
ctx.allocator,
- bun.fs.FileSystem.RealFS.PLATFORM_TMP_DIR ++ "/{s}@{s}--bunx/node_modules/.bin",
- .{ update_request.name, display_version },
+ bun.fs.FileSystem.RealFS.PLATFORM_TMP_DIR ++ "/{s}--bunx/node_modules/.bin",
+ .{package_fmt},
);
}
try this_bundler.env.map.put("PATH", PATH);
- const bunx_cache_dir = PATH[0 .. bun.fs.FileSystem.RealFS.PLATFORM_TMP_DIR.len + "/--bunx@".len + update_request.name.len + display_version.len];
+ const bunx_cache_dir = PATH[0 .. bun.fs.FileSystem.RealFS.PLATFORM_TMP_DIR.len + "/--bunx".len + package_fmt.len];
var absolute_in_cache_dir_buf: [bun.MAX_PATH_BYTES]u8 = undefined;
var absolute_in_cache_dir = std.fmt.bufPrint(&absolute_in_cache_dir_buf, "/{s}/node_modules/.bin/{s}", .{ bunx_cache_dir, initial_bin_name }) catch unreachable;
const passthrough = passthrough_list.items;
- // Similar to "npx":
- //
- // 1. Try the bin in the current node_modules and then we try the bin in the global cache
- if (bun.which(
- &path_buf,
- PATH_FOR_BIN_DIRS,
- this_bundler.fs.top_level_dir,
- initial_bin_name,
- ) orelse bun.which(
- &path_buf,
- bunx_cache_dir,
- this_bundler.fs.top_level_dir,
- absolute_in_cache_dir,
- )) |destination| {
- const out = bun.asByteSlice(destination);
- _ = try Run.runBinary(
- ctx,
- try this_bundler.fs.dirname_store.append(@TypeOf(out), out),
- this_bundler.fs.top_level_dir,
- this_bundler.env,
- passthrough,
- );
- // we are done!
- Global.exit(0);
- }
+ if (update_request.version.literal.isEmpty() or update_request.version.tag != .dist_tag) {
+ var destination_: ?[:0]const u8 = null;
- // 2. The "bin" is possibly not the same as the package name, so we load the package.json to figure out what "bin" to use
- if (getBinName(&this_bundler, bun.fdcast(root_dir_info.getFileDescriptor()), bunx_cache_dir, initial_bin_name)) |package_name_for_bin| {
- // if we check the bin name and its actually the same, we don't need to check $PATH here again
- if (!strings.eqlLong(package_name_for_bin, initial_bin_name, true)) {
- absolute_in_cache_dir = std.fmt.bufPrint(&absolute_in_cache_dir_buf, "{s}/node_modules/.bin/{s}", .{ bunx_cache_dir, package_name_for_bin }) catch unreachable;
-
- if (bun.which(
+ // Only use the system-installed version if there is no version specified
+ if (update_request.version.literal.isEmpty()) {
+ destination_ = bun.which(
&path_buf,
PATH_FOR_BIN_DIRS,
this_bundler.fs.top_level_dir,
- package_name_for_bin,
- ) orelse bun.which(
- &path_buf,
- bunx_cache_dir,
+ initial_bin_name,
+ );
+ }
+
+ // Similar to "npx":
+ //
+ // 1. Try the bin in the current node_modules and then we try the bin in the global cache
+ if (destination_ orelse bun.which(
+ &path_buf,
+ bunx_cache_dir,
+ this_bundler.fs.top_level_dir,
+ absolute_in_cache_dir,
+ )) |destination| {
+ const out = bun.asByteSlice(destination);
+ _ = try Run.runBinary(
+ ctx,
+ try this_bundler.fs.dirname_store.append(@TypeOf(out), out),
this_bundler.fs.top_level_dir,
- absolute_in_cache_dir,
- )) |destination| {
- const out = bun.asByteSlice(destination);
- _ = try Run.runBinary(
- ctx,
- try this_bundler.fs.dirname_store.append(@TypeOf(out), out),
+ this_bundler.env,
+ passthrough,
+ );
+ // we are done!
+ Global.exit(0);
+ }
+
+ // 2. The "bin" is possibly not the same as the package name, so we load the package.json to figure out what "bin" to use
+ if (getBinName(&this_bundler, bun.fdcast(root_dir_info.getFileDescriptor()), bunx_cache_dir, initial_bin_name)) |package_name_for_bin| {
+ // if we check the bin name and its actually the same, we don't need to check $PATH here again
+ if (!strings.eqlLong(package_name_for_bin, initial_bin_name, true)) {
+ absolute_in_cache_dir = std.fmt.bufPrint(&absolute_in_cache_dir_buf, "{s}/node_modules/.bin/{s}", .{ bunx_cache_dir, package_name_for_bin }) catch unreachable;
+
+ // Only use the system-installed version if there is no version specified
+ if (update_request.version.literal.isEmpty()) {
+ destination_ = bun.which(
+ &path_buf,
+ PATH_FOR_BIN_DIRS,
+ this_bundler.fs.top_level_dir,
+ package_name_for_bin,
+ );
+ }
+
+ if (destination_ orelse bun.which(
+ &path_buf,
+ bunx_cache_dir,
this_bundler.fs.top_level_dir,
- this_bundler.env,
- passthrough,
- );
- // we are done!
- Global.exit(0);
+ absolute_in_cache_dir,
+ )) |destination| {
+ const out = bun.asByteSlice(destination);
+ _ = try Run.runBinary(
+ ctx,
+ try this_bundler.fs.dirname_store.append(@TypeOf(out), out),
+ this_bundler.fs.top_level_dir,
+ this_bundler.env,
+ passthrough,
+ );
+ // we are done!
+ Global.exit(0);
+ }
+ }
+ } else |err| {
+ if (err == error.NoBinFound) {
+ Output.prettyErrorln("<r><red>error<r><d>:<r> could not determine executable to run for package <r><b>{s}<r>", .{update_request.name});
+ Global.exit(1);
}
- }
- } else |err| {
- if (err == error.NoBinFound) {
- Output.prettyErrorln("<r><red>error<r><d>:<r> could not determine executable to run for package <r><b>{s}<r>", .{update_request.name});
- Global.exit(1);
}
}
var bunx_install_dir_path = try std.fmt.allocPrint(
ctx.allocator,
- bun.fs.FileSystem.RealFS.PLATFORM_TMP_DIR ++ "/{s}@{s}--bunx",
- .{ update_request.name, display_version },
+ bun.fs.FileSystem.RealFS.PLATFORM_TMP_DIR ++ "/{s}--bunx",
+ .{package_fmt},
);
// TODO: fix this after zig upgrade
@@ -353,22 +389,22 @@ pub const BunxCommand = struct {
create_package_json: {
// create package.json, but only if it doesn't exist
- var package_json = bunx_install_dir.createFileZ("package.json", .{ .truncate = false }) catch break :create_package_json;
+ var package_json = bunx_install_dir.createFileZ("package.json", .{ .truncate = true }) catch break :create_package_json;
defer package_json.close();
package_json.writeAll("{}\n") catch {};
}
var args_buf = [_]string{
- try std.fs.selfExePathAlloc(ctx.allocator), "add", "--no-summary", try std.fmt.allocPrint(
- ctx.allocator,
- "{s}@{s}",
- .{
- update_request.name,
- display_version,
- },
- ),
+ try std.fs.selfExePathAlloc(ctx.allocator), "add", "--no-summary",
+ package_fmt,
+ // disable the manifest cache when a tag is specified
+ // so that @latest is fetched from the registry
+ "--no-cache",
};
- var child_process = std.ChildProcess.init(&args_buf, default_allocator);
+
+ const argv_to_use: []const string = args_buf[0 .. args_buf.len - @as(usize, @intFromBool(update_request.version.tag != .dist_tag))];
+
+ var child_process = std.ChildProcess.init(argv_to_use, default_allocator);
child_process.cwd = bunx_install_dir_path;
child_process.cwd_dir = bunx_install_dir;
const env_map = try this_bundler.env.map.cloneToEnvMap(ctx.allocator);
@@ -400,14 +436,10 @@ pub const BunxCommand = struct {
// Similar to "npx":
//
- // 1. Try the bin in the current node_modules and then we try the bin in the global cache
+ // 1. Try the bin in the global cache
+ // Do not try $PATH because we already checked it above if we should
if (bun.which(
&path_buf,
- PATH_FOR_BIN_DIRS,
- this_bundler.fs.top_level_dir,
- initial_bin_name,
- ) orelse bun.which(
- &path_buf,
bunx_cache_dir,
this_bundler.fs.top_level_dir,
absolute_in_cache_dir,
@@ -426,18 +458,11 @@ pub const BunxCommand = struct {
// 2. The "bin" is possibly not the same as the package name, so we load the package.json to figure out what "bin" to use
if (getBinNameFromTempDirectory(&this_bundler, bunx_cache_dir, update_request.name)) |package_name_for_bin| {
-
- // if we check the bin name and its actually the same, we don't need to check $PATH here again
if (!strings.eqlLong(package_name_for_bin, initial_bin_name, true)) {
absolute_in_cache_dir = std.fmt.bufPrint(&absolute_in_cache_dir_buf, "{s}/node_modules/.bin/{s}", .{ bunx_cache_dir, package_name_for_bin }) catch unreachable;
if (bun.which(
&path_buf,
- PATH_FOR_BIN_DIRS,
- this_bundler.fs.top_level_dir,
- package_name_for_bin,
- ) orelse bun.which(
- &path_buf,
bunx_cache_dir,
this_bundler.fs.top_level_dir,
absolute_in_cache_dir,