From d55b2595dda9530ea9a4baf10aaba62aa91bba45 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 23 Sep 2024 10:21:04 +0900 Subject: [PATCH] fix(dependency-path)!: escape `#` character in directory name (#8557) --- .changeset/violet-rockets-pull.md | 7 +++++++ packages/dependency-path/src/index.ts | 2 +- packages/dependency-path/test/index.ts | 3 +++ pkg-manager/core/test/install/fromRepo.ts | 11 +++++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 .changeset/violet-rockets-pull.md diff --git a/.changeset/violet-rockets-pull.md b/.changeset/violet-rockets-pull.md new file mode 100644 index 0000000000..700ad044ce --- /dev/null +++ b/.changeset/violet-rockets-pull.md @@ -0,0 +1,7 @@ +--- +"@pnpm/dependency-path": major +"@pnpm/core": major +pnpm: major +--- + +Escape the `#` character in directory names within the virtual store (`node_modules/.pnpm`) [#8557](https://github.com/pnpm/pnpm/pull/8557). diff --git a/packages/dependency-path/src/index.ts b/packages/dependency-path/src/index.ts index 67c40d030f..42800d9107 100644 --- a/packages/dependency-path/src/index.ts +++ b/packages/dependency-path/src/index.ts @@ -165,7 +165,7 @@ export function parse (dependencyPath: string): DependencyPath { } export function depPathToFilename (depPath: string, maxLengthWithoutHash: number): string { - let filename = depPathToFilenameUnescaped(depPath).replace(/[\\/:*?"<>|]/g, '+') + let filename = depPathToFilenameUnescaped(depPath).replace(/[\\/:*?"<>|#]/g, '+') if (filename.includes('(')) { filename = filename .replace(/\)$/, '') diff --git a/packages/dependency-path/test/index.ts b/packages/dependency-path/test/index.ts index bbe38eee8c..efade1888f 100644 --- a/packages/dependency-path/test/index.ts +++ b/packages/dependency-path/test/index.ts @@ -98,6 +98,9 @@ test('depPathToFilename()', () => { expect(depPathToFilename('abcd/'.repeat(200), 120)).toBe('abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+ab_e7c10c3598ebbc0ca640b6524c68e602') // cspell:disable-line expect(depPathToFilename('/JSONSteam@1.0.0', 120)).toBe('JSONSteam@1.0.0_533d3b11e9111b7a24f914844c021ddf') // cspell:disable-line + + expect(depPathToFilename('foo@git+https://github.com/something/foo#1234', 120)).toBe('foo@git+https+++github.com+something+foo+1234') + expect(depPathToFilename('foo@https://codeload.github.com/something/foo/tar.gz/1234#path:packages/foo', 120)).toBe('foo@https+++codeload.github.com+something+foo+tar.gz+1234+path+packages+foo') }) test('tryGetPackageId', () => { diff --git a/pkg-manager/core/test/install/fromRepo.ts b/pkg-manager/core/test/install/fromRepo.ts index 393890184f..5ae3237511 100644 --- a/pkg-manager/core/test/install/fromRepo.ts +++ b/pkg-manager/core/test/install/fromRepo.ts @@ -339,3 +339,14 @@ test('from subdirectories of a git repo', async () => { '@my-namespace/simple-react-app': 'github:RexSkz/test-git-subfolder-fetch#path:/packages/simple-react-app', }) }) + +test('no hash character for github subdirectory install', async () => { + prepareEmpty() + + await addDependenciesToPackage({}, [ + 'github:pnpm/only-allow#path:/&v1.2.1', + ], testDefaults()) + + expect(fs.readdirSync('./node_modules/.pnpm')) + .toContain('only-allow@https+++codeload.github.com+pnpm+only-allow+tar.gz+4d577a5a5862a43e752df37a1e8a0c71c3a0084a+path++') +})