Skip to content

Commit 1e6149e

Browse files
authored
[rush-resolver-cache-plugin] Fix file: dependency context resolution mismatch (pnpm v9/v10) (#5802)
* fix: normalize file dependency key resolution * test: cover additional file dependency key edge cases * refactor: extract repeated specifier strings into variables in tests * chore: add changefile for resolver cache plugin file: fix --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent 42cc717 commit 1e6149e

3 files changed

Lines changed: 88 additions & 10 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"comment": "Fix `file:` dependency context resolution to use canonical dependency keys for pnpm v9/v10.",
5+
"type": "patch",
6+
"packageName": "@microsoft/rush"
7+
}
8+
],
9+
"packageName": "@microsoft/rush",
10+
"email": "5100938+bmiddha@users.noreply.github.com"
11+
}

rush-plugins/rush-resolver-cache-plugin/src/helpers.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ export function resolveDependencyKey(
3131
specifier.slice(5)
3232
);
3333
} else if (specifier.startsWith('file:')) {
34-
return getDescriptionFileRootFromKey(lockfileFolder, specifier, helpers.depPathToFilename, key);
34+
const resolvedKey: string = packageKeys?.has(specifier)
35+
? specifier
36+
: helpers.buildDependencyKey(key, specifier);
37+
return getDescriptionFileRootFromKey(lockfileFolder, resolvedKey, helpers.depPathToFilename, key);
3538
} else {
3639
const resolvedKey: string = packageKeys?.has(specifier)
3740
? specifier

rush-plugins/rush-resolver-cache-plugin/src/test/helpers.test.ts

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -282,10 +282,11 @@ describe(resolveDependencyKey.name, () => {
282282
});
283283

284284
it('resolves link: specifier for project context', () => {
285+
const specifier: string = 'link:../bar';
285286
const result: string = resolveDependencyKey(
286287
lockfileFolder,
287288
'bar',
288-
'link:../bar',
289+
specifier,
289290
makeProjectContext(),
290291
v9Helpers
291292
);
@@ -294,10 +295,11 @@ describe(resolveDependencyKey.name, () => {
294295
});
295296

296297
it('resolves link: specifier for non-project context', () => {
298+
const specifier: string = 'link:../bar';
297299
const result: string = resolveDependencyKey(
298300
lockfileFolder,
299301
'bar',
300-
'link:../bar',
302+
specifier,
301303
makePackageContext(),
302304
v9Helpers
303305
);
@@ -306,23 +308,82 @@ describe(resolveDependencyKey.name, () => {
306308
});
307309

308310
it('resolves file: specifier', () => {
311+
const specifier: string = 'file:../../../rigs/local-node-rig';
309312
const result: string = resolveDependencyKey(
310313
lockfileFolder,
311314
'my-rig',
312-
'file:../../../rigs/local-node-rig',
315+
specifier,
313316
makeProjectContext(),
314317
v9Helpers
315318
);
316319
expect(result).toContain('node_modules/.pnpm/');
317320
expect(result).toContain('/node_modules/my-rig');
318321
});
319322

323+
it('resolves file: specifier using canonical dependency key shape', () => {
324+
const specifier: string =
325+
'file:../../a/b/c/my-local-package-1.0.0.tgz(react-dom@17.0.1(react@17.0.1))(react@17.0.1)';
326+
const result: string = resolveDependencyKey(
327+
lockfileFolder,
328+
'my-local-package',
329+
specifier,
330+
makeProjectContext(),
331+
v9Helpers
332+
);
333+
const expected: string = getDescriptionFileRootFromKey(
334+
lockfileFolder,
335+
v9Helpers.buildDependencyKey('my-local-package', specifier),
336+
v9Helpers.depPathToFilename,
337+
'my-local-package'
338+
);
339+
expect(result).toBe(expected);
340+
});
341+
342+
it('resolves file: specifier using canonical dependency key shape (v8)', () => {
343+
const specifier: string = 'file:../../../rigs/local-node-rig';
344+
const result: string = resolveDependencyKey(
345+
lockfileFolder,
346+
'my-rig',
347+
specifier,
348+
makeProjectContext(),
349+
v8Helpers
350+
);
351+
const expected: string = getDescriptionFileRootFromKey(
352+
lockfileFolder,
353+
v8Helpers.buildDependencyKey('my-rig', specifier),
354+
v8Helpers.depPathToFilename,
355+
'my-rig'
356+
);
357+
expect(result).toBe(expected);
358+
});
359+
360+
it('uses file: specifier directly when packageKeys already contains it', () => {
361+
const specifier: string = 'file:../../../rigs/local-node-rig';
362+
const packageKeys: Set<string> = new Set([specifier]);
363+
const result: string = resolveDependencyKey(
364+
lockfileFolder,
365+
'my-rig',
366+
specifier,
367+
makeProjectContext(),
368+
v9Helpers,
369+
packageKeys
370+
);
371+
const expected: string = getDescriptionFileRootFromKey(
372+
lockfileFolder,
373+
specifier,
374+
v9Helpers.depPathToFilename,
375+
'my-rig'
376+
);
377+
expect(result).toBe(expected);
378+
});
379+
320380
it('resolves specifier found in packageKeys (v6)', () => {
321-
const packageKeys: Set<string> = new Set(['/autoprefixer@9.8.8']);
381+
const specifier: string = '/autoprefixer@9.8.8';
382+
const packageKeys: Set<string> = new Set([specifier]);
322383
const result: string = resolveDependencyKey(
323384
lockfileFolder,
324385
'autoprefixer',
325-
'/autoprefixer@9.8.8',
386+
specifier,
326387
makeProjectContext(),
327388
v8Helpers,
328389
packageKeys
@@ -332,11 +393,12 @@ describe(resolveDependencyKey.name, () => {
332393
});
333394

334395
it('resolves specifier found in packageKeys (v9)', () => {
335-
const packageKeys: Set<string> = new Set(['autoprefixer@9.8.8']);
396+
const specifier: string = 'autoprefixer@9.8.8';
397+
const packageKeys: Set<string> = new Set([specifier]);
336398
const result: string = resolveDependencyKey(
337399
lockfileFolder,
338400
'autoprefixer',
339-
'autoprefixer@9.8.8',
401+
specifier,
340402
makeProjectContext(),
341403
v9Helpers,
342404
packageKeys
@@ -346,10 +408,11 @@ describe(resolveDependencyKey.name, () => {
346408
});
347409

348410
it('builds dependency key for plain version specifiers (v9)', () => {
411+
const specifier: string = '9.8.8';
349412
const result: string = resolveDependencyKey(
350413
lockfileFolder,
351414
'autoprefixer',
352-
'9.8.8',
415+
specifier,
353416
makeProjectContext(),
354417
v9Helpers
355418
);
@@ -358,10 +421,11 @@ describe(resolveDependencyKey.name, () => {
358421
});
359422

360423
it('builds dependency key for plain version specifiers (v8)', () => {
424+
const specifier: string = '9.8.8';
361425
const result: string = resolveDependencyKey(
362426
lockfileFolder,
363427
'autoprefixer',
364-
'9.8.8',
428+
specifier,
365429
makeProjectContext(),
366430
v8Helpers
367431
);

0 commit comments

Comments
 (0)