diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cli.zig | 14 | ||||
-rw-r--r-- | src/cli/install.sh | 138 | ||||
-rw-r--r-- | src/cli/run_command.zig | 2 | ||||
-rw-r--r-- | src/cli/upgrade_command.zig | 495 | ||||
-rw-r--r-- | src/fs.zig | 2 | ||||
m--------- | src/javascript/jsc/WebKit | 0 |
6 files changed, 647 insertions, 4 deletions
diff --git a/src/cli.zig b/src/cli.zig index e0ffc1235..9748945e8 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -35,7 +35,7 @@ const BuildCommand = @import("./cli/build_command.zig").BuildCommand; const CreateCommand = @import("./cli/create_command.zig").CreateCommand; const CreateListExamplesCommand = @import("./cli/create_command.zig").CreateListExamplesCommand; const RunCommand = @import("./cli/run_command.zig").RunCommand; - +const UpgradeCommand = @import("./cli/upgrade_command.zig").UpgradeCommand; var start_time: i128 = undefined; pub const Cli = struct { @@ -459,7 +459,8 @@ const HelpCommand = struct { \\> <r> <b><magenta>bun <r><d> ./a.ts ./b.jsx<r> Bundle dependencies of input files into a <r><magenta>.bun<r> \\> <r> <b><green>run <r><d> test <r> Run a package.json script or executable<r> \\> <r> <b><cyan>create <r><d>next ./app<r> Start a new project from a template <d>(shorthand: c)<r> - \\> <r> <b><blue>discord <r> Open Bun's Discord server + \\> <r> <b><blue>upgrade <r> Get the latest version of Bun + \\> <r> <b><d>discord <r> Open Bun's Discord server \\> <r> <b><d>help <r> Print this help menu \\ ; @@ -477,6 +478,7 @@ const HelpCommand = struct { \\> <r> <b><magenta>bun <r><d> ./a.ts ./b.jsx<r> Bundle dependencies of input files into a <r><magenta>.bun<r> \\> <r> <green>run <r><d> ./a.ts <r> Run a JavaScript-like file with Bun.js \\> <r> <b><blue>discord<r> Open Bun's Discord server + \\> <r> <b><blue>upgrade <r> Get the latest version of Bun \\> <r> <b><d>help <r> Print this help menu \\ ; @@ -578,6 +580,7 @@ pub const Command = struct { RootCommandMatcher.case("init") => .InitCommand, RootCommandMatcher.case("bun") => .BunCommand, RootCommandMatcher.case("discord") => .DiscordCommand, + RootCommandMatcher.case("upgrade") => .UpgradeCommand, RootCommandMatcher.case("c"), RootCommandMatcher.case("create") => .CreateCommand, RootCommandMatcher.case("b"), RootCommandMatcher.case("build") => .BuildCommand, @@ -594,6 +597,7 @@ pub const Command = struct { RootCommandMatcher.case("discord") => .DiscordCommand, RootCommandMatcher.case("d"), RootCommandMatcher.case("dev") => .DevCommand, RootCommandMatcher.case("c"), RootCommandMatcher.case("create") => .CreateCommand, + RootCommandMatcher.case("upgrade") => .UpgradeCommand, RootCommandMatcher.case("help") => .HelpCommand, else => .AutoCommand, @@ -656,6 +660,11 @@ pub const Command = struct { _ = try RunCommand.exec(ctx, false, true); } }, + .UpgradeCommand => { + const ctx = try Command.Context.create(allocator, log, .UpgradeCommand); + try UpgradeCommand.exec(ctx); + return; + }, .AutoCommand => { var ctx = Command.Context.create(allocator, log, .AutoCommand) catch |e| { switch (e) { @@ -702,5 +711,6 @@ pub const Command = struct { AutoCommand, HelpCommand, CreateCommand, + UpgradeCommand, }; }; diff --git a/src/cli/install.sh b/src/cli/install.sh new file mode 100644 index 000000000..e771ba28d --- /dev/null +++ b/src/cli/install.sh @@ -0,0 +1,138 @@ +#!/bin/bash + + +# Reset +Color_Off='' # Text Reset + +# Regular Colors +Black='' # Black +Red='' # Red +Green='' # Green +Yellow='' # Yellow +Blue='' # Blue +Purple='' # Purple +Cyan='' # Cyan +White='' # White + +# Bold +BBlack='' # Black +BRed='' # Red +BGreen='' # Green +BYellow='' # Yellow +BBlue='' # Blue +BPurple='' # Purple +BCyan='' # Cyan +BWhite='' # White + +if test -t 1; then +# Reset +Color_Off='\033[0m' # Text Reset + +# Regular Colors +Black='\033[0;30m' # Black +Red='\033[0;31m' # Red +Green='\033[0;32m' # Green +Yellow='\033[0;33m' # Yellow +Blue='\033[0;34m' # Blue +Purple='\033[0;35m' # Purple +Cyan='\033[0;36m' # Cyan +White='\033[0;37m' # White + +# Bold +BBlack='\033[1;30m' # Black +BRed='\033[1;31m' # Red +BGreen='\033[1;32m' # Green +BYellow='\033[1;33m' # Yellow +BBlue='\033[1;34m' # Blue +BPurple='\033[1;35m' # Purple +BCyan='\033[1;36m' # Cyan +BWhite='\033[1;37m' # White +fi + + +if ! command -v unzip >/dev/null; then + echo -e "${Red}error${Color_Off}: unzip is required to install Bun (see: https://github.com/Jarred-Sumner/bun#unzip-is-required)." 1>&2 + exit 1 +fi + +if [ "$OS" = "Windows_NT" ]; then + echo "error: Please install Bun using Windows Subsystem for Linux." + exit 1 +else + case $(uname -sm) in + "Darwin x86_64") target="darwin-x64" ;; + "Darwin arm64") target="darwin-aarch64" ;; + *) target="linux-x64" ;; + esac +fi + +github_repo="https://github.com/Jarred-Sumner/bun-releases-for-updater" + +if [ $# -eq 0 ]; then + bun_uri="$github_repo/releases/latest/download/bun-${target}.zip" +else + bun_uri="$github_repo/releases/download/${1}/bun-${target}.zip" +fi + +bun_install="${BUN_INSTALL:-$HOME/.bun}" +bin_dir="$bun_install/bin" +exe="$bin_dir/bun" + +if [ ! -d "$bin_dir" ]; then + mkdir -p "$bin_dir" +fi + +curl --fail --location --progress-bar --output "$exe.zip" "$bun_uri" + +if (( $? )); then + echo -e "${Red}error${Color_Off}: Failed to download Bun from $bun_uri" 1>&2 + exit 1 +fi +unzip -d "$bin_dir" -q -o "$exe.zip" +if (( $? )); then + echo -e "${Red}error${Color_Off}: Failed to extract Bun" 1>&2 + exit 1 +fi +mv "$bin_dir/bun-${target}/bun" "$exe" +if (( $? )); then + echo -e "${Red}error${Color_Off}: Failed to extract Bun" 1>&2 + exit 1 +fi +chmod +x "$exe" +if (( $? )); then + echo -e "${Red}error${Color_Off}: Failed to set permissions on bun executable." 1>&2 + exit 1 +fi +rmdir $bin_dir/bun-${target} +rm "$exe.zip" + +echo -e "${Green}Bun was installed successfully to ${BGreen}$exe$Color_Off" + +if command -v bun --version >/dev/null; then + echo "Run 'bun --help' to get started" + exit 0 +fi + +if test $(basename $SHELL) == "fish"; then + echo "" + echo "Manually add the directory to your \$HOME/.config/fish" + echo "" + echo -e " $BWhite set -Ux BUN_INSTALL \"$bun_install\"$Color_Off" + echo -e " $BWhite set -px --path PATH \"$bin_dir\"$Color_Off" +elif test $(basename $SHELL) == "zsh"; then + echo "" + echo "Manually add the directory to your \$HOME/.zshrc (or similar)" + echo "" + echo -e " $BWhite export BUN_INSTALL=\"$bun_install$Color_Off" + echo -e " $BWhite export PATH=\"\$BUN_INSTALL/bin:\$PATH\"$Color_Off" +else + echo "" + echo "Manually add the directory to your \$HOME/.bashrc (or similar)" + echo "" + echo -e " $BWhiteexport BUN_INSTALL=\"$bun_install\"$Color_Off" + echo -e " $BWhiteexport PATH=\"\$BUN_INSTALL/bin:\$PATH\"$Color_Off" +fi +echo "" +echo -e "To get started, run" +echo -e "$BWhite" +echo -e " bun --help$Color_Off"
\ No newline at end of file diff --git a/src/cli/run_command.zig b/src/cli/run_command.zig index 3a8039978..b2dc426ef 100644 --- a/src/cli/run_command.zig +++ b/src/cli/run_command.zig @@ -464,7 +464,7 @@ pub const RunCommand = struct { var display_name = package_json.name; if (display_name.len == 0) { - display_name = std.fs.path.basename(root_dir_info.getEntries().?.dir); + display_name = std.fs.path.basename(package_json.source.path.name.dir); } var iterator = scripts.iterator(); diff --git a/src/cli/upgrade_command.zig b/src/cli/upgrade_command.zig new file mode 100644 index 000000000..8dc83a037 --- /dev/null +++ b/src/cli/upgrade_command.zig @@ -0,0 +1,495 @@ +usingnamespace @import("../global.zig"); +const std = @import("std"); + +const lex = @import("../js_lexer.zig"); +const logger = @import("../logger.zig"); +const alloc = @import("../alloc.zig"); +const options = @import("../options.zig"); +const js_parser = @import("../js_parser.zig"); +const js_ast = @import("../js_ast.zig"); +const linker = @import("../linker.zig"); +usingnamespace @import("../ast/base.zig"); +usingnamespace @import("../defines.zig"); +const panicky = @import("../panic_handler.zig"); +const allocators = @import("../allocators.zig"); +const sync = @import(".././sync.zig"); +const Api = @import("../api/schema.zig").Api; +const resolve_path = @import("../resolver/resolve_path.zig"); +const configureTransformOptionsForBun = @import("../javascript/jsc/config.zig").configureTransformOptionsForBun; +const Command = @import("../cli.zig").Command; +const bundler = @import("../bundler.zig"); +const NodeModuleBundle = @import("../node_module_bundle.zig").NodeModuleBundle; +const fs = @import("../fs.zig"); +const URL = @import("../query_string_map.zig").URL; +const HTTPClient = @import("../http_client.zig"); +const ParseJSON = @import("../json_parser.zig").ParseJSON; +const Archive = @import("../libarchive/libarchive.zig").Archive; +const Zlib = @import("../zlib.zig"); +const JSPrinter = @import("../js_printer.zig"); +const DotEnv = @import("../env_loader.zig"); +const NPMClient = @import("../which_npm_client.zig").NPMClient; +const which = @import("../which.zig").which; +const clap = @import("clap"); +const Lock = @import("../lock.zig").Lock; +const Headers = @import("../javascript/jsc/webcore/response.zig").Headers; +const CopyFile = @import("../copy_file.zig"); + +pub var initialized_store = false; +pub fn initializeStore() void { + if (initialized_store) return; + initialized_store = true; + js_ast.Expr.Data.Store.create(default_allocator); + js_ast.Stmt.Data.Store.create(default_allocator); +} + +pub const Version = struct { + zip_url: string, + tag: string, + buf: MutableString, + size: u32 = 0, + + pub fn name(this: Version) ?string { + if (this.tag.len > "bun-v".len and strings.eqlComptime(this.tag[0.."bun-v".len], "bun-v")) { + return this.tag[("bun-v".len)..]; + } else { + return null; + } + } + + pub const platform_label = if (Environment.isMac) "darwin" else "linux"; + pub const arch_label = if (Environment.isAarch64) "aarch64" else "x64"; + pub const triplet = platform_label ++ "-" ++ arch_label; + pub const folder_name = "bun-" ++ triplet; + pub const zip_filename = folder_name ++ ".zip"; + + const current_version: string = "bun-v" ++ Global.package_json_version; + + pub fn isCurrent(this: Version) bool { + return strings.eqlComptime(this.tag, current_version); + } +}; + +pub const UpgradeCommand = struct { + pub const timeout: u32 = 30000; + const default_github_headers = "Acceptapplication/vnd.github.v3+json"; + var github_repository_url_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + + var current_executable_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + var unzip_path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + + pub fn getLatestVersion( + allocator: *std.mem.Allocator, + env_loader: *DotEnv.Loader, + refresher: *std.Progress, + progress: *std.Progress.Node, + comptime silent: bool, + ) !?Version { + var headers_buf: string = default_github_headers; + + var header_entries: Headers.Entries = .{}; + const accept = Headers.Kv{ + .name = Api.StringPointer{ .offset = 0, .length = @intCast(u32, "Accept".len) }, + .value = Api.StringPointer{ .offset = @intCast(u32, "Accept".len), .length = @intCast(u32, "application/vnd.github.v3+json".len) }, + }; + try header_entries.append(allocator, accept); + + // Incase they're using a GitHub proxy in e.g. China + var github_api_domain: string = "api.github.com"; + if (env_loader.map.get("GITHUB_API_DOMAIN")) |api_domain| { + if (api_domain.len > 0) { + github_api_domain = api_domain; + } + } + + var api_url = URL.parse( + try std.fmt.bufPrint( + &github_repository_url_buf, + "https://{s}/repos/Jarred-Sumner/bun-releases-for-updater/releases/latest", + .{ + github_api_domain, + }, + ), + ); + + var client = HTTPClient.init( + allocator, + .GET, + api_url, + header_entries, + headers_buf, + ); + client.timeout = timeout; + if (!silent) { + client.progress_node = progress; + } + + if (env_loader.map.get("GITHUB_ACCESS_TOKEN")) |access_token| { + if (access_token.len > 0) { + headers_buf = try std.fmt.allocPrint(allocator, default_github_headers ++ "Access-TokenBearer {s}", .{access_token}); + try header_entries.append( + allocator, + Headers.Kv{ + .name = Api.StringPointer{ + .offset = accept.value.length + accept.value.offset, + .length = @intCast(u32, "Access-Token".len), + }, + .value = Api.StringPointer{ + .offset = @intCast(u32, accept.value.length + accept.value.offset + "Access-Token".len), + .length = @intCast(u32, access_token.len), + }, + }, + ); + } + } + + var metadata_body = try MutableString.init(allocator, 2048); + var response = try client.send("", &metadata_body); + + switch (response.status_code) { + 404 => return error.HTTP404, + 403 => return error.HTTPForbidden, + 429 => return error.HTTPTooManyRequests, + 499...599 => return error.GitHubIsDown, + 200 => {}, + else => return error.HTTPError, + } + + var log = logger.Log.init(allocator); + var source = logger.Source.initPathString("releases.json", metadata_body.list.items); + initializeStore(); + var expr = ParseJSON(&source, &log, allocator) catch |err| { + if (!silent) { + progress.end(); + refresher.refresh(); + + if (log.errors > 0) { + if (Output.enable_ansi_colors) { + try log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), true); + } else { + try log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), false); + } + Output.flush(); + std.os.exit(1); + } else { + Output.prettyErrorln("Error parsing releases from GitHub: <r><red>{s}<r>", .{@errorName(err)}); + Output.flush(); + std.os.exit(1); + } + } + + return null; + }; + + if (log.errors > 0) { + if (comptime !silent) { + progress.end(); + refresher.refresh(); + + if (Output.enable_ansi_colors) { + try log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), true); + } else { + try log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), false); + } + Output.flush(); + std.os.exit(1); + } + + return null; + } + + var version = Version{ .zip_url = "", .tag = "", .buf = metadata_body, .size = 0 }; + + if (expr.data != .e_object) { + if (comptime !silent) { + progress.end(); + refresher.refresh(); + + const json_type: js_ast.Expr.Tag = @as(js_ast.Expr.Tag, expr.data); + Output.prettyErrorln("JSON error - expected an object but received {s}", .{@tagName(json_type)}); + Output.flush(); + std.os.exit(1); + } + + return null; + } + + if (expr.asProperty("tag_name")) |tag_name_| { + if (tag_name_.expr.asString(allocator)) |tag_name| { + version.tag = tag_name; + } + } + + if (version.tag.len == 0) { + if (comptime !silent) { + progress.end(); + refresher.refresh(); + + Output.prettyErrorln("JSON Error parsing releases from GitHub: <r><red>tag_name<r> is missing?\n{s}", .{metadata_body.list.items}); + Output.flush(); + std.os.exit(1); + } + + return null; + } + + get_asset: { + const assets_ = expr.asProperty("assets") orelse break :get_asset; + var assets = assets_.expr.asArray() orelse break :get_asset; + + while (assets.next()) |asset| { + if (asset.asProperty("name")) |name_| { + if (name_.expr.asString(allocator)) |name| { + if (strings.eqlComptime(name, Version.zip_filename)) { + version.zip_url = (asset.asProperty("browser_download_url") orelse break :get_asset).expr.asString(allocator) orelse break :get_asset; + + if (asset.asProperty("size")) |size_| { + if (size_.expr.data == .e_number) { + version.size = @intCast(u32, @maximum(@floatToInt(i32, std.math.ceil(size_.expr.data.e_number.value)), 0)); + } + } + return version; + } + } + } + } + } + + if (comptime !silent) { + progress.end(); + refresher.refresh(); + if (version.name()) |name| { + Output.prettyErrorln("Bun v{s} is out, but not for this platform ({s}) yet.", .{ + name, Version.triplet, + }); + } + + Output.flush(); + std.os.exit(0); + } + + version.buf.deinit(); + + return null; + } + const exe_subpath = Version.folder_name; + + pub fn exec(ctx: Command.Context) !void { + var filesystem = try fs.FileSystem.init1(ctx.allocator, null); + var env_loader: DotEnv.Loader = brk: { + var map = try ctx.allocator.create(DotEnv.Map); + map.* = DotEnv.Map.init(ctx.allocator); + + break :brk DotEnv.Loader.init(map, ctx.allocator); + }; + + env_loader.loadProcess(); + + var version: Version = undefined; + + { + var refresher = std.Progress{}; + var progress = try refresher.start("Fetching version tags", 0); + + version = (try getLatestVersion(ctx.allocator, &env_loader, &refresher, progress, false)) orelse return; + + progress.end(); + refresher.refresh(); + + if (version.name() != null and version.isCurrent()) { + Output.prettyErrorln( + "<r><green>Congrats!<r> You're already on the latest version of Bun <d>(which is v {s})<r>", + .{ + version.name().?, + }, + ); + Output.flush(); + std.os.exit(0); + } + + if (version.name() == null) { + Output.prettyErrorln( + "<r><red>error:<r> Bun versions are currently unavailable (the latest version name didn't match the expeccted format)", + .{}, + ); + Output.flush(); + std.os.exit(1); + } + } + + { + Output.prettyErrorln("<r><b>Bun <cyan>v{s}<r> is out<r>! You're on <blue>{s}<r>\n", .{ version.name().?, Global.package_json_version }); + Output.flush(); + + var refresher = std.Progress{}; + var progress = try refresher.start("Downloading", version.size); + + var client = HTTPClient.init( + ctx.allocator, + .GET, + URL.parse(version.zip_url), + .{}, + "", + ); + client.timeout = timeout; + client.progress_node = progress; + var zip_file_buffer = try MutableString.init(ctx.allocator, @maximum(version.size, 1024)); + var response = try client.send( + "", + &zip_file_buffer, + ); + + progress.end(); + refresher.refresh(); + + switch (response.status_code) { + 404 => return error.HTTP404, + 403 => return error.HTTPForbidden, + 429 => return error.HTTPTooManyRequests, + 499...599 => return error.GitHubIsDown, + 200 => {}, + else => return error.HTTPError, + } + + var bytes = zip_file_buffer.toOwnedSliceLeaky(); + if (bytes.len == 0) { + Output.prettyErrorln("<r><red>error:<r> Failed to download the latest version of Bun. Received empty content", .{}); + Output.flush(); + std.os.exit(1); + } + + const version_name = version.name().?; + + var save_dir_ = filesystem.tmpdir(); + var save_dir = save_dir_.makeOpenPath(version_name, .{ .iterate = true }) catch |err| { + Output.prettyErrorln("<r><red>error:<r> Failed to open temporary directory", .{}); + Output.flush(); + std.os.exit(1); + }; + + const tmpname = "bun.zip"; + + var zip_file = save_dir.createFileZ(tmpname, .{ .truncate = true }) catch |err| { + Output.prettyErrorln("<r><red>error:<r> Failed to open temp file {s}", .{@errorName(err)}); + Output.flush(); + std.os.exit(1); + }; + + { + _ = zip_file.writeAll(bytes) catch |err| { + save_dir.deleteFileZ(tmpname) catch {}; + Output.prettyErrorln("<r><red>error:<r> Failed to write to temp file {s}", .{@errorName(err)}); + Output.flush(); + std.os.exit(1); + }; + zip_file.close(); + } + + { + defer { + save_dir.deleteFileZ(tmpname) catch {}; + } + + const unzip_exe = which(&unzip_path_buf, env_loader.map.get("PATH") orelse "", filesystem.top_level_dir, "unzip") orelse { + save_dir.deleteFileZ(tmpname) catch {}; + Output.prettyErrorln("<r><red>error:<r> Failed to locate \"unzip\" in PATH. bun upgrade needs \"unzip\" to work.", .{}); + Output.flush(); + std.os.exit(1); + }; + Output.prettyErrorln("<r><b>Unzipping...<r>", .{}); + Output.flush(); + + var unzip_argv = [_]string{ + std.mem.span(unzip_exe), + std.mem.span(tmpname), + }; + + var unzip_process = try std.ChildProcess.init(&unzip_argv, ctx.allocator); + defer unzip_process.deinit(); + unzip_process.cwd_dir = save_dir; + unzip_process.stdin_behavior = .Inherit; + unzip_process.stdout_behavior = .Inherit; + unzip_process.stderr_behavior = .Inherit; + + const unzip_result = unzip_process.spawnAndWait() catch |err| { + save_dir.deleteFileZ(tmpname) catch {}; + Output.prettyErrorln("<r><red>error:<r> Failed to spawn unzip due to {s}.", .{@errorName(err)}); + Output.flush(); + std.os.exit(1); + }; + + if (unzip_result.Exited != 0) { + Output.prettyErrorln("<r><red>Unzip failed<r> (exit code: {d})", .{unzip_result.Exited}); + Output.flush(); + save_dir.deleteFileZ(tmpname) catch {}; + std.os.exit(1); + } + } + + { + var verify_argv = [_]string{ + exe_subpath, + "--version", + }; + + const result = std.ChildProcess.exec(.{ + .allocator = ctx.allocator, + .argv = &verify_argv, + .cwd_dir = save_dir, + .max_output_bytes = 128, + }) catch |err| { + save_dir_.deleteTree(version_name) catch {}; + Output.prettyErrorln("<r><red>error<r> Failed to verify Bun {s}<r>)", .{@errorName(err)}); + Output.flush(); + std.os.exit(1); + }; + + if (result.term.Exited != 0) { + Output.prettyErrorln("<r><red>error<r> failed to verify Bun<r> (exit code: {d})", .{result.term.Exited}); + Output.flush(); + std.os.exit(1); + } + + if (!strings.eql(std.mem.trim(u8, result.stdout, " \n\r\t"), version_name)) { + Output.prettyErrorln( + "<r><red>error<r>: The downloaded version of Bun (<red>{s}<r>) doesn't match the expected version (<b>{s}<r>)<r>. Cancelled upgrade", + .{ + result.stdout[0..@minimum(result.stdout.len, 128)], + version_name, + }, + ); + Output.flush(); + std.os.exit(1); + } + } + + var destination_executable_ = std.fs.selfExePath(¤t_executable_buf) catch return error.UpgradeFailedMissingExecutable; + current_executable_buf[destination_executable_.len] = 0; + + var target_filename_ = std.fs.path.basename(destination_executable_); + var target_filename = current_executable_buf[destination_executable_.len - target_filename_.len ..][0..target_filename_.len :0]; + var target_dir_ = std.fs.path.dirname(destination_executable_) orelse return error.UpgradeFailedBecauseOfMissingExecutableDir; + // safe because the slash will no longer be in use + current_executable_buf[target_dir_.len] = 0; + var target_dirname = current_executable_buf[0..target_dir_.len :0]; + var target_dir = std.fs.openDirAbsoluteZ(target_dirname, .{ .iterate = true }) catch |err| { + Output.prettyErrorln("<r><red>error:<r> Failed to open Bun's install directory {s}", .{@errorName(err)}); + Output.flush(); + std.os.exit(1); + }; + + if (env_loader.map.get("BUN_DRY_RUN") == null) { + C.moveFileZ(save_dir.fd, exe_subpath, target_dir.fd, target_filename) catch |err| { + Output.prettyErrorln("<r><red>error:<r> Failed to move new version of Bun due to {s}. You could try the install script instead:\n curl https://bun.sh/install | bash", .{@errorName(err)}); + Output.flush(); + std.os.exit(1); + }; + } + + Output.prettyErrorln("\n", .{}); + Output.flush(); + Output.prettyln("<r><b><green>Upgraded successfully<r>. Welcome to Bun v{s}!\nFind out what's new: https://github.com/Jarred-Sumner/bun/releases<r>", .{version_name}); + Output.flush(); + return; + } + } +}; diff --git a/src/fs.zig b/src/fs.zig index 0b28fa9b7..9c8a0b6d3 100644 --- a/src/fs.zig +++ b/src/fs.zig @@ -493,7 +493,7 @@ pub const FileSystem = struct { pub var tmpdir_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; const PLATFORM_TMP_DIR: string = switch (std.Target.current.os.tag) { - .windows => "%TMPDIR%", + .windows => "TMPDIR", .macos => "/private/tmp", else => "/tmp", }; diff --git a/src/javascript/jsc/WebKit b/src/javascript/jsc/WebKit -Subproject 58007798f366ae8bb7487ca5256a6db860c6da4 +Subproject 2c7c359ff9e6d1cff8528354ef19881d4d0e6c7 |