diff --git a/src/install/dependency.zig b/src/install/dependency.zig index 314e364d9e..68bbcdfeb6 100644 --- a/src/install/dependency.zig +++ b/src/install/dependency.zig @@ -400,7 +400,7 @@ pub const Version = struct { // ^1.2.3 // * // || 1.x - '=', '>', '<', '^', '*', '|' => return .npm, + '=', '>', '<', '^', '*', '|', '&' => return .npm, // ./foo.tgz // ./path/to/foo // ../path/to/bar @@ -615,7 +615,12 @@ pub const Version = struct { // git@example.com:path/to/repo.git if (isSCPLikePath(dependency)) return .git; // beta - return .dist_tag; + + if (!strings.containsChar(dependency, '|') and !strings.containsChar(dependency, '&')) { + return .dist_tag; + } + + return .npm; } }; diff --git a/src/install/semver.zig b/src/install/semver.zig index e9fa11ef8f..45519f5b57 100644 --- a/src/install/semver.zig +++ b/src/install/semver.zig @@ -1941,6 +1941,9 @@ pub const Query = struct { else => { i += 1; token.tag = Token.Tag.none; + + // skip tagged versions + while (i < input.len and input[i] != ' ') : (i += 1) {} skip_round = true; }, } diff --git a/test/cli/install/registry/bun-install-registry.test.ts b/test/cli/install/registry/bun-install-registry.test.ts index 53a6c33c87..b56d4d3934 100644 --- a/test/cli/install/registry/bun-install-registry.test.ts +++ b/test/cli/install/registry/bun-install-registry.test.ts @@ -214,6 +214,89 @@ test("package added after install", async () => { } as any); }); +describe("semver", () => { + const taggedVersionTests = [ + { + title: "tagged version last in range", + depVersion: "1 || 2 || pre-3", + expected: "2.0.1", + }, + { + title: "tagged version in middle of range", + depVersion: "1 || pre-3 || 2", + expected: "2.0.1", + }, + { + title: "tagged version first in range", + depVersion: "pre-3 || 2 || 1", + expected: "2.0.1", + }, + { + title: "multiple tagged versions in range", + depVersion: "pre-3 || 2 || pre-1 || 1 || 3 || pre-3", + expected: "3.0.0", + }, + { + title: "start with &&", + depVersion: "&& 1", + expected: "1.0.1", + }, + { + title: "start with ||", + depVersion: "|| 1", + expected: "1.0.1", + }, + { + title: "start with || no space", + depVersion: "||2", + expected: "2.0.1", + }, + { + title: "|| with no space on both sides", + depVersion: "1||2", + expected: "2.0.1", + }, + ]; + + for (const { title, depVersion, expected } of taggedVersionTests) { + test(title, async () => { + await writeFile( + join(packageDir, "package.json"), + JSON.stringify({ + name: "foo", + version: "1.0.0", + dependencies: { + "dep-with-tags": depVersion, + }, + }), + ); + + var { stdout, stderr, exited } = spawn({ + cmd: [bunExe(), "install"], + cwd: packageDir, + stdout: null, + stdin: "pipe", + stderr: "pipe", + env, + }); + + expect(stderr).toBeDefined(); + var err = await new Response(stderr).text(); + expect(stdout).toBeDefined(); + var out = await new Response(stdout).text(); + expect(await exited).toBe(0); + expect(err).toContain("Saved lockfile"); + expect(err).not.toContain("not found"); + expect(err).not.toContain("error:"); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + ` + dep-with-tags@${expected}`, + "", + " 1 package installed", + ]); + }); + } +}); + describe("prereleases", () => { const prereleaseTests = [ [ diff --git a/test/cli/install/registry/packages/.verdaccio-db.json b/test/cli/install/registry/packages/.verdaccio-db.json index 619a0d7eba..fca64c97c5 100644 --- a/test/cli/install/registry/packages/.verdaccio-db.json +++ b/test/cli/install/registry/packages/.verdaccio-db.json @@ -1 +1 @@ -{"list":["basic-1","@babel/parser","@babel/traverse","@private/has-bin-entry","@private/package","@private/unconventional-tarball","@scoped/create-test-app","@scoped/has-bin-entry","@types/babel__traverse","@types/is-number","@types/no-deps","binding-gyp-scripts","broken-peer-deps","create-test-app","dep-loop-entry","dep-loop-exit","dev-deps","dragon-test-1-a","dragon-test-1-b","dragon-test-1-c","dragon-test-1-d","dragon-test-1-e","dragon-test-3-a","dragon-test-3-b","dragon-test-7-a","dragon-test-7-b","dragon-test-7-c","dragon-test-7-d","dragon-test-8-a","dragon-test-8-b","dragon-test-8-c","dragon-test-8-d","dragon-test-11-a","dragon-test-11-b","fallback-peer-deps","forward-peer-deps","forward-peer-deps-too","has-bin-entries","has-symlinks","has-types","hoisting-peer-check-child","hoisting-peer-check-parent","inject-node-gyp","invalid-main","is-number","left-pad","mismatched-peer-deps-lvl0","mismatched-peer-deps-lvl1","mismatched-peer-deps-lvl2","native","native-bar-x64","native-foo-x64","native-foo-x86","native-libc-glibc","native-libc-musl","no-deps","no-deps-backward-tags","no-deps-bins","no-deps-bins-esm","no-deps-browser-field","no-deps-build-metadata","no-deps-checked","no-deps-deprecated","no-deps-deprecated-empty","no-deps-deprecated-whitespace","no-deps-esm","no-deps-exports","no-deps-failing","no-deps-mjs","no-deps-nested-postinstall","no-deps-scripted","no-deps-scripted-bis","no-deps-scripted-empty","no-deps-scripted-to-fail","no-deps-scripted-to-deeply-fail","no-deps-tags","node-gyp","node-modules-path","one-deep1-dep-bins","one-deep2-dep-bins","one-dep-scripted","one-fixed-dep","one-fixed-dep-bins","one-fixed-dep-checked","one-fixed-dep-scripted","one-fixed-dep-with-types","one-range-dep","one-range-dep-too","optional-native","optional-peer-deps","optional-peer-deps-implicit","path-parse","peer-deps","peer-deps-fixed","peer-deps-lvl0","peer-deps-lvl1","peer-deps-lvl2","peer-deps-too","prefer-unplugged-false","prefer-unplugged-true","private-package","private-unconventional-tarball","provides-peer-deps-1-0-0","provides-peer-deps-1-0-0-too","provides-peer-deps-2-0-0","resolve","self-require-dep","self-require-trap","two-range-deps","unconventional-tarball","various-requires","vulnerable","vulnerable-dep","vulnerable-many","vulnerable-peer-deps","prereleases-1","prereleases-2"],"secret":"4f8fdf3ae3425c5661cbdd85990a5f44365b989c3c6f478ed48ccf5bae9e14b1"} \ No newline at end of file +{"list":["basic-1","@babel/parser","@babel/traverse","@private/has-bin-entry","@private/package","@private/unconventional-tarball","@scoped/create-test-app","@scoped/has-bin-entry","@types/babel__traverse","@types/is-number","@types/no-deps","binding-gyp-scripts","broken-peer-deps","create-test-app","dep-loop-entry","dep-loop-exit","dev-deps","dragon-test-1-a","dragon-test-1-b","dragon-test-1-c","dragon-test-1-d","dragon-test-1-e","dragon-test-3-a","dragon-test-3-b","dragon-test-7-a","dragon-test-7-b","dragon-test-7-c","dragon-test-7-d","dragon-test-8-a","dragon-test-8-b","dragon-test-8-c","dragon-test-8-d","dragon-test-11-a","dragon-test-11-b","fallback-peer-deps","forward-peer-deps","forward-peer-deps-too","has-bin-entries","has-symlinks","has-types","hoisting-peer-check-child","hoisting-peer-check-parent","inject-node-gyp","invalid-main","is-number","left-pad","mismatched-peer-deps-lvl0","mismatched-peer-deps-lvl1","mismatched-peer-deps-lvl2","native","native-bar-x64","native-foo-x64","native-foo-x86","native-libc-glibc","native-libc-musl","no-deps","no-deps-backward-tags","no-deps-bins","no-deps-bins-esm","no-deps-browser-field","no-deps-build-metadata","no-deps-checked","no-deps-deprecated","no-deps-deprecated-empty","no-deps-deprecated-whitespace","no-deps-esm","no-deps-exports","no-deps-failing","no-deps-mjs","no-deps-nested-postinstall","no-deps-scripted","no-deps-scripted-bis","no-deps-scripted-empty","no-deps-scripted-to-fail","no-deps-scripted-to-deeply-fail","no-deps-tags","node-gyp","node-modules-path","one-deep1-dep-bins","one-deep2-dep-bins","one-dep-scripted","one-fixed-dep","one-fixed-dep-bins","one-fixed-dep-checked","one-fixed-dep-scripted","one-fixed-dep-with-types","one-range-dep","one-range-dep-too","optional-native","optional-peer-deps","optional-peer-deps-implicit","path-parse","peer-deps","peer-deps-fixed","peer-deps-lvl0","peer-deps-lvl1","peer-deps-lvl2","peer-deps-too","prefer-unplugged-false","prefer-unplugged-true","private-package","private-unconventional-tarball","provides-peer-deps-1-0-0","provides-peer-deps-1-0-0-too","provides-peer-deps-2-0-0","resolve","self-require-dep","self-require-trap","two-range-deps","unconventional-tarball","various-requires","vulnerable","vulnerable-dep","vulnerable-many","vulnerable-peer-deps","prereleases-1","prereleases-2","dep-with-tags"],"secret":"4f8fdf3ae3425c5661cbdd85990a5f44365b989c3c6f478ed48ccf5bae9e14b1"} \ No newline at end of file diff --git a/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-1.0.0.tgz b/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-1.0.0.tgz new file mode 100644 index 0000000000..accce0455a Binary files /dev/null and b/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-1.0.0.tgz differ diff --git a/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-1.0.1.tgz b/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-1.0.1.tgz new file mode 100644 index 0000000000..d042f4f83d Binary files /dev/null and b/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-1.0.1.tgz differ diff --git a/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-2.0.0.tgz b/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-2.0.0.tgz new file mode 100644 index 0000000000..d5e81f7920 Binary files /dev/null and b/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-2.0.0.tgz differ diff --git a/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-2.0.1.tgz b/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-2.0.1.tgz new file mode 100644 index 0000000000..b39ce05ecb Binary files /dev/null and b/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-2.0.1.tgz differ diff --git a/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-3.0.0.tgz b/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-3.0.0.tgz new file mode 100644 index 0000000000..3f2658de80 Binary files /dev/null and b/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-3.0.0.tgz differ diff --git a/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-3.0.1.tgz b/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-3.0.1.tgz new file mode 100644 index 0000000000..d3e793c874 Binary files /dev/null and b/test/cli/install/registry/packages/dep-with-tags/dep-with-tags-3.0.1.tgz differ diff --git a/test/cli/install/registry/packages/dep-with-tags/package.json b/test/cli/install/registry/packages/dep-with-tags/package.json new file mode 100644 index 0000000000..1f6a261c41 --- /dev/null +++ b/test/cli/install/registry/packages/dep-with-tags/package.json @@ -0,0 +1,137 @@ +{ + "name": "dep-with-tags", + "versions": { + "1.0.0": { + "name": "dep-with-tags", + "version": "1.0.0", + "dependencies": {}, + "_id": "dep-with-tags@1.0.0", + "_nodeVersion": "20.8.0", + "_npmVersion": "10.1.0", + "dist": { + "integrity": "sha512-XB/M8CHI49qBjwHY4SJacxdubPJdkTQpG4aLV1GphIsHJNV8cz/ee97seEX8UGvMD2oWCpuGSQWJbihuQDb7EQ==", + "shasum": "309d399d607cd2b413b0a3ed30c5de95bbadd489", + "tarball": "http://localhost:4873/dep-with-tags/-/dep-with-tags-1.0.0.tgz" + }, + "contributors": [] + }, + "1.0.1": { + "name": "dep-with-tags", + "version": "1.0.1", + "dependencies": {}, + "_id": "dep-with-tags@1.0.1", + "_nodeVersion": "20.8.0", + "_npmVersion": "10.1.0", + "dist": { + "integrity": "sha512-akiZqe4FHDriKxmXUwT/MnugbJAHNibtAM+UcAGFpr1LYvV00TRxufqnNNj6ZgbZd2LfbJFlSZ4rRTEnBf0wUw==", + "shasum": "ca7c4798f9340ac3faa782daa6a962eb234a8317", + "tarball": "http://localhost:4873/dep-with-tags/-/dep-with-tags-1.0.1.tgz" + }, + "contributors": [] + }, + "2.0.0": { + "name": "dep-with-tags", + "version": "2.0.0", + "dependencies": {}, + "_id": "dep-with-tags@2.0.0", + "_nodeVersion": "20.8.0", + "_npmVersion": "10.1.0", + "dist": { + "integrity": "sha512-2sha1vZ9rG0iurQZno5jQBEi3amkm6GUlUgZVLhtwD4wCLZ+PpVRuYkL+6a3Ue4Wt8fiMYZWunyh3nmPAUP3oQ==", + "shasum": "1f5c876f9e561ea70aed7e9609794471e0703ef0", + "tarball": "http://localhost:4873/dep-with-tags/-/dep-with-tags-2.0.0.tgz" + }, + "contributors": [] + }, + "2.0.1": { + "name": "dep-with-tags", + "version": "2.0.1", + "dependencies": {}, + "_id": "dep-with-tags@2.0.1", + "_nodeVersion": "20.8.0", + "_npmVersion": "10.1.0", + "dist": { + "integrity": "sha512-7O5A2wU7ubjYfVIc1lZNdczbOxrXVCGf7bbzOW607Y12WWib7TIMQm3r1XiUrdfgDdlAyFRlJUh/8pBAGQb8oQ==", + "shasum": "28acd23319e571b792e195c7aba3f83f098e3bf7", + "tarball": "http://localhost:4873/dep-with-tags/-/dep-with-tags-2.0.1.tgz" + }, + "contributors": [] + }, + "3.0.0": { + "name": "dep-with-tags", + "version": "3.0.0", + "dependencies": {}, + "_id": "dep-with-tags@3.0.0", + "_nodeVersion": "20.8.0", + "_npmVersion": "10.1.0", + "dist": { + "integrity": "sha512-A4sQrinTIwq49TAn2FvUBsVqz17q3g5bcyzJYLdRYAsFE91jiz1eVjDVeCiOKA3eY2VV88aJfaRJOCZibPGOnA==", + "shasum": "fab1ac57a4d1ffd56d25bd2c6e9d180fbb9f46e3", + "tarball": "http://localhost:4873/dep-with-tags/-/dep-with-tags-3.0.0.tgz" + }, + "contributors": [] + }, + "3.0.1": { + "name": "dep-with-tags", + "version": "3.0.1", + "dependencies": {}, + "_id": "dep-with-tags@3.0.1", + "_nodeVersion": "20.8.0", + "_npmVersion": "10.1.0", + "dist": { + "integrity": "sha512-axPXYhO5HsRjS0dBGtDzh8ZO1jslfoSrMt3IzC16vfH/kYjEZZ4oTZ8i4uRhCLk2xYcX+RaeaLL3SonoMapYwA==", + "shasum": "c3895ea8b73696f6fd224b0364ff0a142cfbd13e", + "tarball": "http://localhost:4873/dep-with-tags/-/dep-with-tags-3.0.1.tgz" + }, + "contributors": [] + } + }, + "time": { + "modified": "2023-11-07T00:25:42.483Z", + "created": "2023-11-07T00:24:52.810Z", + "1.0.0": "2023-11-07T00:24:52.810Z", + "1.0.1": "2023-11-07T00:25:07.173Z", + "2.0.0": "2023-11-07T00:25:21.739Z", + "2.0.1": "2023-11-07T00:25:29.630Z", + "3.0.0": "2023-11-07T00:25:37.772Z", + "3.0.1": "2023-11-07T00:25:42.483Z" + }, + "users": {}, + "dist-tags": { + "latest": "3.0.0", + "pre-1": "1.0.1", + "pre-2": "2.0.1", + "pre-3": "3.0.1" + }, + "_uplinks": {}, + "_distfiles": {}, + "_attachments": { + "dep-with-tags-1.0.0.tgz": { + "shasum": "309d399d607cd2b413b0a3ed30c5de95bbadd489", + "version": "1.0.0" + }, + "dep-with-tags-1.0.1.tgz": { + "shasum": "ca7c4798f9340ac3faa782daa6a962eb234a8317", + "version": "1.0.1" + }, + "dep-with-tags-2.0.0.tgz": { + "shasum": "1f5c876f9e561ea70aed7e9609794471e0703ef0", + "version": "2.0.0" + }, + "dep-with-tags-2.0.1.tgz": { + "shasum": "28acd23319e571b792e195c7aba3f83f098e3bf7", + "version": "2.0.1" + }, + "dep-with-tags-3.0.0.tgz": { + "shasum": "fab1ac57a4d1ffd56d25bd2c6e9d180fbb9f46e3", + "version": "3.0.0" + }, + "dep-with-tags-3.0.1.tgz": { + "shasum": "c3895ea8b73696f6fd224b0364ff0a142cfbd13e", + "version": "3.0.1" + } + }, + "_rev": "", + "_id": "dep-with-tags", + "readme": "ERROR: No README data found!" +} \ No newline at end of file