feat(ngcc): support reverting a file written by FileWriter
(#36626)
This commit adds a `revertFile()` method to `FileWriter`, which can revert a transformed file (and its backup - if any) written by the `FileWriter`. In a subsequent commit, this will be used to allow ngcc to recover when a worker process crashes in the middle of processing a task. PR Close #36626
This commit is contained in:

committed by
Andrew Kushnir

parent
ff6e93163f
commit
772ccf0d9f
@ -6,7 +6,8 @@
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {EntryPointJsonProperty} from '../packages/entry_point';
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/file_system';
|
||||
import {EntryPoint, EntryPointJsonProperty} from '../packages/entry_point';
|
||||
import {EntryPointBundle} from '../packages/entry_point_bundle';
|
||||
import {FileToWrite} from '../rendering/utils';
|
||||
|
||||
@ -17,4 +18,18 @@ export interface FileWriter {
|
||||
writeBundle(
|
||||
bundle: EntryPointBundle, transformedFiles: FileToWrite[],
|
||||
formatProperties: EntryPointJsonProperty[]): void;
|
||||
|
||||
/**
|
||||
* Revert the changes to an entry-point processed for the specified format-properties by the same
|
||||
* `FileWriter` implementation.
|
||||
*
|
||||
* @param entryPoint The entry-point to revert.
|
||||
* @param transformedFilePaths The original paths of the transformed files. (The transformed files
|
||||
* may be written at the same or a different location, depending on the `FileWriter`
|
||||
* implementation.)
|
||||
* @param formatProperties The format-properties pointing to the entry-point.
|
||||
*/
|
||||
revertBundle(
|
||||
entryPoint: EntryPoint, transformedFilePaths: AbsoluteFsPath[],
|
||||
formatProperties: EntryPointJsonProperty[]): void;
|
||||
}
|
||||
|
@ -5,9 +5,9 @@
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {absoluteFrom, dirname, FileSystem} from '../../../src/ngtsc/file_system';
|
||||
import {absoluteFrom, AbsoluteFsPath, dirname, FileSystem} from '../../../src/ngtsc/file_system';
|
||||
import {Logger} from '../logging/logger';
|
||||
import {EntryPointJsonProperty} from '../packages/entry_point';
|
||||
import {EntryPoint, EntryPointJsonProperty} from '../packages/entry_point';
|
||||
import {EntryPointBundle} from '../packages/entry_point_bundle';
|
||||
import {FileToWrite} from '../rendering/utils';
|
||||
|
||||
@ -29,6 +29,14 @@ export class InPlaceFileWriter implements FileWriter {
|
||||
transformedFiles.forEach(file => this.writeFileAndBackup(file));
|
||||
}
|
||||
|
||||
revertBundle(
|
||||
_entryPoint: EntryPoint, transformedFilePaths: AbsoluteFsPath[],
|
||||
_formatProperties: EntryPointJsonProperty[]): void {
|
||||
for (const filePath of transformedFilePaths) {
|
||||
this.revertFileAndBackup(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
protected writeFileAndBackup(file: FileToWrite): void {
|
||||
this.fs.ensureDir(dirname(file.path));
|
||||
const backPath = absoluteFrom(`${file.path}${NGCC_BACKUP_EXTENSION}`);
|
||||
@ -51,4 +59,15 @@ export class InPlaceFileWriter implements FileWriter {
|
||||
this.fs.writeFile(file.path, file.contents);
|
||||
}
|
||||
}
|
||||
|
||||
protected revertFileAndBackup(filePath: AbsoluteFsPath): void {
|
||||
if (this.fs.exists(filePath)) {
|
||||
this.fs.removeFile(filePath);
|
||||
|
||||
const backPath = absoluteFrom(`${filePath}${NGCC_BACKUP_EXTENSION}`);
|
||||
if (this.fs.exists(backPath)) {
|
||||
this.fs.moveFile(backPath, filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,27 @@ export class NewEntryPointFileWriter extends InPlaceFileWriter {
|
||||
this.updatePackageJson(entryPoint, formatProperties, ngccFolder);
|
||||
}
|
||||
|
||||
revertBundle(
|
||||
entryPoint: EntryPoint, transformedFilePaths: AbsoluteFsPath[],
|
||||
formatProperties: EntryPointJsonProperty[]): void {
|
||||
// IMPLEMENTATION NOTE:
|
||||
//
|
||||
// The changes made by `copyBundle()` are not reverted here. The non-transformed copied files
|
||||
// are identical to the original ones and they will be overwritten when re-processing the
|
||||
// entry-point anyway.
|
||||
//
|
||||
// This way, we avoid the overhead of having to inform the master process about all source files
|
||||
// being copied in `copyBundle()`.
|
||||
|
||||
// Revert the transformed files.
|
||||
for (const filePath of transformedFilePaths) {
|
||||
this.revertFile(filePath, entryPoint.package);
|
||||
}
|
||||
|
||||
// Revert any changes to `package.json`.
|
||||
this.revertPackageJson(entryPoint, formatProperties);
|
||||
}
|
||||
|
||||
protected copyBundle(
|
||||
bundle: EntryPointBundle, packagePath: AbsoluteFsPath, ngccFolder: AbsoluteFsPath) {
|
||||
bundle.src.program.getSourceFiles().forEach(sourceFile => {
|
||||
@ -71,6 +92,17 @@ export class NewEntryPointFileWriter extends InPlaceFileWriter {
|
||||
}
|
||||
}
|
||||
|
||||
protected revertFile(filePath: AbsoluteFsPath, packagePath: AbsoluteFsPath): void {
|
||||
if (isDtsPath(filePath.replace(/\.map$/, ''))) {
|
||||
// This is either `.d.ts` or `.d.ts.map` file
|
||||
super.revertFileAndBackup(filePath);
|
||||
} else if (this.fs.exists(filePath)) {
|
||||
const relativePath = relative(packagePath, filePath);
|
||||
const newFilePath = join(packagePath, NGCC_DIRECTORY, relativePath);
|
||||
this.fs.removeFile(newFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
protected updatePackageJson(
|
||||
entryPoint: EntryPoint, formatProperties: EntryPointJsonProperty[],
|
||||
ngccFolder: AbsoluteFsPath) {
|
||||
@ -105,4 +137,25 @@ export class NewEntryPointFileWriter extends InPlaceFileWriter {
|
||||
|
||||
update.writeChanges(packageJsonPath, packageJson);
|
||||
}
|
||||
|
||||
protected revertPackageJson(entryPoint: EntryPoint, formatProperties: EntryPointJsonProperty[]) {
|
||||
if (formatProperties.length === 0) {
|
||||
// No format properties need reverting.
|
||||
return;
|
||||
}
|
||||
|
||||
const packageJson = entryPoint.packageJson;
|
||||
const packageJsonPath = join(entryPoint.path, 'package.json');
|
||||
|
||||
// Revert all properties in `package.json` (both in memory and on disk).
|
||||
// Since `updatePackageJson()` only adds properties, it is safe to just remove them (if they
|
||||
// exist).
|
||||
const update = this.pkgJsonUpdater.createUpdate();
|
||||
|
||||
for (const formatProperty of formatProperties) {
|
||||
update.addChange([`${formatProperty}${NGCC_PROPERTY_EXTENSION}`], undefined);
|
||||
}
|
||||
|
||||
update.writeChanges(packageJsonPath, packageJson);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user