New subcommand: bun upgrade. It upgrades bun to the latest version.

This commit is contained in:
Jarred Sumner
2021-10-28 05:34:38 -07:00
parent c7fc08056a
commit a44cb9708f
25 changed files with 772 additions and 365 deletions

6
.gitignore vendored
View File

@@ -64,7 +64,11 @@ release/
sign.*.json
packages/debug-*
packages/bun-cli/postinstall.js
packages/bun-*/bin/*
packages/bun-*/bun
packages/bun-*/bun-profile
packages/bun-*/debug-bun
packages/bun-*/*.o
packages/bun-cli/postinstall.js
packages/bun-cli/bin/*
bun-test-scratch

236
Makefile
View File

@@ -2,6 +2,7 @@ SHELL := /bin/bash # Use bash syntax to be consistent
OS_NAME := $(shell uname -s | tr '[:upper:]' '[:lower:]')
ARCH_NAME_RAW := $(shell uname -m)
BUN_AUTO_UPDATER_REPO = Jarred-Sumner/bun-releases-for-updater
make-lazy = $(eval $1 = $$(eval $1 := $(value $(1)))$$($1))
@@ -15,20 +16,17 @@ else
endif
TRIPLET = $(OS_NAME)-$(ARCH_NAME)
PACKAGE_NAME = bun-cli-$(TRIPLET)
PACKAGE_NAME = bun-$(TRIPLET)
PACKAGES_REALPATH = $(realpath packages)
PACKAGE_DIR = $(PACKAGES_REALPATH)/$(PACKAGE_NAME)
DEBUG_PACKAGE_DIR = $(PACKAGES_REALPATH)/debug-$(PACKAGE_NAME)
BIN_DIR = $(PACKAGE_DIR)/bin
RELEASE_BUN = $(PACKAGE_DIR)/bin/bun
DEBUG_BIN = $(DEBUG_PACKAGE_DIR)/bin
DEBUG_BIN = $(DEBUG_PACKAGE_DIR)/
DEBUG_BUN = $(DEBUG_BIN)/bun-debug
BUILD_ID = $(shell cat ./build-id)
PACKAGE_JSON_VERSION = 0.0.$(BUILD_ID)
BUN_BUILD_TAG = bun-v$(PACKAGE_JSON_VERSION)
PACKAGE_MAC = $(PACKAGES_REALPATH)/bun-cli-mac
MAC_BIN = $(PACKAGE_MAC)/bin
MAC_BUN = $(MAC_BIN)/bun
BUN_RELEASE_BIN = $(PACKAGE_DIR)/bun
# We must use the same compiler version for the JavaScriptCore bindings and JavaScriptCore
# If we don't do this, strange memory allocation failures occur.
@@ -78,6 +76,7 @@ build-iconv-linux:
cd src/deps/libiconv/libiconv-1.16; ./configure --enable-static; make -j 12; cp ./lib/.libs/libiconv.a $(DEPS_DIR)/libiconv.a
BUN_TMP_DIR := /tmp/make-bun
BUN_DEPLOY_DIR = /tmp/bun-v$(PACKAGE_JSON_VERSION)/$(PACKAGE_NAME)
DEFAULT_USE_BMALLOC := 1
# ifeq ($(OS_NAME),linux)
@@ -309,7 +308,8 @@ BUN_LLD_FLAGS = $(OBJ_FILES) \
bun: vendor build-obj bun-link-lld-release
vendor-without-check: api analytics node-fallbacks runtime_js fallback_decoder bun_error mimalloc picohttp zlib openssl s2n libarchive
vendor-without-check: api analytics node-fallbacks runtime_js fallback_decoder bun_error mimalloc picohttp zlib openssl s2n bzip2 libarchive
libarchive:
cd src/deps/libarchive; \
@@ -321,10 +321,10 @@ libarchive:
cp ./.libs/libarchive.a $(DEPS_DIR)/libarchive.a;
tgz:
zig build-exe -Drelease-fast --main-pkg-path $(shell pwd) ./misctools/tgz.zig $(DEPS_DIR)/zlib/libz.a $(DEPS_DIR)/libarchive.a $(LIBICONV_PATH) -lc
zig build-exe -Drelease-fast --main-pkg-path $(shell pwd) ./misctools/tgz.zig $(DEPS_DIR)/zlib/libz.a $(DEPS_DIR)/libarchive.a $(LIBICONV_PATH) -lc
tgz-debug:
zig build-exe --main-pkg-path $(shell pwd) ./misctools/tgz.zig $(DEPS_DIR)/zlib/libz.a $(DEPS_DIR)/libarchive.a $(LIBICONV_PATH) -lc
zig build-exe --main-pkg-path $(shell pwd) ./misctools/tgz.zig $(DEPS_DIR)/zlib/libz.a $(DEPS_DIR)/libarchive.a $(LIBICONV_PATH) -lc
vendor: require init-submodules vendor-without-check
@@ -365,8 +365,6 @@ jsc-check:
all-js: runtime_js fallback_decoder bun_error node-fallbacks
bin-dir:
@echo $(BIN_DIR)
api:
pnpm install; ./node_modules/.bin/peechy --schema src/api/schema.peechy --esm src/api/schema.js --ts src/api/schema.d.ts --zig src/api/schema.zig
@@ -387,8 +385,8 @@ bun_error:
@cd packages/bun-error; pnpm install; npm run --silent build
generate-install-script:
@rm -f $(PACKAGES_REALPATH)/bun-cli/install.js
# NODE_ENV=production esbuild --log-level=error --define:BUN_VERSION="\"$(PACKAGE_JSON_VERSION)\"" --define:process.env.NODE_ENV="\"production\"" --platform=node --target=node14 --bundle --format=cjs $(PACKAGES_REALPATH)/bun-cli/node-install.ts > $(PACKAGES_REALPATH)/bun-cli/install.js
@rm -f $(PACKAGES_REALPATH)/bun/install.js
@esbuild --log-level=error --define:BUN_VERSION="\"$(PACKAGE_JSON_VERSION)\"" --define:process.env.NODE_ENV="\"production\"" --platform=node --format=cjs $(PACKAGES_REALPATH)/bun/install.ts > $(PACKAGES_REALPATH)/bun/install.js
fetch:
cd misctools; zig build-obj -Drelease-fast ./fetch.zig -fcompiler-rt -lc --main-pkg-path ../
@@ -476,197 +474,65 @@ bump:
expr $(BUILD_ID) + 1 > build-id
# When adding a new architecture, don't forget to update this!
write-package-json-version-cli-json:
jq -S --raw-output '.version = "${PACKAGE_JSON_VERSION}"' packages/bun-cli/package.json > packages/bun-cli/package.json.new
mv packages/bun-cli/package.json.new packages/bun-cli/package.json
jq -S --raw-output '.optionalDependencies."bun-cli-linux-x64" = "${PACKAGE_JSON_VERSION}"' packages/bun-cli/package.json > packages/bun-cli/package.json.new
mv packages/bun-cli/package.json.new packages/bun-cli/package.json
jq -S --raw-output '.optionalDependencies."bun-cli-mac" = "${PACKAGE_JSON_VERSION}"' packages/bun-cli/package.json > packages/bun-cli/package.json.new
mv packages/bun-cli/package.json.new packages/bun-cli/package.json
write-package-json-version:
jq -S --raw-output '.version = "${PACKAGE_JSON_VERSION}"' $(PACKAGE_DIR)/package.json > $(PACKAGE_DIR)/package.json.new
mv $(PACKAGE_DIR)/package.json.new $(PACKAGE_DIR)/package.json
write-package-json-version-cli: write-package-json-version-cli-json generate-install-script
write-package-json-version-mac:
jq -S --raw-output '.version = "${PACKAGE_JSON_VERSION}"' $(PACKAGE_MAC)/package.json > $(PACKAGE_MAC)/package.json.new
mv $(PACKAGE_MAC)/package.json.new $(PACKAGE_MAC)/package.json
tag:
git tag $(BUN_BUILD_TAG)
git push --tags
prepare-release: tag release-create write-package-json-version-cli write-package-json-version write-package-json-version-mac
prepare-release: tag release-create
release-create-auto-updater:
release-create:
gh release create --title "Bun v$(PACKAGE_JSON_VERSION)" "$(BUN_BUILD_TAG)"
BUN_DEPLOY_DIR = $(BUN_TMP_DIR)/bun-deploy
BUN_DEPLOY_CLI = $(BUN_TMP_DIR)/bun-cli
BUN_DEPLOY_PKG = $(BUN_DEPLOY_DIR)/$(PACKAGE_NAME)
BUN_DEPLOY_TGZ = $(BUN_DEPLOY_PKG)/$(PACKAGE_NAME)-$(PACKAGE_JSON_VERSION).tgz
BUN_DEPLOY_PKG_MAC = $(BUN_DEPLOY_DIR)/bun-cli-mac
BUN_DEPLOY_TGZ_MAC = $(BUN_DEPLOY_PKG_MAC)/bun-cli-mac-$(PACKAGE_JSON_VERSION).tgz
RELEASE_CLI_CHECK_DIR = /tmp/bun-$(PACKAGE_JSON_VERSION)-cli-check
RELEASE_BIN_CHECK_DIR = /tmp/bun-$(PACKAGE_JSON_VERSION)-bin-check
release-cli-generate: write-package-json-version-cli release-cli-generate-build
release-cli-generate-build:
rm -rf $(BUN_DEPLOY_CLI)
mkdir -p $(BUN_DEPLOY_CLI)
chmod +x packages/bun-cli/bin/bun
cp -r packages/bun-cli $(BUN_DEPLOY_CLI)
cd $(BUN_DEPLOY_CLI)/bun-cli; npm pack;
release-cli-check-npm:
rm -rf $(RELEASE_CLI_CHECK_DIR);
mkdir -p $(RELEASE_CLI_CHECK_DIR);
echo "{\"name\": \"bun-test-$(PACKAGE_JSON_VERSION)\"}" > $(RELEASE_CLI_CHECK_DIR)/package.json
cd $(RELEASE_CLI_CHECK_DIR) && npm install --save $(BUN_DEPLOY_CLI)/bun-cli/bun-cli-$(PACKAGE_JSON_VERSION).tgz
test "$(PACKAGE_JSON_VERSION)" == "$(shell eval $(RELEASE_CLI_CHECK_DIR)/node_modules/.bin/bun --version || echo "FAIL" )"
release-cli-check-yarn:
rm -rf $(RELEASE_CLI_CHECK_DIR);
mkdir -p $(RELEASE_CLI_CHECK_DIR);
echo "{\"name\": \"bun-test-$(PACKAGE_JSON_VERSION)\"}" > $(RELEASE_CLI_CHECK_DIR)/package.json
cd $(RELEASE_CLI_CHECK_DIR) && yarn add $(BUN_DEPLOY_CLI)/bun-cli/bun-cli-$(PACKAGE_JSON_VERSION).tgz
test "$(PACKAGE_JSON_VERSION)" == "$(shell eval $(RELEASE_CLI_CHECK_DIR)/node_modules/.bin/bun --version || echo "FAIL" )"
release-cli-check-pnpm:
rm -rf $(RELEASE_CLI_CHECK_DIR);
mkdir -p $(RELEASE_CLI_CHECK_DIR);
echo "{\"name\": \"bun-test-$(PACKAGE_JSON_VERSION)\"}" > $(RELEASE_CLI_CHECK_DIR)/package.json
cd $(RELEASE_CLI_CHECK_DIR) && pnpm add $(BUN_DEPLOY_CLI)/bun-cli/bun-cli-$(PACKAGE_JSON_VERSION).tgz
test "$(PACKAGE_JSON_VERSION)" == "$(shell eval $(RELEASE_CLI_CHECK_DIR)/node_modules/.bin/bun --version || echo "FAIL" )"
release-cli-check: release-cli-check-npm release-cli-check-yarn release-cli-check-pnpm
release-bin-check-npm:
rm -rf $(RELEASE_BIN_CHECK_DIR);
mkdir -p $(RELEASE_BIN_CHECK_DIR);
echo "{\"name\": \"bun-test-$(PACKAGE_JSON_VERSION)\"}" > $(RELEASE_BIN_CHECK_DIR)/package.json
cd $(RELEASE_BIN_CHECK_DIR) && npm install --save $(BUN_DEPLOY_TGZ)
test "$(PACKAGE_JSON_VERSION)" == "$(shell eval $(RELEASE_BIN_CHECK_DIR)/node_modules/$(PACKAGE_NAME)/bin/bun --version || echo "FAIL" )"
release-bin-check-yarn:
rm -rf $(RELEASE_BIN_CHECK_DIR);
mkdir -p $(RELEASE_BIN_CHECK_DIR);
echo "{\"name\": \"bun-test-$(PACKAGE_JSON_VERSION)\"}" > $(RELEASE_BIN_CHECK_DIR)/package.json
cd $(RELEASE_BIN_CHECK_DIR) && yarn add $(BUN_DEPLOY_TGZ)
test "$(PACKAGE_JSON_VERSION)" == "$(shell eval $(RELEASE_BIN_CHECK_DIR)/node_modules/$(PACKAGE_NAME)/bin/bun --version || echo "FAIL" )"
release-bin-check-pnpm:
rm -rf $(RELEASE_BIN_CHECK_DIR);
mkdir -p $(RELEASE_BIN_CHECK_DIR);
echo "{\"name\": \"bun-test-$(PACKAGE_JSON_VERSION)\"}" > $(RELEASE_BIN_CHECK_DIR)/package.json
cd $(RELEASE_BIN_CHECK_DIR) && pnpm add $(BUN_DEPLOY_TGZ)
test "$(PACKAGE_JSON_VERSION)" == "$(shell eval $(RELEASE_BIN_CHECK_DIR)/node_modules/$(PACKAGE_NAME)/bin/bun --version || echo "FAIL" )"
release-bin-check: release-bin-check-npm release-bin-check-yarn release-bin-check-pnpm
release-mac-check-npm:
rm -rf $(RELEASE_BIN_CHECK_DIR);
mkdir -p $(RELEASE_BIN_CHECK_DIR);
echo "{\"name\": \"bun-test-$(PACKAGE_JSON_VERSION)\"}" > $(RELEASE_BIN_CHECK_DIR)/package.json
cd $(RELEASE_BIN_CHECK_DIR) && npm install --save $(BUN_DEPLOY_TGZ_MAC)
test "$(PACKAGE_JSON_VERSION)" == "$(shell eval $(RELEASE_BIN_CHECK_DIR)/node_modules/.bin/bun --version || echo "FAIL" )"
release-mac-check-yarn:
rm -rf $(RELEASE_BIN_CHECK_DIR);
mkdir -p $(RELEASE_BIN_CHECK_DIR);
echo "{\"name\": \"bun-test-$(PACKAGE_JSON_VERSION)\"}" > $(RELEASE_BIN_CHECK_DIR)/package.json
cd $(RELEASE_BIN_CHECK_DIR) && yarn add $(BUN_DEPLOY_TGZ_MAC)
test "$(PACKAGE_JSON_VERSION)" == "$(shell eval $(RELEASE_BIN_CHECK_DIR)/node_modules/.bin/bun --version || echo "FAIL" )"
release-mac-check-pnpm:
rm -rf $(RELEASE_BIN_CHECK_DIR);
mkdir -p $(RELEASE_BIN_CHECK_DIR);
echo "{\"name\": \"bun-test-$(PACKAGE_JSON_VERSION)\"}" > $(RELEASE_BIN_CHECK_DIR)/package.json
cd $(RELEASE_BIN_CHECK_DIR) && pnpm add $(BUN_DEPLOY_TGZ_MAC)
test "$(PACKAGE_JSON_VERSION)" == "$(shell eval $(RELEASE_BIN_CHECK_DIR)/node_modules/.bin/bun --version || echo "FAIL" )"
release-mac-check: release-mac-check-npm release-mac-check-yarn release-mac-check-pnpm
release-cli-push:
gh release upload $(BUN_BUILD_TAG) --clobber $(BUN_DEPLOY_CLI)/bun-cli/bun-cli-$(PACKAGE_JSON_VERSION).tgz
npm publish $(BUN_DEPLOY_CLI)/bun-cli/bun-cli-$(PACKAGE_JSON_VERSION).tgz --access=public
release-bin-generate: write-package-json-version
rm -rf $(BUN_DEPLOY_DIR)
mkdir -p $(BUN_DEPLOY_DIR)
cp -r $(PACKAGE_DIR) $(BUN_DEPLOY_DIR)
cd $(BUN_DEPLOY_PKG); npm pack;
release-mac-generate: write-package-json-version-mac
rm -rf $(BUN_DEPLOY_DIR)
mkdir -p $(BUN_DEPLOY_DIR)
cp -r $(PACKAGE_MAC) $(BUN_DEPLOY_DIR)
cd $(BUN_DEPLOY_PKG_MAC); npm pack;
gh release create --repo=$(BUN_AUTO_UPDATER_REPO) --title "Bun v$(PACKAGE_JSON_VERSION)" "$(BUN_BUILD_TAG)" -n "See https://github.com/Jarred-Sumner/bun/releases/tag/$(BUN_BUILD_TAG) for release notes. Using the install script or `bun upgrade` is the recommended way to install Bun. Join Bun's Discord to get access https://bun.sh/discord"
release-bin-entitlements:
release-bin-entitlements-mac:
release-bin-generate-zip:
ifeq ($(OS_NAME),darwin)
# Without this, JIT will fail on aarch64
# strip will remove the entitlements.plist
# which, in turn, will break JIT
release-bin-entitlements:
codesign --entitlements $(realpath entitlements.plist) --options runtime --force --timestamp --sign "$(CODESIGN_IDENTITY)" -vvv --deep --strict $(BIN_DIR)/bun
codesign --entitlements $(realpath entitlements.plist) --options runtime --force --timestamp --sign "$(CODESIGN_IDENTITY)" -vvvv --deep --strict $(BUN_RELEASE_BIN)
release-bin-entitlements-mac:
codesign --entitlements $(realpath entitlements.plist) --options runtime --force --timestamp --sign "$(CODESIGN_IDENTITY)" -vvv --deep --strict $(MAC_BUN)
# macOS expects a specific directory structure for the zip file
# ditto lets us generate it similarly to right clicking "Compress" in Finder
release-bin-generate-zip:
dot_clean -vnm /tmp/bun-$(PACKAGE_JSON_VERSION)/bun-$(TRIPLET)
cd /tmp/bun-$(PACKAGE_JSON_VERSION)/bun-$(TRIPLET) && \
codesign --entitlements $(realpath entitlements.plist) --options runtime --force --timestamp --sign "$(CODESIGN_IDENTITY)" -vvvv --deep --strict bun
ditto -ck --rsrc --sequesterRsrc --keepParent /tmp/bun-$(PACKAGE_JSON_VERSION)/bun-$(TRIPLET) $(BUN_DEPLOY_ZIP)
else
release-bin-generate-zip:
cd /tmp/bun-$(PACKAGE_JSON_VERSION)/ && zip -r bun-$(TRIPLET)
endif
BUN_DEPLOY_ZIP = /tmp/bun-$(PACKAGE_JSON_VERSION)/bun-$(TRIPLET).zip
release-bin-generate-copy:
rm -rf /tmp/bun-$(PACKAGE_JSON_VERSION)/bun-$(TRIPLET) $(BUN_DEPLOY_ZIP)
mkdir -p /tmp/bun-$(PACKAGE_JSON_VERSION)/bun-$(TRIPLET)
cp $(BUN_RELEASE_BIN) /tmp/bun-$(PACKAGE_JSON_VERSION)/bun-$(TRIPLET)/bun
release-bin-generate: release-bin-generate-copy release-bin-generate-zip
release-bin-codesign:
mkdir -p $(BUN_DEPLOY_ZIP)-input/package
tar -xzvf $(BUN_DEPLOY_TGZ) package
zip -r $(BUN_DEPLOY_ZIP) package
xcrun notarytool submit --wait $(BUN_DEPLOY_ZIP)
xcrun notarytool submit --wait $(BUN_DEPLOY_ZIP) --keychain-profile "bun"
release-bin-notarize:
xcrun notarytool submit $(BIN_DIR)/bun
release-bin-without-push: test-all release-bin-check
release-bin-without-push: test-all release-bin-generate release-bin-codesign
release-bin: release-bin-without-push release-bin-push
release-mac-without-push: release-mac-generate-bin release-bin-entitlements-mac test-all-mac release-mac-generate release-mac-check
release-mac: release-mac-without-push release-mac-push
release-mac-check:
rm -rf /tmp/bun-$(PACKAGE_JSON_VERSION)-check;
mkdir -p /tmp/bun-$(PACKAGE_JSON_VERSION)-check;
echo "{\"name\": \"bun-test-$(PACKAGE_JSON_VERSION)\"}" > /tmp/bun-$(PACKAGE_JSON_VERSION)-check/package.json
cd /tmp/bun-$(PACKAGE_JSON_VERSION)-check && npm install $(BUN_DEPLOY_TGZ_MAC)
test "$(PACKAGE_JSON_VERSION)" == "$(shell eval /tmp/bun-$(PACKAGE_JSON_VERSION)-check/node_modules/.bin/bun --version)"
release-bin-push:
gh release upload $(BUN_BUILD_TAG) --clobber $(BUN_DEPLOY_TGZ)
npm publish $(BUN_DEPLOY_TGZ) --access=public
release-mac-push:
gh release upload $(BUN_BUILD_TAG) --clobber $(BUN_DEPLOY_TGZ_MAC)
npm publish $(BUN_DEPLOY_TGZ_MAC) --access=public
release-mac-generate-bin:
rm -rf /tmp/bun-fat-$(PACKAGE_JSON_VERSION)
mkdir -p /tmp/bun-fat-$(PACKAGE_JSON_VERSION)
curl "https://registry.npmjs.org/bun-cli-darwin-aarch64/-/bun-cli-darwin-aarch64-0.0.37.tgz" > /tmp/bun-fat-$(PACKAGE_JSON_VERSION)/aarch64.tgz
curl "https://registry.npmjs.org/bun-cli-darwin-x64/-/bun-cli-darwin-x64-0.0.37.tgz" > /tmp/bun-fat-$(PACKAGE_JSON_VERSION)/x64.tgz
mkdir /tmp/bun-fat-$(PACKAGE_JSON_VERSION)/x64
mkdir /tmp/bun-fat-$(PACKAGE_JSON_VERSION)/aarch64
cd /tmp/bun-fat-$(PACKAGE_JSON_VERSION) && tar -xvf x64.tgz -C x64
cd /tmp/bun-fat-$(PACKAGE_JSON_VERSION) && tar -xvf aarch64.tgz -C aarch64
rm -f $(MAC_BUN)
lipo -create -output $(MAC_BUN) /tmp/bun-fat-$(PACKAGE_JSON_VERSION)/x64/package/bin/bun /tmp/bun-fat-$(PACKAGE_JSON_VERSION)/aarch64/package/bin/bun
gh release upload $(BUN_BUILD_TAG) --clobber $(BUN_DEPLOY_ZIP)
gh release upload $(BUN_BUILD_TAG) --clobber $(BUN_DEPLOY_ZIP) --repo $(BUN_AUTO_UPDATER_REPO)
dev-obj:
zig build obj
@@ -788,21 +654,21 @@ bun-link-lld-debug:
bun-relink-copy:
cp /tmp/bun-$(PACKAGE_JSON_VERSION).o $(BIN_DIR)/bun.o
cp /tmp/bun-$(PACKAGE_JSON_VERSION).o $(BUN_RELEASE_BIN).o
bun-relink: bun-relink-copy bun-link-lld-release
bun-link-lld-release:
$(CXX) $(BUN_LLD_FLAGS) \
$(BIN_DIR)/bun.o \
-o $(BIN_DIR)/bun \
$(BUN_RELEASE_BIN).o \
-o $(BUN_RELEASE_BIN) \
-W \
-flto \
-ftls-model=initial-exec \
-O3
cp $(BIN_DIR)/bun $(BIN_DIR)/bun-profile
$(STRIP) $(BIN_DIR)/bun
mv $(BIN_DIR)/bun.o /tmp/bun-$(PACKAGE_JSON_VERSION).o
cp $(BUN_RELEASE_BIN) $(BUN_RELEASE_BIN)-profile
$(STRIP) $(BUN_RELEASE_BIN)
mv $(BUN_RELEASE_BIN).o /tmp/bun-$(PACKAGE_JSON_VERSION).o
# We do this outside of build.zig for performance reasons
# The C compilation stuff with build.zig is really slow and we don't need to run this as often as the rest

View File

@@ -15,8 +15,7 @@ All in one fast & easy-to-use tool. Instead of 1,000 node_modules for develo
## Install:
```
# Global install is recommended so bun appears in your $PATH
npm install -g bun-cli
curl -fsSL bun.sh/install | bash
```
## Benchmarks
@@ -458,9 +457,9 @@ When running bun on an M1 (or Apple Silicon), if you see a message like this:
> [1] 28447 killed bun create next ./test
It most likely means you're running bun's x64 version on Apple Silicon. This happens if `node` (or, rather, `npm`) is running via Rosetta. Rosetta is unable to emulate AVX2 instructions, which Bun indirectly uses.
It most likely means you're running bun's x64 version on Apple Silicon. This happens if bun is running via Rosetta. Rosetta is unable to emulate AVX2 instructions, which Bun indirectly uses.
The fix is to ensure you installed a version of Node built for Apple Silicon and then reinstall `bun-cli`. You can also try to directly install `npm install -g bun-cli-darwin-aarch64`.
The fix is to ensure you installed a version of Bun built for Apple Silicon.
# Reference

View File

@@ -1 +1 @@
38
39

109
build.zig
View File

@@ -34,7 +34,7 @@ pub fn build(b: *std.build.Builder) !void {
const cwd: []const u8 = b.pathFromRoot(".");
var exe: *std.build.LibExeObjStep = undefined;
var output_dir_buf = std.mem.zeroes([4096]u8);
var bin_label = if (mode == std.builtin.Mode.Debug) "packages/debug-bun-cli-" else "packages/bun-cli-";
var bin_label = if (mode == std.builtin.Mode.Debug) "packages/debug-bun-" else "packages/bun-";
var triplet_buf: [64]u8 = undefined;
var os_tagname = @tagName(target.getOs().tag);
@@ -60,7 +60,7 @@ pub fn build(b: *std.build.Builder) !void {
var triplet = triplet_buf[0 .. osname.len + cpuArchName.len + 1];
const output_dir_base = try std.fmt.bufPrint(&output_dir_buf, "{s}{s}/bin", .{ bin_label, triplet });
const output_dir_base = try std.fmt.bufPrint(&output_dir_buf, "{s}{s}", .{ bin_label, triplet });
const output_dir = b.pathFromRoot(output_dir_base);
const bun_executable_name = if (mode == std.builtin.Mode.Debug) "bun-debug" else "bun";
@@ -207,67 +207,64 @@ pub fn build(b: *std.build.Builder) !void {
headers_obj.setMainPkgPath(javascript.main_pkg_path.?);
headers_step.dependOn(&headers_obj.step);
b.default_step.dependOn(&exe.step);
{
var steps = [_]*std.build.LibExeObjStep{ exe, javascript, typings_exe };
// const single_threaded = b.option(bool, "single-threaded", "Build single-threaded") orelse false;
var steps = [_]*std.build.LibExeObjStep{ exe, javascript, typings_exe };
// const single_threaded = b.option(bool, "single-threaded", "Build single-threaded") orelse false;
for (steps) |step, i| {
step.linkLibC();
step.linkLibCpp();
addPicoHTTP(
step,
true,
);
step.addObjectFile("src/deps/libJavaScriptCore.a");
step.addObjectFile("src/deps/libWTF.a");
step.addObjectFile("src/deps/libcrypto.a");
step.addObjectFile("src/deps/libbmalloc.a");
step.addObjectFile("src/deps/libarchive.a");
step.addObjectFile("src/deps/libs2n.a");
step.addObjectFile("src/deps/zlib/libz.a");
step.addObjectFile("src/deps/mimalloc/libmimalloc.a");
step.addLibPath("src/deps/mimalloc");
step.addIncludeDir("src/deps/mimalloc");
// step.single_threaded = single_threaded;
if (target.getOsTag() == .macos) {
const homebrew_prefix = comptime if (std.Target.current.cpu.arch == .aarch64)
"/opt/homebrew/"
else
"/usr/local/";
// We must link ICU statically
step.addObjectFile(homebrew_prefix ++ "opt/icu4c/lib/libicudata.a");
step.addObjectFile(homebrew_prefix ++ "opt/icu4c/lib/libicui18n.a");
step.addObjectFile(homebrew_prefix ++ "opt/icu4c/lib/libicuuc.a");
step.addObjectFile(homebrew_prefix ++ "opt/libiconv/lib/libiconv.a");
// icucore is a weird macOS only library
step.linkSystemLibrary("icucore");
step.addLibPath(homebrew_prefix ++ "opt/icu4c/lib");
step.addIncludeDir(homebrew_prefix ++ "opt/icu4c/include");
} else {
step.linkSystemLibrary("icuuc");
step.linkSystemLibrary("icudata");
step.linkSystemLibrary("icui18n");
step.addObjectFile("src/deps/libiconv.a");
}
for (bindings_files.items) |binding| {
step.addObjectFile(
binding,
for (steps) |step, i| {
step.linkLibC();
step.linkLibCpp();
addPicoHTTP(
step,
true,
);
step.addObjectFile("src/deps/libJavaScriptCore.a");
step.addObjectFile("src/deps/libWTF.a");
step.addObjectFile("src/deps/libcrypto.a");
step.addObjectFile("src/deps/libbmalloc.a");
step.addObjectFile("src/deps/libarchive.a");
step.addObjectFile("src/deps/libs2n.a");
step.addObjectFile("src/deps/zlib/libz.a");
step.addObjectFile("src/deps/mimalloc/libmimalloc.a");
step.addLibPath("src/deps/mimalloc");
step.addIncludeDir("src/deps/mimalloc");
// step.single_threaded = single_threaded;
if (target.getOsTag() == .macos) {
const homebrew_prefix = comptime if (std.Target.current.cpu.arch == .aarch64)
"/opt/homebrew/"
else
"/usr/local/";
// We must link ICU statically
step.addObjectFile(homebrew_prefix ++ "opt/icu4c/lib/libicudata.a");
step.addObjectFile(homebrew_prefix ++ "opt/icu4c/lib/libicui18n.a");
step.addObjectFile(homebrew_prefix ++ "opt/icu4c/lib/libicuuc.a");
step.addObjectFile(homebrew_prefix ++ "opt/libiconv/lib/libiconv.a");
// icucore is a weird macOS only library
step.linkSystemLibrary("icucore");
step.addLibPath(homebrew_prefix ++ "opt/icu4c/lib");
step.addIncludeDir(homebrew_prefix ++ "opt/icu4c/include");
} else {
step.linkSystemLibrary("icuuc");
step.linkSystemLibrary("icudata");
step.linkSystemLibrary("icui18n");
step.addObjectFile("src/deps/libiconv.a");
}
for (bindings_files.items) |binding| {
step.addObjectFile(
binding,
);
}
}
}
}
{
var obj_step = b.step("obj", "Build Bun as a .o file");

View File

@@ -2,13 +2,15 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.application-identifier</key>
<string>com.codeblogcorp.bun</string>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.single-jit</key>
<true/>
<key>com.apple.security.network.client</key>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>

View File

@@ -74,7 +74,7 @@ pub fn main() anyerror!void {
tarball_buf_list = std.ArrayListUnmanaged(u8){ .capacity = file_buf.len, .items = file_buf };
}
_ = try Archive.extractToDisk(
_ = try Archive.extractToDisk(
file_buf,
folder,
null,

View File

@@ -1,16 +0,0 @@
{
"cpu": [
"arm64"
],
"bugs": {
"url": "https://github.com/jarred-sumner/bun/issues"
},
"homepage": "https://bun.sh",
"name": "bun-cli-darwin-aarch64",
"private": false,
"os": [
"darwin"
],
"repository": "https://github.com/jarred-sumner/bun",
"version": "0.0.37"
}

View File

@@ -1,16 +0,0 @@
{
"bugs": {
"url": "https://github.com/jarred-sumner/bun/issues"
},
"cpu": [
"x64"
],
"homepage": "https://bun.sh",
"name": "bun-cli-darwin-x64",
"os": [
"darwin"
],
"private": false,
"repository": "https://github.com/jarred-sumner/bun",
"version": "0.0.38"
}

View File

@@ -1,17 +0,0 @@
{
"cpu": [
"x64"
],
"bugs": {
"url": "https://github.com/jarred-sumner/bun/issues"
},
"homepage": "https://bun.sh",
"description": "Linux build of Bun",
"name": "bun-cli-linux-x64",
"private": false,
"os": [
"linux"
],
"repository": "https://github.com/jarred-sumner/bun",
"version": "0.0.37"
}

View File

@@ -1,4 +0,0 @@
bin/bun-profile
bin/*.o
*.o
*.a

View File

@@ -1,18 +0,0 @@
{
"cpu": [
"x64",
"arm64"
],
"description": "macOS build of Bun",
"bugs": {
"url": "https://github.com/jarred-sumner/bun/issues"
},
"homepage": "https://bun.sh",
"name": "bun-cli-mac",
"os": [
"darwin"
],
"private": false,
"repository": "https://github.com/jarred-sumner/bun",
"version": "0.0.37"
}

View File

@@ -1,3 +0,0 @@
scripts
pnpm-lock.yaml
*.ts

View File

@@ -1,17 +0,0 @@
{
"bugs": {
"url": "https://github.com/jarred-sumner/bun/issues"
},
"description": "Bun: a fast bundler, transpiler and task runner for web software. To get early access, join the Discord https://bun.sh/discord",
"homepage": "https://bun.sh",
"license": "MIT",
"main": "package.json",
"name": "bun-cli",
"optionalDependencies": {
"bun-cli-linux-x64": "0.0.37",
"bun-cli-mac": "0.0.37"
},
"repository": "https://github.com/jarred-sumner/bun",
"scripts": {},
"version": "0.0.37"
}

View File

@@ -1,13 +0,0 @@
#!/usr/bin/env node
throw new Error(`bun-cli: Failed to install correctly
Make sure you don't have "ignore-scripts" set to true. You can check this with
"npm config get ignore-scripts". If that returns true you can reset it back to
false using "npm config set ignore-scripts false" and then reinstall bun.
If you're using npm v7, make sure your package-lock.json file contains either
"lockfileVersion": 1 or the code "hasInstallScript": true. If it doesn't have
either of those, then it is likely the case that a known bug in npm v7 has
corrupted your package-lock.json file. Regenerating your package-lock.json file
should fix this issue.
`);

View File

@@ -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,
};
};

138
src/cli/install.sh Normal file
View File

@@ -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"

View File

@@ -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();

495
src/cli/upgrade_command.zig Normal file
View File

@@ -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;
}
}
};

View File

@@ -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",
};