From ea65d7903fac872ded486e9df83e05d25e0804e4 Mon Sep 17 00:00:00 2001 From: Claude Bot Date: Sun, 12 Oct 2025 02:59:08 +0000 Subject: [PATCH] fix: prefer bun.lock over bun.lockb when migrating lockfiles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When migrating from npm/yarn/pnpm lockfiles, Bun was incorrectly setting the lockfile format to binary (.lockb) in both success and error cases. This caused Bun to create bun.lockb instead of the preferred bun.lock format. This change ensures that all migration paths (npm, yarn, pnpm) return .format = .text instead of .format = .binary, causing Bun to create bun.lock files as expected. Changes: - src/install/migration.zig: Changed error paths for npm, yarn, and pnpm migrations to return .format = .text - src/install/migration.zig: Changed npm successful migration path to return .format = .text - src/install/yarn.zig: Changed yarn successful migration path to return .format = .text - test/regression/issue/migration-lockfile-format.test.ts: Added regression tests to verify lockfile format after migration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/install/migration.zig | 8 +- src/install/yarn.zig | 2 +- .../issue/migration-lockfile-format.test.ts | 132 ++++++++++++++++++ 3 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 test/regression/issue/migration-lockfile-format.test.ts diff --git a/src/install/migration.zig b/src/install/migration.zig index 888cac4d2c..7659779984 100644 --- a/src/install/migration.zig +++ b/src/install/migration.zig @@ -30,7 +30,7 @@ pub fn detectAndLoadOtherLockfile( .step = .migrating, .value = err, .lockfile_path = "package-lock.json", - .format = .binary, + .format = .text, } }; }; @@ -54,7 +54,7 @@ pub fn detectAndLoadOtherLockfile( .step = .migrating, .value = err, .lockfile_path = "yarn.lock", - .format = .binary, + .format = .text, } }; }; @@ -126,7 +126,7 @@ pub fn detectAndLoadOtherLockfile( .step = .migrating, .value = err, .lockfile_path = "pnpm-lock.yaml", - .format = .binary, + .format = .text, } }; }; @@ -1089,7 +1089,7 @@ pub fn migrateNPMLockfile( .migrated = .npm, .loaded_from_binary_lockfile = false, .serializer_result = .{}, - .format = .binary, + .format = .text, }, }; } diff --git a/src/install/yarn.zig b/src/install/yarn.zig index 6baaf5e9cb..fbf9e66737 100644 --- a/src/install/yarn.zig +++ b/src/install/yarn.zig @@ -1684,7 +1684,7 @@ pub fn migrateYarnLockfile( .migrated = .yarn, .loaded_from_binary_lockfile = false, .serializer_result = .{}, - .format = .binary, + .format = .text, } }; return result; diff --git a/test/regression/issue/migration-lockfile-format.test.ts b/test/regression/issue/migration-lockfile-format.test.ts new file mode 100644 index 0000000000..db4c1ac95d --- /dev/null +++ b/test/regression/issue/migration-lockfile-format.test.ts @@ -0,0 +1,132 @@ +import { expect, test } from "bun:test"; +import { existsSync } from "fs"; +import { bunEnv, bunExe, tempDir } from "harness"; +import { join } from "path"; + +test("failing to migrate pnpm-lock.yaml should create bun.lock not bun.lockb", async () => { + using dir = tempDir("pnpm-migration-format", { + "package.json": JSON.stringify({ + name: "test", + version: "1.0.0", + dependencies: { + "is-even": "1.0.0", + }, + }), + // Create an invalid pnpm-lock.yaml that will fail to migrate + "pnpm-lock.yaml": `lockfileVersion: '9.0' +importers: + .: + dependencies: + is-even: + specifier: 1.0.0 + version: 1.0.0 +packages: + /is-even@1.0.0: + resolution: {integrity: sha512-invalid-integrity} + engines: {node: '>=0.10.0'} +`, + }); + + const result = await Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: String(dir), + env: bunEnv, + stderr: "pipe", + stdout: "pipe", + }).exited; + + // After failed migration, bun.lock should exist (not bun.lockb) + const bunLockPath = join(String(dir), "bun.lock"); + const bunLockbPath = join(String(dir), "bun.lockb"); + + expect(existsSync(bunLockPath)).toBe(true); + expect(existsSync(bunLockbPath)).toBe(false); +}); + +// Note: This test verifies the fix but may pass even if migration succeeds +// The key fix is that error paths return .format = .text instead of .format = .binary +test("after yarn.lock exists, bun install should create bun.lock not bun.lockb", async () => { + using dir = tempDir("yarn-migration-format", { + "package.json": JSON.stringify({ + name: "test", + version: "1.0.0", + dependencies: { + "is-number": "7.0.0", + }, + }), + // Create a valid yarn.lock to ensure migration happens + "yarn.lock": `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + +is-number@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +`, + }); + + await Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: String(dir), + env: bunEnv, + stderr: "pipe", + stdout: "pipe", + }).exited; + + // After migration, bun.lock should exist (not bun.lockb) + const bunLockPath = join(String(dir), "bun.lock"); + const bunLockbPath = join(String(dir), "bun.lockb"); + + expect(existsSync(bunLockPath)).toBe(true); + expect(existsSync(bunLockbPath)).toBe(false); +}); + +test("successful migration from package-lock.json should create bun.lock not bun.lockb", async () => { + using dir = tempDir("npm-migration-format", { + "package.json": JSON.stringify({ + name: "test", + version: "1.0.0", + dependencies: { + "is-number": "7.0.0", + }, + }), + "package-lock.json": JSON.stringify({ + name: "test", + version: "1.0.0", + lockfileVersion: 3, + requires: true, + packages: { + "": { + name: "test", + version: "1.0.0", + dependencies: { + "is-number": "7.0.0", + }, + }, + "node_modules/is-number": { + version: "7.0.0", + resolved: "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + integrity: "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + engines: { + node: ">=0.12.0", + }, + }, + }, + }), + }); + + const result = await Bun.spawn({ + cmd: [bunExe(), "install"], + cwd: String(dir), + env: bunEnv, + stderr: "pipe", + stdout: "pipe", + }).exited; + + // After successful migration, bun.lock should exist (not bun.lockb) + const bunLockPath = join(String(dir), "bun.lock"); + const bunLockbPath = join(String(dir), "bun.lockb"); + + expect(existsSync(bunLockPath)).toBe(true); + expect(existsSync(bunLockbPath)).toBe(false); +});