fix(core): tree should not be changed after committed to disk in migrations (#17071)

This commit is contained in:
Craigory Coppola 2023-05-23 17:07:08 -04:00 committed by GitHub
parent d20c2d8492
commit f95f8c4b69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 37 additions and 22 deletions

View File

@ -656,7 +656,11 @@ export async function generate(
const logger = getLogger(verbose); const logger = getLogger(verbose);
const fsHost = new NxScopeHostUsedForWrappedSchematics( const fsHost = new NxScopeHostUsedForWrappedSchematics(
root, root,
new FsTree(root, verbose) new FsTree(
root,
verbose,
`ng-cli generator: ${opts.collectionName}:${opts.generatorName}`
)
); );
const workflow = createWorkflow(fsHost, root, opts); const workflow = createWorkflow(fsHost, root, opts);
const collection = getCollection(workflow, opts.collectionName); const collection = getCollection(workflow, opts.collectionName);
@ -745,7 +749,11 @@ export async function runMigration(
const logger = getLogger(isVerbose); const logger = getLogger(isVerbose);
const fsHost = new NxScopeHostUsedForWrappedSchematics( const fsHost = new NxScopeHostUsedForWrappedSchematics(
root, root,
new FsTree(root, isVerbose) new FsTree(
root,
isVerbose,
`ng-cli migration: ${packageName}:${migrationName}`
)
); );
const workflow = createWorkflow(fsHost, root, {}); const workflow = createWorkflow(fsHost, root, {});
const collection = resolveMigrationsCollection(packageName); const collection = resolveMigrationsCollection(packageName);

View File

@ -364,7 +364,11 @@ export async function generate(cwd: string, args: { [k: string]: any }) {
); );
if (ws.isNxGenerator(opts.collectionName, normalizedGeneratorName)) { if (ws.isNxGenerator(opts.collectionName, normalizedGeneratorName)) {
const host = new FsTree(workspaceRoot, verbose); const host = new FsTree(
workspaceRoot,
verbose,
`generating (${opts.collectionName}:${normalizedGeneratorName})`
);
const implementation = implementationFactory(); const implementation = implementationFactory();
// @todo(v17): Remove this, isStandalonePreset property is defunct. // @todo(v17): Remove this, isStandalonePreset property is defunct.

View File

@ -33,7 +33,7 @@ path_to_root=$(dirname $BASH_SOURCE)
node ${path.posix.join('$path_to_root', nxWrapperPath(path.posix))} $@`; node ${path.posix.join('$path_to_root', nxWrapperPath(path.posix))} $@`;
export function generateDotNxSetup(version?: string) { export function generateDotNxSetup(version?: string) {
const host = new FsTree(process.cwd(), false); const host = new FsTree(process.cwd(), false, '.nx setup');
writeMinimalNxJson(host, version); writeMinimalNxJson(host, version);
updateGitIgnore(host); updateGitIgnore(host);
host.write(nxWrapperPath(), getNxWrapperContents()); host.write(nxWrapperPath(), getNxWrapperContents());

View File

@ -1578,7 +1578,11 @@ async function runNxMigration(
name name
); );
const fn = require(implPath)[fnSymbol]; const fn = require(implPath)[fnSymbol];
const host = new FsTree(root, process.env.NX_VERBOSE_LOGGING === 'true'); const host = new FsTree(
root,
process.env.NX_VERBOSE_LOGGING === 'true',
`migration ${collection.name}:${name}`
);
await fn(host, {}); await fn(host, {});
host.lock(); host.lock();
const changes = host.listChanges(); const changes = host.listChanges();

View File

@ -33,7 +33,7 @@ export async function newWorkspace(cwd: string, args: { [k: string]: any }) {
false false
); );
const host = new FsTree(cwd, false); const host = new FsTree(cwd, false, 'nx new');
const implementation = implementationFactory(); const implementation = implementationFactory();
const task = await implementation(host, combinedOpts); const task = await implementation(host, combinedOpts);
flushChanges(cwd, host.listChanges()); flushChanges(cwd, host.listChanges());

View File

@ -138,7 +138,11 @@ export class FsTree implements Tree {
*/ */
private locked = false; private locked = false;
constructor(readonly root: string, private readonly isVerbose: boolean) {} constructor(
readonly root: string,
private readonly isVerbose: boolean,
private readonly logOperationId?: string
) {}
read(filePath: string): Buffer | null; read(filePath: string): Buffer | null;
read(filePath: string, encoding: BufferEncoding): string | null; read(filePath: string, encoding: BufferEncoding): string | null;
@ -357,20 +361,15 @@ export class FsTree implements Tree {
private assertUnlocked() { private assertUnlocked() {
if (this.locked) { if (this.locked) {
// TODO (v17): Remove condition output.error({
if (gt(nxVersion, '17.0.0')) { title: `File changes have already been written to disk. Further changes were attempted ${
throw new Error( this.logOperationId ? ` while running ${this.logOperationId}.` : '.'
'The tree has already been committed to disk. It can no longer be modified. Do not modify the tree during a GeneratorCallback and ensure that Promises have resolved before the generator returns or resolves.' }`,
);
} else {
output.warn({
title: 'Tree modified after commit to disk.',
bodyLines: [ bodyLines: [
'The tree has already been committed to disk. It can no longer be modified. Do not modify the tree during a GeneratorCallback and ensure that Promises have resolved before the generator returns or resolves.', 'The file system can no longer be modified. This commonly happens when a generator attempts to make further changes in its callback, or an asynchronous operation is still running after the generator completes.',
`This will be an error in version 16. Please open an issue on the Nx repo if experiencing this with a first-party plugin, or the plugin's repo if using a community plugin.`,
], ],
}); });
} throw new Error('Tree changed after commit to disk.');
} }
} }

View File

@ -63,7 +63,7 @@ export default async function (tree: Tree) {
} }
} }
formatChangedFilesWithPrettierIfAvailable(tree); await formatChangedFilesWithPrettierIfAvailable(tree);
} }
function updateDependsOnAndInputsInsideNxJson(tree: Tree) { function updateDependsOnAndInputsInsideNxJson(tree: Tree) {
const nxJson = readNxJson(tree); const nxJson = readNxJson(tree);