mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(ngcc): ensure that ngcc does not write a lock-file into node_modules package directories (#44228)
When executing, ngcc writes a lock-file that is used to coordinate multiple concurrent instances of ngcc. Previously, this file was written at `node_modules/@angular/compiler-cli/ngcc`, or similar depending upon the bundling of the package. But this causes problems for setups where `node_modules` package directories are expected to be read-only. Now, the lock-file is written as `.ngcc_lock_file` into the top of the `node_modules`, which is an acceptable place to store transient files. This change should help to unblock use of tools like pnpm and lerna, which can use symlinks to readonly package directories. PR Close #44228
This commit is contained in:
committed by
Jessica Janiuk
parent
f7dd0f83f0
commit
24b635395f
@@ -209,7 +209,7 @@ ngcc --formats fesm2015
|
||||
assertFailed "Expected 'ngcc --formats fesm2015' to fail (since '--formats' is deprecated)."
|
||||
|
||||
# Does it timeout if there is another ngcc process running
|
||||
LOCKFILE=node_modules/@angular/compiler-cli/bundles/ngcc/__ngcc_lock_file__
|
||||
LOCKFILE=node_modules/.ngcc_lock_file
|
||||
touch $LOCKFILE
|
||||
trap "[[ -f $LOCKFILE ]] && rm $LOCKFILE" EXIT
|
||||
ngcc
|
||||
|
||||
@@ -19,8 +19,8 @@ export function getLockFilePath(fs: PathManipulation) {
|
||||
// allows us to have a consistent position for the lock file to reside. We are unable to rely
|
||||
// on `__dirname` (or equivalent) as this code is being bundled and different entry-points
|
||||
// will have dedicated bundles where the lock file location would differ then.
|
||||
const ngccEntryPointFile = requireFn.resolve('@angular/compiler-cli/ngcc');
|
||||
return fs.resolve(ngccEntryPointFile, '../__ngcc_lock_file__');
|
||||
const ngccEntryPointFile = requireFn.resolve('@angular/compiler-cli/package.json');
|
||||
return fs.resolve(ngccEntryPointFile, '../../../.ngcc_lock_file');
|
||||
}
|
||||
|
||||
export interface LockFile {
|
||||
|
||||
@@ -119,3 +119,18 @@ var __assign${suffix} = null;
|
||||
export function getRootFiles(testFiles: TestFile[]): AbsoluteFsPath[] {
|
||||
return testFiles.filter(f => f.isRoot !== false).map(f => absoluteFrom(f.name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock out the lockfile path resolution, which uses `require.resolve()`.
|
||||
*/
|
||||
export function mockRequireResolveForLockfile() {
|
||||
const moduleConstructor: any = module.constructor;
|
||||
const originalResolveFileName = moduleConstructor._resolveFilename;
|
||||
spyOn<any>(moduleConstructor, '_resolveFilename').and.callFake(function(request: string) {
|
||||
if (request === '@angular/compiler-cli/package.json') {
|
||||
return '/node_modules/' + request;
|
||||
} else {
|
||||
return originalResolveFileName.apply(null, arguments as any);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import {EntryPointJsonProperty, EntryPointPackageJson, SUPPORTED_FORMAT_PROPERTI
|
||||
import {EntryPointManifestFile} from '../../src/packages/entry_point_manifest';
|
||||
import {Transformer} from '../../src/packages/transformer';
|
||||
import {DirectPackageJsonUpdater, PackageJsonUpdater} from '../../src/writing/package_json_updater';
|
||||
import {mockRequireResolveForLockfile} from '../helpers/utils';
|
||||
|
||||
import {compileIntoApf, compileIntoFlatEs2015Package, compileIntoFlatEs5Package, loadNgccIntegrationTestFiles} from './util';
|
||||
|
||||
@@ -46,6 +47,7 @@ runInEachFileSystem(() => {
|
||||
_ = absoluteFrom;
|
||||
fs = getFileSystem();
|
||||
pkgJsonUpdater = new DirectPackageJsonUpdater(fs);
|
||||
mockRequireResolveForLockfile();
|
||||
initMockFileSystem(fs, testFiles);
|
||||
|
||||
// Force single-process execution in unit tests by mocking available CPUs to 1.
|
||||
|
||||
@@ -13,6 +13,7 @@ import {runInEachFileSystem} from '../../../../src/ngtsc/file_system/testing';
|
||||
import {MockLogger} from '../../../../src/ngtsc/logging/testing';
|
||||
import {getLockFilePath} from '../../../src/locking/lock_file';
|
||||
import {LockFileWithChildProcess} from '../../../src/locking/lock_file_with_child_process';
|
||||
import {mockRequireResolveForLockfile} from '../../helpers/utils';
|
||||
|
||||
runInEachFileSystem(() => {
|
||||
describe('LockFileWithChildProcess', () => {
|
||||
@@ -55,6 +56,10 @@ runInEachFileSystem(() => {
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
mockRequireResolveForLockfile();
|
||||
});
|
||||
|
||||
describe('constructor', () => {
|
||||
it('should create the unlocker process', () => {
|
||||
const fs = getFileSystem();
|
||||
|
||||
Reference in New Issue
Block a user