Compare commits

...

7 Commits

Author SHA1 Message Date
RiskyMH
54e471b39b Merge remote-tracking branch 'origin/main' into riskymh/upgrade-fix
# Conflicts:
#	test/cli/install/bun-upgrade.test.ts
2025-12-01 16:19:10 +11:00
RiskyMH
a5d81c9815 okokok should be simpler & better 2025-06-13 19:31:10 +10:00
RiskyMH
4e8252da9d oops 2025-06-13 18:40:39 +10:00
RiskyMH
471b423ec8 Update bun-upgrade.test.ts 2025-06-13 18:29:46 +10:00
RiskyMH
a851b4b6a6 simpler tests 2025-06-13 18:28:29 +10:00
RiskyMH
c5981b4211 better tests 2025-06-13 17:53:14 +10:00
RiskyMH
fbaf63af42 make the bun upgrade <package name> error better 2025-06-13 15:41:51 +10:00
2 changed files with 83 additions and 48 deletions

View File

@@ -320,18 +320,39 @@ pub const UpgradeCommand = struct {
const args = bun.argv;
if (args.len > 2) {
for (args[2..]) |arg| {
if (!strings.contains(arg, "--")) {
Output.prettyError(
\\<r><red>error<r><d>:<r> This command updates Bun itself, and does not take package names.
\\<blue>note<r><d>:<r> Use `bun update
, .{});
for (args[2..]) |arg_err| {
Output.prettyError(" {s}", .{arg_err});
var upgrade_index: ?usize = null;
for (args[1..], 1..) |arg, i| {
// if this is after "upgrade", it needs to be one of the specific flags
// otherwise, just verify that it's a flag (because BUN_OPTIONS are passed here)
if (upgrade_index) |_| {
if (strings.eqlComptime(arg, "--canary") or
strings.eqlComptime(arg, "--profile") or
strings.eqlComptime(arg, "--stable"))
{
continue;
}
} else {
if (strings.startsWith(arg, "--")) continue;
if (strings.eqlComptime(arg, "upgrade")) {
upgrade_index = i;
continue;
}
Output.prettyErrorln("` instead.", .{});
Global.exit(1);
}
Output.prettyError(
\\<r><red>error<r><d>:<r> This command updates Bun itself, and does not take package names.
\\<blue>note<r><d>:<r> Use `bun update
, .{});
const index = upgrade_index orelse 2;
for (args, 0..) |arg_err, _i| {
if (_i == 0 or _i == index) continue;
Output.prettyError(" {s}", .{arg_err});
}
Output.prettyErrorln("` instead.", .{});
Global.exit(1);
}
}

View File

@@ -1,7 +1,7 @@
import { spawn, spawnSync } from "bun";
import { upgrade_test_helpers } from "bun:internal-for-testing";
import { beforeAll, beforeEach, expect, it, setDefaultTimeout } from "bun:test";
import { bunExe, bunEnv as env, tls, tmpdirSync } from "harness";
import { bunEnv, bunExe, tls, tmpdirSync } from "harness";
import { copyFileSync } from "node:fs";
import { basename, join } from "path";
const { openTempDirWithoutSharingDelete, closeTempDirHandle } = upgrade_test_helpers;
@@ -19,52 +19,66 @@ beforeEach(async () => {
copyFileSync(bunExe(), execPath);
});
it("two invalid arguments, should display error message and suggest command", async () => {
// just a useless one to see that it bypassed the `bun upgrade <...>` -> `bun update <...>` check
using server = Bun.serve({
tls: tls,
port: 0,
async fetch() {
return Response.json({});
},
});
const env = {
...bunEnv,
NODE_TLS_REJECT_UNAUTHORIZED: "0",
GITHUB_API_DOMAIN: `${server.hostname}:${server.port}`,
};
const invalid_tests = [
[["upgrade", "bun-types", "--dev"], "bun update bun-types --dev"],
[["upgrade", "bun-types"], "bun update bun-types"],
[["upgrade", "--dev", "bun-types"], "bun update --dev bun-types"],
[["--dev", "upgrade", "bun-types", "--stable"], "bun update --dev bun-types --stable"],
[["upgrade", "upgrade"], "bun update upgrade"],
[["upgrade", "--latest"], "bun update --latest"],
];
for (const [args, expected] of invalid_tests) {
it(`"${args.join(" ")}": should display error message and suggest command`, async () => {
const { stderr } = spawn({
cmd: [execPath, ...args],
cwd,
stdout: null,
stdin: "pipe",
stderr: "pipe",
env,
});
const err = await new Response(stderr).text();
expect(err.split(/\r?\n/)).toContain("error: This command updates Bun itself, and does not take package names.");
expect(err.split(/\r?\n/)).toContain(`note: Use \`${expected}\` instead.`);
});
}
it("one flag with BUN_OPTIONS, should succeed", async () => {
const { stderr } = spawn({
cmd: [execPath, "upgrade", "bun-types", "--dev"],
cmd: [execPath, "upgrade"],
cwd,
stdout: null,
stdin: "pipe",
stderr: "pipe",
env,
env: {
...env,
BUN_OPTIONS: "--bun",
},
});
const err = await stderr.text();
expect(err.split(/\r?\n/)).toContain("error: This command updates Bun itself, and does not take package names.");
expect(err.split(/\r?\n/)).toContain("note: Use `bun update bun-types --dev` instead.");
const err = await new Response(stderr).text();
// Should not contain error message
expect(err.split(/\r?\n/)).not.toContain("error: This command updates Bun itself, and does not take package names.");
expect(err.split(/\r?\n/)).not.toContain("note: Use `bun update` instead.");
});
it("two invalid arguments flipped, should display error message and suggest command", async () => {
const { stderr } = spawn({
cmd: [execPath, "upgrade", "--dev", "bun-types"],
cwd,
stdout: null,
stdin: "pipe",
stderr: "pipe",
env,
});
const err = await stderr.text();
expect(err.split(/\r?\n/)).toContain("error: This command updates Bun itself, and does not take package names.");
expect(err.split(/\r?\n/)).toContain("note: Use `bun update --dev bun-types` instead.");
});
it("one invalid argument, should display error message and suggest command", async () => {
const { stderr } = spawn({
cmd: [execPath, "upgrade", "bun-types"],
cwd,
stdout: null,
stdin: "pipe",
stderr: "pipe",
env,
});
const err = await stderr.text();
expect(err.split(/\r?\n/)).toContain("error: This command updates Bun itself, and does not take package names.");
expect(err.split(/\r?\n/)).toContain("note: Use `bun update bun-types` instead.");
});
it("one valid argument, should succeed", async () => {
it("one valid flag, should succeed", async () => {
const { stderr } = spawn({
cmd: [execPath, "upgrade", "--help"],
cwd,