diff options
Diffstat (limited to 'src/cli/bunx_command.zig')
-rw-r--r-- | src/cli/bunx_command.zig | 193 |
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, |