diff --git a/src/cdk/schematics/ng-update/upgrade-rules/index.ts b/src/cdk/schematics/ng-update/upgrade-rules/index.ts index db5d1e25461a..d53d445435c6 100644 --- a/src/cdk/schematics/ng-update/upgrade-rules/index.ts +++ b/src/cdk/schematics/ng-update/upgrade-rules/index.ts @@ -7,6 +7,7 @@ */ import {Rule, SchematicContext, Tree} from '@angular-devkit/schematics'; +import {NodePackageInstallTask} from '@angular-devkit/schematics/tasks'; import {MigrationRuleType, runMigrationRules} from '../../update-tool'; import {TargetVersion} from '../../update-tool/target-version'; @@ -79,12 +80,23 @@ export function createUpgradeRule( buildPaths.forEach(p => runMigration(p, false)); testPaths.forEach(p => runMigration(p, true)); + let runPackageManager = false; + // Run the global post migration static members for all migration rules. - rules.forEach(r => r.globalPostMigration(tree, context)); + rules.forEach(rule => { + const actionResult = rule.globalPostMigration(tree, context); + if (actionResult) { + runPackageManager = runPackageManager || actionResult.runPackageManager; + } + }); - // Execute all asynchronous tasks and await them here. We want to run - // the "onMigrationCompleteFn" after all work is done. - await context.engine.executePostTasks().toPromise(); + // If a rule requested the package manager to run, we run it as an + // asynchronous post migration task. We cannot run it synchronously, + // as file changes from the current migration task are not applied to + // the file system yet. + if (runPackageManager) { + context.addTask(new NodePackageInstallTask({quiet: false})); + } if (onMigrationCompleteFn) { onMigrationCompleteFn(targetVersion, hasRuleFailures); diff --git a/src/cdk/schematics/update-tool/migration-rule.ts b/src/cdk/schematics/update-tool/migration-rule.ts index 7399354fdbbc..eb397d8cc799 100644 --- a/src/cdk/schematics/update-tool/migration-rule.ts +++ b/src/cdk/schematics/update-tool/migration-rule.ts @@ -19,6 +19,11 @@ export interface MigrationFailure { position?: LineAndCharacter; } +export type PostMigrationAction = void | { + /** Whether the package manager should run upon migration completion. */ + runPackageManager: boolean; +}; + export class MigrationRule { /** List of migration failures that need to be reported. */ failures: MigrationFailure[] = []; @@ -92,5 +97,5 @@ export class MigrationRule { * migration result of all individual targets. e.g. removing HammerJS if it * is not needed in any project target. */ - static globalPostMigration(tree: Tree, context: SchematicContext) {} + static globalPostMigration(tree: Tree, context: SchematicContext): PostMigrationAction {} } diff --git a/src/material/schematics/ng-update/upgrade-rules/hammer-gestures-v9/hammer-gestures-rule.ts b/src/material/schematics/ng-update/upgrade-rules/hammer-gestures-v9/hammer-gestures-rule.ts index 89aaf38a5202..d0bbc4829b56 100644 --- a/src/material/schematics/ng-update/upgrade-rules/hammer-gestures-v9/hammer-gestures-rule.ts +++ b/src/material/schematics/ng-update/upgrade-rules/hammer-gestures-v9/hammer-gestures-rule.ts @@ -12,12 +12,12 @@ import { Path as DevkitPath } from '@angular-devkit/core'; import {SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics'; -import {NodePackageInstallTask} from '@angular-devkit/schematics/tasks'; import { getProjectIndexFiles, getProjectMainFile, MigrationFailure, MigrationRule, + PostMigrationAction, ResolvedResource, TargetVersion } from '@angular/cdk/schematics'; @@ -762,11 +762,11 @@ export class HammerGesturesRule extends MigrationRule { * on the analysis of the individual targets. For example: we only remove Hammer * from the "package.json" if it is not used in *any* project target. */ - static globalPostMigration(tree: Tree, context: SchematicContext) { + static globalPostMigration(tree: Tree, context: SchematicContext): PostMigrationAction { if (!this.globalUsesHammer && this._removeHammerFromPackageJson(tree)) { // Since Hammer has been removed from the workspace "package.json" file, // we schedule a node package install task to refresh the lock file. - context.addTask(new NodePackageInstallTask({quiet: false})); + return {runPackageManager: true}; } context.logger.info(chalk.yellow(