diff --git a/src/install/PackageManager/PackageManagerEnqueue.zig b/src/install/PackageManager/PackageManagerEnqueue.zig index 9df5508e74..d7bea30549 100644 --- a/src/install/PackageManager/PackageManagerEnqueue.zig +++ b/src/install/PackageManager/PackageManagerEnqueue.zig @@ -1611,6 +1611,31 @@ fn getOrPutResolvedPackage( } } } + } else if (version.tag == .dist_tag) { + if (this.options.link_workspace_packages) { + const workspace_path = if (this.lockfile.workspace_paths.count() > 0) + this.lockfile.workspace_paths.get(name_hash) + else + null; + if (workspace_path != null) { + const root_package = this.lockfile.rootPackage() orelse break :resolve_from_workspace; + const root_dependencies = root_package.dependencies.get(this.lockfile.buffers.dependencies.items); + const root_resolutions = root_package.resolutions.get(this.lockfile.buffers.resolutions.items); + + for (root_dependencies, root_resolutions) |root_dep, workspace_package_id| { + if (workspace_package_id != invalid_package_id and + root_dep.version.tag == .workspace and + root_dep.name_hash == name_hash) + { + successFn(this, dependency_id, workspace_package_id); + return .{ + .package = this.lockfile.packages.get(workspace_package_id), + .is_first_time = false, + }; + } + } + } + } } } diff --git a/src/install/lockfile/Package.zig b/src/install/lockfile/Package.zig index 48c8970699..39f0fad0f4 100644 --- a/src/install/lockfile/Package.zig +++ b/src/install/lockfile/Package.zig @@ -1121,6 +1121,24 @@ pub fn Package(comptime SemverIntType: type) type { } } }, + .dist_tag => { + if (workspace_path != null and pm.options.link_workspace_packages) { + const path = workspace_path.?.sliced(buf); + if (Dependency.parseWithTag( + allocator, + external_alias.value, + external_alias.hash, + path.slice, + .workspace, + &path, + log, + pm, + )) |dep| { + dependency_version.tag = dep.tag; + dependency_version.value = dep.value; + } + } + }, .workspace => workspace: { if (workspace_path) |path| { if (workspace_range) |range| { diff --git a/test/cli/install/__snapshots__/bun-workspaces.test.ts.snap b/test/cli/install/__snapshots__/bun-workspaces.test.ts.snap index ac3d396fea..cb0ab5362a 100644 --- a/test/cli/install/__snapshots__/bun-workspaces.test.ts.snap +++ b/test/cli/install/__snapshots__/bun-workspaces.test.ts.snap @@ -738,6 +738,252 @@ exports[`dependency on workspace without version in package.json: version: *-pre }" `; +exports[`dependency on workspace without version in package.json: version: latest 1`] = ` +"{ + "format": "v3", + "meta_hash": "0000000000000000000000000000000000000000000000000000000000000000", + "package_index": { + "no-deps": 2, + "foo": 0, + "bar": 1 + }, + "trees": [ + { + "id": 0, + "path": "node_modules", + "depth": 0, + "dependencies": { + "bar": { + "id": 0, + "package_id": 1 + }, + "no-deps": { + "id": 1, + "package_id": 2 + } + } + } + ], + "dependencies": [ + { + "name": "bar", + "literal": "", + "workspace": "packages/bar", + "package_id": 1, + "behavior": { + "workspace": true + }, + "id": 0 + }, + { + "name": "no-deps", + "literal": "", + "workspace": "packages/mono", + "package_id": 2, + "behavior": { + "workspace": true + }, + "id": 1 + }, + { + "name": "no-deps", + "literal": "latest", + "workspace": "packages/mono", + "package_id": 2, + "behavior": { + "prod": true + }, + "id": 2 + } + ], + "packages": [ + { + "id": 0, + "name": "foo", + "name_hash": "14841791273925386894", + "resolution": { + "tag": "root", + "value": "", + "resolved": "" + }, + "dependencies": [ + 0, + 1 + ], + "integrity": null, + "man_dir": "", + "origin": "local", + "bin": null, + "scripts": {} + }, + { + "id": 1, + "name": "bar", + "name_hash": "11592711315645265694", + "resolution": { + "tag": "workspace", + "value": "workspace:packages/bar", + "resolved": "workspace:packages/bar" + }, + "dependencies": [ + 2 + ], + "integrity": null, + "man_dir": "", + "origin": "npm", + "bin": null, + "scripts": {} + }, + { + "id": 2, + "name": "no-deps", + "name_hash": "5128161233225832376", + "resolution": { + "tag": "workspace", + "value": "workspace:packages/mono", + "resolved": "workspace:packages/mono" + }, + "dependencies": [], + "integrity": null, + "man_dir": "", + "origin": "npm", + "bin": null, + "scripts": {} + } + ], + "workspace_paths": { + "11592711315645265694": "packages/bar", + "5128161233225832376": "packages/mono" + }, + "workspace_versions": { + "11592711315645265694": "1.0.0" + } +}" +`; + +exports[`dependency on workspace without version in package.json: version: 1`] = ` +"{ + "format": "v3", + "meta_hash": "0000000000000000000000000000000000000000000000000000000000000000", + "package_index": { + "no-deps": 2, + "foo": 0, + "bar": 1 + }, + "trees": [ + { + "id": 0, + "path": "node_modules", + "depth": 0, + "dependencies": { + "bar": { + "id": 0, + "package_id": 1 + }, + "no-deps": { + "id": 1, + "package_id": 2 + } + } + } + ], + "dependencies": [ + { + "name": "bar", + "literal": "", + "workspace": "packages/bar", + "package_id": 1, + "behavior": { + "workspace": true + }, + "id": 0 + }, + { + "name": "no-deps", + "literal": "", + "workspace": "packages/mono", + "package_id": 2, + "behavior": { + "workspace": true + }, + "id": 1 + }, + { + "name": "no-deps", + "literal": "", + "workspace": "packages/mono", + "package_id": 2, + "behavior": { + "prod": true + }, + "id": 2 + } + ], + "packages": [ + { + "id": 0, + "name": "foo", + "name_hash": "14841791273925386894", + "resolution": { + "tag": "root", + "value": "", + "resolved": "" + }, + "dependencies": [ + 0, + 1 + ], + "integrity": null, + "man_dir": "", + "origin": "local", + "bin": null, + "scripts": {} + }, + { + "id": 1, + "name": "bar", + "name_hash": "11592711315645265694", + "resolution": { + "tag": "workspace", + "value": "workspace:packages/bar", + "resolved": "workspace:packages/bar" + }, + "dependencies": [ + 2 + ], + "integrity": null, + "man_dir": "", + "origin": "npm", + "bin": null, + "scripts": {} + }, + { + "id": 2, + "name": "no-deps", + "name_hash": "5128161233225832376", + "resolution": { + "tag": "workspace", + "value": "workspace:packages/mono", + "resolved": "workspace:packages/mono" + }, + "dependencies": [], + "integrity": null, + "man_dir": "", + "origin": "npm", + "bin": null, + "scripts": {} + } + ], + "workspace_paths": { + "11592711315645265694": "packages/bar", + "5128161233225832376": "packages/mono" + }, + "workspace_versions": { + "11592711315645265694": "1.0.0" + } +}" +`; + exports[`dependency on workspace without version in package.json: version: 1 1`] = ` "{ "format": "v3", @@ -1674,327 +1920,12 @@ exports[`dependency on workspace without version in package.json: version: *+bui }" `; -exports[`dependency on workspace without version in package.json: version: latest 1`] = ` -"{ - "format": "v3", - "meta_hash": "0000000000000000000000000000000000000000000000000000000000000000", - "package_index": { - "no-deps": [ - 2, - 3 - ], - "foo": 0, - "bar": 1 - }, - "trees": [ - { - "id": 0, - "path": "node_modules", - "depth": 0, - "dependencies": { - "bar": { - "id": 0, - "package_id": 1 - }, - "no-deps": { - "id": 1, - "package_id": 2 - } - } - }, - { - "id": 1, - "path": "node_modules/bar/node_modules", - "depth": 1, - "dependencies": { - "no-deps": { - "id": 2, - "package_id": 3 - } - } - } - ], - "dependencies": [ - { - "name": "bar", - "literal": "", - "workspace": "packages/bar", - "package_id": 1, - "behavior": { - "workspace": true - }, - "id": 0 - }, - { - "name": "no-deps", - "literal": "", - "workspace": "packages/mono", - "package_id": 2, - "behavior": { - "workspace": true - }, - "id": 1 - }, - { - "name": "no-deps", - "literal": "latest", - "dist_tag": { - "name": "no-deps", - "tag": "no-deps" - }, - "package_id": 3, - "behavior": { - "prod": true - }, - "id": 2 - } - ], - "packages": [ - { - "id": 0, - "name": "foo", - "name_hash": "14841791273925386894", - "resolution": { - "tag": "root", - "value": "", - "resolved": "" - }, - "dependencies": [ - 0, - 1 - ], - "integrity": null, - "man_dir": "", - "origin": "local", - "bin": null, - "scripts": {} - }, - { - "id": 1, - "name": "bar", - "name_hash": "11592711315645265694", - "resolution": { - "tag": "workspace", - "value": "workspace:packages/bar", - "resolved": "workspace:packages/bar" - }, - "dependencies": [ - 2 - ], - "integrity": null, - "man_dir": "", - "origin": "npm", - "bin": null, - "scripts": {} - }, - { - "id": 2, - "name": "no-deps", - "name_hash": "5128161233225832376", - "resolution": { - "tag": "workspace", - "value": "workspace:packages/mono", - "resolved": "workspace:packages/mono" - }, - "dependencies": [], - "integrity": null, - "man_dir": "", - "origin": "npm", - "bin": null, - "scripts": {} - }, - { - "id": 3, - "name": "no-deps", - "name_hash": "5128161233225832376", - "resolution": { - "tag": "npm", - "value": "2.0.0", - "resolved": "http://localhost:1234/no-deps/-/no-deps-2.0.0.tgz" - }, - "dependencies": [], - "integrity": "sha512-W3duJKZPcMIG5rA1io5cSK/bhW9rWFz+jFxZsKS/3suK4qHDkQNxUTEXee9/hTaAoDCeHWQqogukWYKzfr6X4g==", - "man_dir": "", - "origin": "npm", - "bin": null, - "scripts": {} - } - ], - "workspace_paths": { - "11592711315645265694": "packages/bar", - "5128161233225832376": "packages/mono" - }, - "workspace_versions": { - "11592711315645265694": "1.0.0" - } -}" -`; - -exports[`dependency on workspace without version in package.json: version: 1`] = ` -"{ - "format": "v3", - "meta_hash": "0000000000000000000000000000000000000000000000000000000000000000", - "package_index": { - "no-deps": [ - 2, - 3 - ], - "foo": 0, - "bar": 1 - }, - "trees": [ - { - "id": 0, - "path": "node_modules", - "depth": 0, - "dependencies": { - "bar": { - "id": 0, - "package_id": 1 - }, - "no-deps": { - "id": 1, - "package_id": 2 - } - } - }, - { - "id": 1, - "path": "node_modules/bar/node_modules", - "depth": 1, - "dependencies": { - "no-deps": { - "id": 2, - "package_id": 3 - } - } - } - ], - "dependencies": [ - { - "name": "bar", - "literal": "", - "workspace": "packages/bar", - "package_id": 1, - "behavior": { - "workspace": true - }, - "id": 0 - }, - { - "name": "no-deps", - "literal": "", - "workspace": "packages/mono", - "package_id": 2, - "behavior": { - "workspace": true - }, - "id": 1 - }, - { - "name": "no-deps", - "literal": "", - "dist_tag": { - "name": "no-deps", - "tag": "no-deps" - }, - "package_id": 3, - "behavior": { - "prod": true - }, - "id": 2 - } - ], - "packages": [ - { - "id": 0, - "name": "foo", - "name_hash": "14841791273925386894", - "resolution": { - "tag": "root", - "value": "", - "resolved": "" - }, - "dependencies": [ - 0, - 1 - ], - "integrity": null, - "man_dir": "", - "origin": "local", - "bin": null, - "scripts": {} - }, - { - "id": 1, - "name": "bar", - "name_hash": "11592711315645265694", - "resolution": { - "tag": "workspace", - "value": "workspace:packages/bar", - "resolved": "workspace:packages/bar" - }, - "dependencies": [ - 2 - ], - "integrity": null, - "man_dir": "", - "origin": "npm", - "bin": null, - "scripts": {} - }, - { - "id": 2, - "name": "no-deps", - "name_hash": "5128161233225832376", - "resolution": { - "tag": "workspace", - "value": "workspace:packages/mono", - "resolved": "workspace:packages/mono" - }, - "dependencies": [], - "integrity": null, - "man_dir": "", - "origin": "npm", - "bin": null, - "scripts": {} - }, - { - "id": 3, - "name": "no-deps", - "name_hash": "5128161233225832376", - "resolution": { - "tag": "npm", - "value": "2.0.0", - "resolved": "http://localhost:1234/no-deps/-/no-deps-2.0.0.tgz" - }, - "dependencies": [], - "integrity": "sha512-W3duJKZPcMIG5rA1io5cSK/bhW9rWFz+jFxZsKS/3suK4qHDkQNxUTEXee9/hTaAoDCeHWQqogukWYKzfr6X4g==", - "man_dir": "", - "origin": "npm", - "bin": null, - "scripts": {} - } - ], - "workspace_paths": { - "11592711315645265694": "packages/bar", - "5128161233225832376": "packages/mono" - }, - "workspace_versions": { - "11592711315645265694": "1.0.0" - } -}" -`; - exports[`dependency on same name as workspace and dist-tag: with version 1`] = ` "{ "format": "v3", "meta_hash": "0000000000000000000000000000000000000000000000000000000000000000", "package_index": { - "no-deps": [ - 2, - 3 - ], + "no-deps": 2, "foo": 0, "bar": 1 }, @@ -2013,17 +1944,6 @@ exports[`dependency on same name as workspace and dist-tag: with version 1`] = ` "package_id": 2 } } - }, - { - "id": 1, - "path": "node_modules/bar/node_modules", - "depth": 1, - "dependencies": { - "no-deps": { - "id": 2, - "package_id": 3 - } - } } ], "dependencies": [ @@ -2050,11 +1970,8 @@ exports[`dependency on same name as workspace and dist-tag: with version 1`] = ` { "name": "no-deps", "literal": "latest", - "dist_tag": { - "name": "no-deps", - "tag": "no-deps" - }, - "package_id": 3, + "workspace": "packages/mono", + "package_id": 2, "behavior": { "prod": true }, @@ -2114,22 +2031,6 @@ exports[`dependency on same name as workspace and dist-tag: with version 1`] = ` "origin": "npm", "bin": null, "scripts": {} - }, - { - "id": 3, - "name": "no-deps", - "name_hash": "5128161233225832376", - "resolution": { - "tag": "npm", - "value": "2.0.0", - "resolved": "http://localhost:1234/no-deps/-/no-deps-2.0.0.tgz" - }, - "dependencies": [], - "integrity": "sha512-W3duJKZPcMIG5rA1io5cSK/bhW9rWFz+jFxZsKS/3suK4qHDkQNxUTEXee9/hTaAoDCeHWQqogukWYKzfr6X4g==", - "man_dir": "", - "origin": "npm", - "bin": null, - "scripts": {} } ], "workspace_paths": { diff --git a/test/cli/install/bun-workspaces.test.ts b/test/cli/install/bun-workspaces.test.ts index b1a0a59ec3..4de1fac14c 100644 --- a/test/cli/install/bun-workspaces.test.ts +++ b/test/cli/install/bun-workspaces.test.ts @@ -66,17 +66,10 @@ test("dependency on workspace without version in package.json", async () => { "kjwoehcojrgjoj", // dist-tag does not exist, should choose local workspace "*.1.*", "*-pre", + "latest", // dist-tag exists, should choose local workspace + "", // empty string is treated as "latest" dist tag, should choose local workspace ]; - const shouldNotWork: string[] = [ - "1", - "1.*", - "1.1.*", - "1.1.0", - "*-pre+build", - "*+build", - "latest", // dist-tag exists, should choose package from npm - "", - ]; + const shouldNotWork: string[] = ["1", "1.*", "1.1.*", "1.1.0", "*-pre+build", "*+build"]; for (const version of shouldWork) { writeFileSync( @@ -213,7 +206,7 @@ test("dependency on same name as workspace and dist-tag", async () => { expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ expect.stringContaining("bun install v1."), "", - "3 packages installed", + "2 packages installed", ]); });