aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cli.zig14
-rw-r--r--src/cli/install.sh138
-rw-r--r--src/cli/run_command.zig2
-rw-r--r--src/cli/upgrade_command.zig495
-rw-r--r--src/fs.zig2
m---------src/javascript/jsc/WebKit0
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(&current_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