From f95f8c4b69cde6653c12a83215a4a40a9cabea8d Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Tue, 23 May 2023 17:07:08 -0400 Subject: [PATCH] fix(core): tree should not be changed after committed to disk in migrations (#17071) --- packages/nx/src/adapter/ngcli-adapter.ts | 12 ++++++-- .../nx/src/command-line/generate/generate.ts | 6 +++- .../implementation/dot-nx/add-nx-scripts.ts | 2 +- .../nx/src/command-line/migrate/migrate.ts | 6 +++- packages/nx/src/command-line/new/new.ts | 2 +- packages/nx/src/generators/tree.ts | 29 +++++++++---------- .../update-depends-on-to-tokens.ts | 2 +- 7 files changed, 37 insertions(+), 22 deletions(-) diff --git a/packages/nx/src/adapter/ngcli-adapter.ts b/packages/nx/src/adapter/ngcli-adapter.ts index 1f3bb6398e..8c8ba0e8d6 100644 --- a/packages/nx/src/adapter/ngcli-adapter.ts +++ b/packages/nx/src/adapter/ngcli-adapter.ts @@ -656,7 +656,11 @@ export async function generate( const logger = getLogger(verbose); const fsHost = new NxScopeHostUsedForWrappedSchematics( root, - new FsTree(root, verbose) + new FsTree( + root, + verbose, + `ng-cli generator: ${opts.collectionName}:${opts.generatorName}` + ) ); const workflow = createWorkflow(fsHost, root, opts); const collection = getCollection(workflow, opts.collectionName); @@ -745,7 +749,11 @@ export async function runMigration( const logger = getLogger(isVerbose); const fsHost = new NxScopeHostUsedForWrappedSchematics( root, - new FsTree(root, isVerbose) + new FsTree( + root, + isVerbose, + `ng-cli migration: ${packageName}:${migrationName}` + ) ); const workflow = createWorkflow(fsHost, root, {}); const collection = resolveMigrationsCollection(packageName); diff --git a/packages/nx/src/command-line/generate/generate.ts b/packages/nx/src/command-line/generate/generate.ts index d3ffcfb8b7..168f0df05a 100644 --- a/packages/nx/src/command-line/generate/generate.ts +++ b/packages/nx/src/command-line/generate/generate.ts @@ -364,7 +364,11 @@ export async function generate(cwd: string, args: { [k: string]: any }) { ); 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(); // @todo(v17): Remove this, isStandalonePreset property is defunct. diff --git a/packages/nx/src/command-line/init/implementation/dot-nx/add-nx-scripts.ts b/packages/nx/src/command-line/init/implementation/dot-nx/add-nx-scripts.ts index 093a6b56a2..312243b5f6 100644 --- a/packages/nx/src/command-line/init/implementation/dot-nx/add-nx-scripts.ts +++ b/packages/nx/src/command-line/init/implementation/dot-nx/add-nx-scripts.ts @@ -33,7 +33,7 @@ path_to_root=$(dirname $BASH_SOURCE) node ${path.posix.join('$path_to_root', nxWrapperPath(path.posix))} $@`; export function generateDotNxSetup(version?: string) { - const host = new FsTree(process.cwd(), false); + const host = new FsTree(process.cwd(), false, '.nx setup'); writeMinimalNxJson(host, version); updateGitIgnore(host); host.write(nxWrapperPath(), getNxWrapperContents()); diff --git a/packages/nx/src/command-line/migrate/migrate.ts b/packages/nx/src/command-line/migrate/migrate.ts index 53837dc8bb..e0a94d9c2a 100644 --- a/packages/nx/src/command-line/migrate/migrate.ts +++ b/packages/nx/src/command-line/migrate/migrate.ts @@ -1578,7 +1578,11 @@ async function runNxMigration( name ); 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, {}); host.lock(); const changes = host.listChanges(); diff --git a/packages/nx/src/command-line/new/new.ts b/packages/nx/src/command-line/new/new.ts index cba3a78979..ffcd7fc83e 100644 --- a/packages/nx/src/command-line/new/new.ts +++ b/packages/nx/src/command-line/new/new.ts @@ -33,7 +33,7 @@ export async function newWorkspace(cwd: string, args: { [k: string]: any }) { false ); - const host = new FsTree(cwd, false); + const host = new FsTree(cwd, false, 'nx new'); const implementation = implementationFactory(); const task = await implementation(host, combinedOpts); flushChanges(cwd, host.listChanges()); diff --git a/packages/nx/src/generators/tree.ts b/packages/nx/src/generators/tree.ts index 5c24df0881..60ff652576 100644 --- a/packages/nx/src/generators/tree.ts +++ b/packages/nx/src/generators/tree.ts @@ -138,7 +138,11 @@ export class FsTree implements Tree { */ 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, encoding: BufferEncoding): string | null; @@ -357,20 +361,15 @@ export class FsTree implements Tree { private assertUnlocked() { if (this.locked) { - // TODO (v17): Remove condition - if (gt(nxVersion, '17.0.0')) { - throw new Error( - '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: [ - '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.', - `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.`, - ], - }); - } + output.error({ + title: `File changes have already been written to disk. Further changes were attempted ${ + this.logOperationId ? ` while running ${this.logOperationId}.` : '.' + }`, + bodyLines: [ + '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.', + ], + }); + throw new Error('Tree changed after commit to disk.'); } } diff --git a/packages/nx/src/migrations/update-16-0-0/update-depends-on-to-tokens.ts b/packages/nx/src/migrations/update-16-0-0/update-depends-on-to-tokens.ts index 30a75b27b2..6fabe17983 100644 --- a/packages/nx/src/migrations/update-16-0-0/update-depends-on-to-tokens.ts +++ b/packages/nx/src/migrations/update-16-0-0/update-depends-on-to-tokens.ts @@ -63,7 +63,7 @@ export default async function (tree: Tree) { } } - formatChangedFilesWithPrettierIfAvailable(tree); + await formatChangedFilesWithPrettierIfAvailable(tree); } function updateDependsOnAndInputsInsideNxJson(tree: Tree) { const nxJson = readNxJson(tree);