From 476c61e8355720fcd5eb535ebe6c8cc826f3e1ee Mon Sep 17 00:00:00 2001 From: David Michon Date: Thu, 19 Sep 2024 17:30:02 -0700 Subject: [PATCH] [rush-resolver-cache] Fix projectFolder on Windows (#4931) Co-authored-by: David Michon --- .../fix-project-folder_2024-09-20-00-10.json | 10 ++++++++++ .../computeResolverCacheFromLockfileAsync.ts | 19 +++++++++++++++---- ...puteResolverCacheFromLockfileAsync.test.ts | 3 ++- 3 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 common/changes/@microsoft/rush/fix-project-folder_2024-09-20-00-10.json diff --git a/common/changes/@microsoft/rush/fix-project-folder_2024-09-20-00-10.json b/common/changes/@microsoft/rush/fix-project-folder_2024-09-20-00-10.json new file mode 100644 index 00000000000..5c8469f9156 --- /dev/null +++ b/common/changes/@microsoft/rush/fix-project-folder_2024-09-20-00-10.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@microsoft/rush", + "comment": "Fix a bug that caused rush-resolver-cache-plugin to crash on Windows.", + "type": "none" + } + ], + "packageName": "@microsoft/rush" +} \ No newline at end of file diff --git a/rush-plugins/rush-resolver-cache-plugin/src/computeResolverCacheFromLockfileAsync.ts b/rush-plugins/rush-resolver-cache-plugin/src/computeResolverCacheFromLockfileAsync.ts index f53225ed40c..dca5e841a28 100644 --- a/rush-plugins/rush-resolver-cache-plugin/src/computeResolverCacheFromLockfileAsync.ts +++ b/rush-plugins/rush-resolver-cache-plugin/src/computeResolverCacheFromLockfileAsync.ts @@ -136,6 +136,15 @@ export interface IComputeResolverCacheFromLockfileOptions { ) => Promise; } +/** + * Copied from `@rushstack/node-core-library/src/Path.ts` to avoid expensive dependency + * @param path - Path using backslashes as path separators + * @returns The same string using forward slashes as path separators + */ +function convertToSlashes(path: string): string { + return path.replace(/\\/g, '/'); +} + /** * Given a lockfile and information about the workspace and platform, computes the resolver cache file. * @param params - The options for computing the resolver cache @@ -146,9 +155,9 @@ export async function computeResolverCacheFromLockfileAsync( ): Promise { const { platformInfo, projectByImporterPath, lockfile, afterExternalPackagesAsync } = params; // Needs to be normalized to `/` for path.posix.join to work correctly - const workspaceRoot: string = params.workspaceRoot.replace(/\\/g, '/'); + const workspaceRoot: string = convertToSlashes(params.workspaceRoot); // Needs to be normalized to `/` for path.posix.join to work correctly - const commonPrefixToTrim: string = params.commonPrefixToTrim.replace(/\\/g, '/'); + const commonPrefixToTrim: string = convertToSlashes(params.commonPrefixToTrim); const contexts: Map = new Map(); const missingOptionalDependencies: Set = new Set(); @@ -218,8 +227,10 @@ export async function computeResolverCacheFromLockfileAsync( throw new Error(`Missing project for importer ${importerPath}`); } + const descriptionFileRoot: string = convertToSlashes(project.projectFolder); + const context: IResolverContext = { - descriptionFileRoot: project.projectFolder, + descriptionFileRoot, descriptionFileHash: undefined, // Not needed anymore name: project.packageJson.name, isProject: true, @@ -227,7 +238,7 @@ export async function computeResolverCacheFromLockfileAsync( ordinal: -1 }; - contexts.set(project.projectFolder, context); + contexts.set(descriptionFileRoot, context); if (importer.dependencies) { resolveDependencies(workspaceRoot, importer.dependencies, context); diff --git a/rush-plugins/rush-resolver-cache-plugin/src/test/computeResolverCacheFromLockfileAsync.test.ts b/rush-plugins/rush-resolver-cache-plugin/src/test/computeResolverCacheFromLockfileAsync.test.ts index fbf067869da..123354f33e7 100644 --- a/rush-plugins/rush-resolver-cache-plugin/src/test/computeResolverCacheFromLockfileAsync.test.ts +++ b/rush-plugins/rush-resolver-cache-plugin/src/test/computeResolverCacheFromLockfileAsync.test.ts @@ -107,7 +107,8 @@ describe(computeResolverCacheFromLockfileAsync.name, () => { for (const importerPath of lockfile.importers.keys()) { const remainder: string = importerPath.slice(importerPath.lastIndexOf('../') + 3); projectByImporterPath.setItem(importerPath, { - projectFolder: `${commonPrefixToTrim.replace(/\\/g, '/')}${remainder}`, + // Normalization is the responsibility of the implementation + projectFolder: `${commonPrefixToTrim}${remainder}`, packageJson: { name: `@local/${remainder.replace(/\//g, '+')}` }