Skip to content

Commit 4bdbfa2

Browse files
committed
refactor(@angular/build): scope cache directory by project name in normalizeCacheOptions
Accept an optional `projectName` parameter in `normalizeCacheOptions` to consistently scope `path` and `localPath` per project across the application, dev-server, library, ng-packagr, and unit-test builders.
1 parent f0f051d commit 4bdbfa2

8 files changed

Lines changed: 58 additions & 12 deletions

File tree

‎packages/angular/build/src/builders/application/options.ts‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,7 @@ export async function normalizeOptions(
182182
const { projectRoot, projectSourceRoot } = getProjectRootPaths(workspaceRoot, projectMetadata);
183183

184184
// Gather persistent caching option and provide a project specific cache location
185-
const cacheOptions = normalizeCacheOptions(projectMetadata, workspaceRoot);
186-
cacheOptions.path = path.join(cacheOptions.path, projectName);
185+
const cacheOptions = normalizeCacheOptions(projectMetadata, workspaceRoot, projectName);
187186

188187
const i18nOptions: I18nOptions & {
189188
duplicateTranslationBehavior?: I18NTranslation;

‎packages/angular/build/src/builders/dev-server/options.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export async function normalizeOptions(
3939
const projectMetadata = await context.getProjectMetadata(projectName);
4040
const projectRoot = path.join(workspaceRoot, (projectMetadata.root as string | undefined) ?? '');
4141

42-
const cacheOptions = normalizeCacheOptions(projectMetadata, workspaceRoot);
42+
const cacheOptions = normalizeCacheOptions(projectMetadata, workspaceRoot, projectName);
4343

4444
// Target specifier defaults to the current project's build target using a development configuration
4545
const buildTargetSpecifier = options.buildTarget ?? `::development`;

‎packages/angular/build/src/builders/dev-server/vite/server.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ export async function setupServer(
167167
externalMetadata.explicitBrowser.length === 0 && ssrMode === ServerSsrMode.NoSsr;
168168
const cacheDir = join(
169169
serverOptions.cacheOptions.localPath ?? serverOptions.cacheOptions.path,
170-
serverOptions.buildTarget.project,
171170
'vite',
172171
);
173172

‎packages/angular/build/src/builders/library/options.ts‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,7 @@ export async function normalizeLibraryOptions(
5050
clearScreen,
5151
} = options;
5252

53-
const resolvedTsConfigPath = path.resolve(workspaceRoot, tsConfig);
5453
const packageJsonPath = path.join(projectRoot, 'package.json');
55-
5654
let packageJson: PackageJsonData;
5755
try {
5856
const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8');
@@ -112,7 +110,7 @@ export async function normalizeLibraryOptions(
112110
projectSourceRoot,
113111
);
114112

115-
const cacheOptions = normalizeCacheOptions(projectMetadata, workspaceRoot);
113+
const cacheOptions = normalizeCacheOptions(projectMetadata, workspaceRoot, projectName);
116114
const styleIncludePaths = (stylePreprocessorOptions?.includePaths ?? []).map((p: string) =>
117115
path.resolve(workspaceRoot, p),
118116
);
@@ -131,7 +129,7 @@ export async function normalizeLibraryOptions(
131129
outputPath: path.resolve(workspaceRoot, options.outputPath ?? path.join('dist', projectName)),
132130
deleteOutputPath,
133131
packageJsonPath,
134-
tsConfigPath: resolvedTsConfigPath,
132+
tsConfigPath: path.resolve(workspaceRoot, tsConfig),
135133
entryPoints,
136134
inlineStyleLanguage,
137135
styleIncludePaths,

‎packages/angular/build/src/builders/ng-packagr/builder.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export async function* execute(
6666
const { enabled: cacheEnabled, path: cacheDirectory } = normalizeCacheOptions(
6767
metadata,
6868
context.workspaceRoot,
69+
projectName,
6970
);
7071

7172
const ngPackagrOptions: NgPackagrOptions = {

‎packages/angular/build/src/builders/unit-test/options.ts‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,7 @@ export async function normalizeOptions(
6464
const { projectRoot, projectSourceRoot } = getProjectRootPaths(workspaceRoot, projectMetadata);
6565

6666
// Gather persistent caching option and provide a project specific cache location
67-
const cacheOptions = normalizeCacheOptions(projectMetadata, workspaceRoot);
68-
cacheOptions.path = path.join(cacheOptions.path, projectName);
67+
const cacheOptions = normalizeCacheOptions(projectMetadata, workspaceRoot, projectName);
6968

7069
const {
7170
runner,

‎packages/angular/build/src/utils/normalize-cache.ts‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,22 @@ function getCacheBasePath(workspaceRoot: string, cachePathSetting: string): stri
9797
return resolve(workspaceRoot, cachePathSetting);
9898
}
9999

100+
/**
101+
* Normalizes the persistent disk cache configuration for a project or workspace.
102+
*
103+
* Resolves whether disk caching is enabled based on the CLI cache metadata, current runtime
104+
* environment (local vs. CI, or WebContainers), and computes the versioned cache directory paths
105+
* (resolving shared Git worktree paths when applicable).
106+
*
107+
* @param projectMetadata The project or workspace metadata object containing optional `cli.cache` settings.
108+
* @param workspaceRoot The absolute path to the workspace root directory.
109+
* @param projectName Optional name of the project used to scope the resolved cache path.
110+
* @returns The normalized disk cache options including enabled state and resolved directory paths.
111+
*/
100112
export function normalizeCacheOptions(
101113
projectMetadata: unknown,
102114
workspaceRoot: string,
115+
projectName: string = '',
103116
): NormalizedCachedOptions {
104117
const cacheMetadata = hasCacheMetadata(projectMetadata) ? projectMetadata.cli.cache : {};
105118

@@ -129,8 +142,8 @@ export function normalizeCacheOptions(
129142
return {
130143
enabled: cacheEnabled,
131144
basePath: cacheBasePath,
132-
path: join(cacheBasePath, VERSION),
145+
path: join(cacheBasePath, VERSION, projectName),
133146
localBasePath: localCacheBasePath,
134-
localPath: join(localCacheBasePath, VERSION),
147+
localPath: join(localCacheBasePath, VERSION, projectName),
135148
};
136149
}

‎packages/angular/build/src/utils/normalize-cache_spec.ts‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,4 +197,41 @@ describe('normalizeCacheOptions', () => {
197197
expect(options.localBasePath).toBe(resolve(workspaceRoot, '.angular/cache'));
198198
expect(options.localPath).toBe(resolve(workspaceRoot, '.angular/cache', '0.0.0-PLACEHOLDER'));
199199
});
200+
201+
it('should scope path and localPath to projectName when provided', async () => {
202+
const workspaceRoot = join(tempDir, 'project');
203+
await mkdir(join(workspaceRoot, '.git'), { recursive: true });
204+
205+
const options = normalizeCacheOptions({}, workspaceRoot, 'my-app');
206+
207+
expect(options.basePath).toBe(resolve(workspaceRoot, '.angular/cache'));
208+
expect(options.path).toBe(resolve(workspaceRoot, '.angular/cache/0.0.0-PLACEHOLDER/my-app'));
209+
expect(options.localBasePath).toBe(resolve(workspaceRoot, '.angular/cache'));
210+
expect(options.localPath).toBe(
211+
resolve(workspaceRoot, '.angular/cache/0.0.0-PLACEHOLDER/my-app'),
212+
);
213+
});
214+
215+
it('should scope path and localPath to projectName in a git worktree', async () => {
216+
const mainRepoRoot = join(tempDir, 'main-repo');
217+
const mainGitDir = join(mainRepoRoot, '.git');
218+
const worktreeRoot = join(tempDir, 'worktree');
219+
220+
await mkdir(mainGitDir, { recursive: true });
221+
222+
const worktreeMetadataDir = join(mainGitDir, 'worktrees/wt-1');
223+
await mkdir(worktreeMetadataDir, { recursive: true });
224+
await mkdir(worktreeRoot, { recursive: true });
225+
await writeFile(join(worktreeRoot, '.git'), `gitdir: ${worktreeMetadataDir}`);
226+
await writeFile(join(worktreeMetadataDir, 'commondir'), '../..');
227+
228+
const options = normalizeCacheOptions({}, worktreeRoot, 'my-lib');
229+
230+
expect(options.basePath).toBe(resolve(mainRepoRoot, '.angular/cache'));
231+
expect(options.path).toBe(resolve(mainRepoRoot, '.angular/cache/0.0.0-PLACEHOLDER/my-lib'));
232+
expect(options.localBasePath).toBe(resolve(worktreeRoot, '.angular/cache'));
233+
expect(options.localPath).toBe(
234+
resolve(worktreeRoot, '.angular/cache/0.0.0-PLACEHOLDER/my-lib'),
235+
);
236+
});
200237
});

0 commit comments

Comments
 (0)