diff --git a/.changeset/new-jeans-sparkle.md b/.changeset/new-jeans-sparkle.md new file mode 100644 index 00000000000..99b4dc7b511 --- /dev/null +++ b/.changeset/new-jeans-sparkle.md @@ -0,0 +1,7 @@ +--- +"@pnpm/lockfile-file": patch +"@pnpm/git-resolver": patch +"pnpm": patch +--- + +Lockfiles that have git-hosted dependencies specified should be correctly converted to the new lockfile format [#7990](https://github.com/pnpm/pnpm/issues/7990). diff --git a/lockfile/lockfile-file/package.json b/lockfile/lockfile-file/package.json index 8031bfbec53..1570cd4cde5 100644 --- a/lockfile/lockfile-file/package.json +++ b/lockfile/lockfile-file/package.json @@ -49,6 +49,7 @@ "@pnpm/constants": "workspace:*", "@pnpm/dependency-path": "workspace:*", "@pnpm/error": "workspace:*", + "@pnpm/git-resolver": "workspace:*", "@pnpm/git-utils": "workspace:*", "@pnpm/lockfile-types": "workspace:*", "@pnpm/lockfile-utils": "workspace:*", diff --git a/lockfile/lockfile-file/src/lockfileFormatConverters.ts b/lockfile/lockfile-file/src/lockfileFormatConverters.ts index f572aa2303f..38fc906cb92 100644 --- a/lockfile/lockfile-file/src/lockfileFormatConverters.ts +++ b/lockfile/lockfile-file/src/lockfileFormatConverters.ts @@ -1,4 +1,5 @@ import { parseDepPath, removePeersSuffix } from '@pnpm/dependency-path' +import { createGitHostedPkgId } from '@pnpm/git-resolver' import { type Lockfile, type ProjectSnapshot, @@ -210,10 +211,7 @@ function convertPkgIds (lockfile: LockfileFile): void { newId += `#path:${pkg.resolution.path}` } } else if ('repo' in pkg.resolution) { - newId += `${pkg.resolution.repo.startsWith('git+') ? '' : 'git+'}${pkg.resolution.repo}#${pkg.resolution.commit}` - if (pkg.resolution.path) { - newId += `&path:${pkg.resolution.path}` - } + newId += createGitHostedPkgId(pkg.resolution) } else if ('directory' in pkg.resolution) { newId += id } else { @@ -255,6 +253,17 @@ function convertPkgIds (lockfile: LockfileFile): void { } } lockfile.packages = newLockfilePackages + if ((lockfile.dependencies != null || lockfile.devDependencies != null || lockfile.optionalDependencies != null) && !lockfile.importers?.['.']) { + lockfile.importers = lockfile.importers ?? {} + lockfile.importers['.'] = { + dependencies: lockfile.dependencies, + devDependencies: lockfile.devDependencies, + optionalDependencies: lockfile.optionalDependencies, + } + delete lockfile.dependencies + delete lockfile.devDependencies + delete lockfile.optionalDependencies + } for (const importer of Object.values(lockfile.importers ?? {})) { for (const depType of ['dependencies', 'optionalDependencies', 'devDependencies'] as const) { for (const [alias, { version }] of Object.entries(importer[depType] ?? {})) { diff --git a/lockfile/lockfile-file/test/lockfileFormatConverters.test.ts b/lockfile/lockfile-file/test/lockfileFormatConverters.test.ts index 33d363f7daf..567536538fa 100644 --- a/lockfile/lockfile-file/test/lockfileFormatConverters.test.ts +++ b/lockfile/lockfile-file/test/lockfileFormatConverters.test.ts @@ -87,7 +87,7 @@ test('convertToLockfileObject converts git-hosted dependencies', () => { }) test('convertToLockfileObject converts git-hosted dependencies via ssh', () => { - expect(convertToLockfileObject({ + const result = convertToLockfileObject({ lockfileVersion: '', importers: { '.': { @@ -96,6 +96,10 @@ test('convertToLockfileObject converts git-hosted dependencies via ssh', () => { specifier: 'ssh://git@gitlab:pnpm/git-resolver#988c61e11dc8d9ca0b5580cb15291951812549dc', version: 'git+ssh://git@gitlab/pnpm/git-resolver#988c61e11dc8d9ca0b5580cb15291951812549dc', }, + foo: { + specifier: 'https://gitlab.com/foo/foo.git', + version: 'git@gitlab.com+foo/foo/6ae3f32d7c631f64fbaf70cdd349ae6e2cc68e6c', + }, }, }, }, @@ -108,15 +112,26 @@ test('convertToLockfileObject converts git-hosted dependencies via ssh', () => { type: 'git', }, } as any, // eslint-disable-line + 'git@gitlab.com+foo/foo/6ae3f32d7c631f64fbaf70cdd349ae6e2cc68e6c': { + name: 'foo', + resolution: { + commit: '6ae3f32d7c631f64fbaf70cdd349ae6e2cc68e6c', + repo: 'git@gitlab.com:foo/foo.git', + type: 'git', + }, + } as any, // eslint-disable-line }, - })).toMatchObject({ + }) + expect(result).toMatchObject({ lockfileVersion: '', importers: { '.': { dependencies: { + foo: 'git+https://git@gitlab.com:foo/foo.git#6ae3f32d7c631f64fbaf70cdd349ae6e2cc68e6c', 'git-resolver': 'git+ssh://git@gitlab/pnpm/git-resolver#988c61e11dc8d9ca0b5580cb15291951812549dc', }, specifiers: { + foo: 'https://gitlab.com/foo/foo.git', 'git-resolver': 'ssh://git@gitlab:pnpm/git-resolver#988c61e11dc8d9ca0b5580cb15291951812549dc', }, }, @@ -129,6 +144,13 @@ test('convertToLockfileObject converts git-hosted dependencies via ssh', () => { type: 'git', }, }, + 'foo@git+https://git@gitlab.com:foo/foo.git#6ae3f32d7c631f64fbaf70cdd349ae6e2cc68e6c': { + resolution: { + commit: '6ae3f32d7c631f64fbaf70cdd349ae6e2cc68e6c', + repo: 'git@gitlab.com:foo/foo.git', + type: 'git', + }, + }, }, }) }) diff --git a/lockfile/lockfile-file/tsconfig.json b/lockfile/lockfile-file/tsconfig.json index 8c604b7dec5..c53a710aa31 100644 --- a/lockfile/lockfile-file/tsconfig.json +++ b/lockfile/lockfile-file/tsconfig.json @@ -24,6 +24,9 @@ { "path": "../../packages/types" }, + { + "path": "../../resolving/git-resolver" + }, { "path": "../lockfile-types" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b408ad03b1..5f09d8bce5a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2130,6 +2130,9 @@ importers: '@pnpm/error': specifier: workspace:* version: link:../../packages/error + '@pnpm/git-resolver': + specifier: workspace:* + version: link:../../resolving/git-resolver '@pnpm/git-utils': specifier: workspace:* version: link:../../packages/git-utils @@ -6372,7 +6375,7 @@ importers: version: link:../fs/symlink-dependency '@rushstack/worker-pool': specifier: 0.4.9 - version: 0.4.9(@types/node@20.12.7) + version: 0.4.9(@types/node@18.19.31) load-json-file: specifier: ^6.2.0 version: 6.2.0 @@ -7908,9 +7911,6 @@ packages: '@types/node@18.19.31': resolution: {integrity: sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==} - '@types/node@20.12.7': - resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} - '@types/node@20.5.1': resolution: {integrity: sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg==} @@ -14497,9 +14497,9 @@ snapshots: '@reflink/reflink-win32-arm64-msvc': 0.1.16 '@reflink/reflink-win32-x64-msvc': 0.1.16 - '@rushstack/worker-pool@0.4.9(@types/node@20.12.7)': + '@rushstack/worker-pool@0.4.9(@types/node@18.19.31)': optionalDependencies: - '@types/node': 20.12.7 + '@types/node': 18.19.31 '@sinclair/typebox@0.27.8': {} @@ -14681,11 +14681,6 @@ snapshots: dependencies: undici-types: 5.26.5 - '@types/node@20.12.7': - dependencies: - undici-types: 5.26.5 - optional: true - '@types/node@20.5.1': {} '@types/normalize-package-data@2.4.4': {} diff --git a/resolving/git-resolver/src/createGitHostedPkgId.ts b/resolving/git-resolver/src/createGitHostedPkgId.ts new file mode 100644 index 00000000000..3d90a4c984f --- /dev/null +++ b/resolving/git-resolver/src/createGitHostedPkgId.ts @@ -0,0 +1,8 @@ +export function createGitHostedPkgId ({ repo, commit, path }: { repo: string, commit: string, path?: string }): string { + let id = `${repo.includes('://') ? '' : 'https://'}${repo}#${commit}` + if (!id.startsWith('git+')) id = `git+${id}` + if (path) { + id += `&path:${path}` + } + return id +} diff --git a/resolving/git-resolver/src/index.ts b/resolving/git-resolver/src/index.ts index e56a5d16ce0..2c4aaa9b9bf 100644 --- a/resolving/git-resolver/src/index.ts +++ b/resolving/git-resolver/src/index.ts @@ -2,6 +2,9 @@ import { type TarballResolution, type GitResolution, type ResolveResult } from ' import git from 'graceful-git' import semver from 'semver' import { parsePref, type HostedPackageSpec } from './parsePref' +import { createGitHostedPkgId } from './createGitHostedPkgId' + +export { createGitHostedPkgId } export type { HostedPackageSpec } @@ -54,10 +57,7 @@ export function createGitResolver ( id += `#path:${resolution.path}` } } else { - id = `${resolution.repo.startsWith('git+') ? '' : 'git+'}${resolution.repo}#${resolution.commit}` - if (resolution.path) { - id += `&path:${resolution.path}` - } + id = createGitHostedPkgId(resolution) } return { diff --git a/resolving/git-resolver/test/createGitHostedPkgId.test.ts b/resolving/git-resolver/test/createGitHostedPkgId.test.ts new file mode 100644 index 00000000000..6a6f64dd256 --- /dev/null +++ b/resolving/git-resolver/test/createGitHostedPkgId.test.ts @@ -0,0 +1,9 @@ +import { createGitHostedPkgId } from '@pnpm/git-resolver' + +test.each([ + [{ repo: 'ssh://git@example.com/org/repo.git', commit: 'cba04669e621b85fbdb33371604de1a2898e68e9' }, 'git+ssh://git@example.com/org/repo.git#cba04669e621b85fbdb33371604de1a2898e68e9'], + [{ repo: 'https://0000000000000000000000000000000000000000:x-oauth-basic@github.com/foo/bar.git', commit: '0000000000000000000000000000000000000000' }, 'git+https://0000000000000000000000000000000000000000:x-oauth-basic@github.com/foo/bar.git#0000000000000000000000000000000000000000'], + [{ repo: 'file:///Users/zoltan/src/pnpm/pnpm/resolving/git-resolver', commit: '988c61e11dc8d9ca0b5580cb15291951812549dc' }, 'git+file:///Users/zoltan/src/pnpm/pnpm/resolving/git-resolver#988c61e11dc8d9ca0b5580cb15291951812549dc'], +])('createGitHostedPkgId', (resolution, id) => { + expect(createGitHostedPkgId(resolution)).toBe(id) +})