@@ -13,14 +13,17 @@ import { execSync } from 'child_process';
1313import * as fs from 'fs' ;
1414import * as path from 'path' ;
1515import * as semver from 'semver' ;
16+ import { PackageManager } from '../lib/config/schema' ;
1617import { Command } from '../models/command' ;
1718import { Arguments } from '../models/interface' ;
19+ import { runTempPackageBin } from '../tasks/install-package' ;
1820import { colors } from '../utilities/color' ;
1921import { getPackageManager } from '../utilities/package-manager' ;
2022import {
2123 PackageIdentifier ,
2224 PackageManifest ,
2325 PackageMetadata ,
26+ fetchPackageManifest ,
2427 fetchPackageMetadata ,
2528} from '../utilities/package-metadata' ;
2629import { PackageTreeNode , findNodeDependencies , readPackageTree } from '../utilities/package-tree' ;
@@ -38,22 +41,23 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
3841 public readonly allowMissingWorkspace = true ;
3942
4043 private workflow : NodeWorkflow ;
44+ private packageManager : PackageManager ;
4145
4246 async initialize ( ) {
47+ this . packageManager = await getPackageManager ( this . workspace . root ) ;
4348 this . workflow = new NodeWorkflow (
4449 new virtualFs . ScopedHost ( new NodeJsSyncHost ( ) , normalize ( this . workspace . root ) ) ,
4550 {
46- packageManager : await getPackageManager ( this . workspace . root ) ,
51+ packageManager : this . packageManager ,
4752 root : normalize ( this . workspace . root ) ,
4853 } ,
4954 ) ;
50-
5155 this . workflow . engineHost . registerOptionsTransform (
5256 validateOptionsWithSchema ( this . workflow . registry ) ,
5357 ) ;
5458 }
5559
56- async executeSchematic (
60+ private async executeSchematic (
5761 collection : string ,
5862 schematic : string ,
5963 options = { } ,
@@ -127,7 +131,7 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
127131 }
128132 }
129133
130- async executeMigrations (
134+ private async executeMigrations (
131135 packageName : string ,
132136 collectionPath : string ,
133137 range : semver . Range ,
@@ -190,6 +194,21 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
190194
191195 // tslint:disable-next-line:no-big-function
192196 async run ( options : UpdateCommandSchema & Arguments ) {
197+ // Check if the current installed CLI version is older than the latest version.
198+ if ( await this . checkCLILatestVersion ( options . verbose ) ) {
199+ this . logger . warn (
200+ 'The installed Angular CLI version is older than the latest published version.\n' +
201+ 'Installing a temporary version to perform the update.' ,
202+ ) ;
203+
204+ return runTempPackageBin (
205+ '@angular/cli@latest' ,
206+ this . logger ,
207+ this . packageManager ,
208+ process . argv . slice ( 2 ) ,
209+ ) ;
210+ }
211+
193212 const packages : PackageIdentifier [ ] = [ ] ;
194213 for ( const request of options [ '--' ] || [ ] ) {
195214 try {
@@ -252,8 +271,7 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
252271 }
253272 }
254273
255- const packageManager = await getPackageManager ( this . workspace . root ) ;
256- this . logger . info ( `Using package manager: '${ packageManager } '` ) ;
274+ this . logger . info ( `Using package manager: '${ this . packageManager } '` ) ;
257275
258276 // Special handling for Angular CLI 1.x migrations
259277 if (
@@ -293,7 +311,7 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
293311 force : options . force || false ,
294312 next : options . next || false ,
295313 verbose : options . verbose || false ,
296- packageManager,
314+ packageManager : this . packageManager ,
297315 packages : options . all ? Object . keys ( rootDependencies ) : [ ] ,
298316 } ) ;
299317
@@ -513,7 +531,7 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
513531 const { success } = await this . executeSchematic ( '@schematics/update' , 'update' , {
514532 verbose : options . verbose || false ,
515533 force : options . force || false ,
516- packageManager,
534+ packageManager : this . packageManager ,
517535 packages : packagesToUpdate ,
518536 migrateExternal : true ,
519537 } ) ;
@@ -549,7 +567,7 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
549567 return success ? 0 : 1 ;
550568 }
551569
552- checkCleanGit ( ) {
570+ private checkCleanGit ( ) : boolean {
553571 try {
554572 const topLevel = execSync ( 'git rev-parse --show-toplevel' , { encoding : 'utf8' , stdio : 'pipe' } ) ;
555573 const result = execSync ( 'git status --porcelain' , { encoding : 'utf8' , stdio : 'pipe' } ) ;
@@ -573,15 +591,15 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
573591 return true ;
574592 }
575593
576- createCommit ( message : string , files : string [ ] ) {
594+ private createCommit ( message : string , files : string [ ] ) {
577595 try {
578596 execSync ( 'git add -A ' + files . join ( ' ' ) , { encoding : 'utf8' , stdio : 'pipe' } ) ;
579597
580598 execSync ( `git commit --no-verify -m "${ message } "` , { encoding : 'utf8' , stdio : 'pipe' } ) ;
581599 } catch ( error ) { }
582600 }
583601
584- findCurrentGitSha ( ) : string | null {
602+ private findCurrentGitSha ( ) : string | null {
585603 try {
586604 const result = execSync ( 'git rev-parse HEAD' , { encoding : 'utf8' , stdio : 'pipe' } ) ;
587605
@@ -590,6 +608,25 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
590608 return null ;
591609 }
592610 }
611+
612+ /**
613+ * Checks if the current installed CLI version is older than the latest version.
614+ * @returns `true` when the installed version is older.
615+ */
616+ private async checkCLILatestVersion ( verbose = false ) : Promise < boolean > {
617+ const { version : installedCLIVersion } = require ( '../package.json' ) ;
618+
619+ const LatestCLIManifest = await fetchPackageManifest (
620+ '@angular/cli@latest' ,
621+ this . logger ,
622+ {
623+ verbose,
624+ usingYarn : this . packageManager === PackageManager . Yarn ,
625+ } ,
626+ ) ;
627+
628+ return semver . lt ( installedCLIVersion , LatestCLIManifest . version ) ;
629+ }
593630}
594631
595632function coerceVersionNumber ( version : string | undefined ) : string | null {
0 commit comments