@@ -5,7 +5,7 @@ import colors from 'colors/safe';
5
5
import * as os from 'os' ;
6
6
import * as path from 'path' ;
7
7
import * as semver from 'semver' ;
8
- import { FileSystem , FileConstants , AlreadyReportedError } from '@rushstack/node-core-library' ;
8
+ import { FileSystem , FileConstants , AlreadyReportedError , Async } from '@rushstack/node-core-library' ;
9
9
10
10
import { BaseInstallManager , IInstallManagerOptions } from '../base/BaseInstallManager' ;
11
11
import { BaseShrinkwrapFile } from '../../logic/base/BaseShrinkwrapFile' ;
@@ -21,6 +21,7 @@ import { RepoStateFile } from '../RepoStateFile';
21
21
import { LastLinkFlagFactory } from '../../api/LastLinkFlag' ;
22
22
import { EnvironmentConfiguration } from '../../api/EnvironmentConfiguration' ;
23
23
import { ShrinkwrapFileFactory } from '../ShrinkwrapFileFactory' ;
24
+ import { BaseProjectShrinkwrapFile } from '../base/BaseProjectShrinkwrapFile' ;
24
25
25
26
/**
26
27
* This class implements common logic between "rush install" and "rush update".
@@ -373,19 +374,44 @@ export class WorkspaceInstallManager extends BaseInstallManager {
373
374
protected async postInstallAsync ( ) : Promise < void > {
374
375
// Grab the temp shrinkwrap, as this was the most recently completed install. It may also be
375
376
// more up-to-date than the checked-in shrinkwrap since filtered installs are not written back.
376
- const tempShrinkwrapFile : BaseShrinkwrapFile = ShrinkwrapFileFactory . getShrinkwrapFile (
377
+ // Note that if there are no projects, or if we're in PNPM workspace mode and there are no
378
+ // projects with dependencies, a lockfile won't be generated.
379
+ const tempShrinkwrapFile : BaseShrinkwrapFile | undefined = ShrinkwrapFileFactory . getShrinkwrapFile (
377
380
this . rushConfiguration . packageManager ,
378
381
this . rushConfiguration . pnpmOptions ,
379
382
this . rushConfiguration . tempShrinkwrapFilename
380
- ) ! ;
381
-
382
- // Write or delete all project shrinkwraps related to the install
383
- await Promise . all (
384
- this . rushConfiguration . projects . map ( async ( project ) => {
385
- await tempShrinkwrapFile . getProjectShrinkwrap ( project ) ?. updateProjectShrinkwrapAsync ( ) ;
386
- } )
387
383
) ;
388
384
385
+ if ( tempShrinkwrapFile ) {
386
+ // Write or delete all project shrinkwraps related to the install
387
+ await Async . forEachAsync (
388
+ this . rushConfiguration . projects ,
389
+ async ( project ) => {
390
+ await tempShrinkwrapFile . getProjectShrinkwrap ( project ) ?. updateProjectShrinkwrapAsync ( ) ;
391
+ } ,
392
+ { concurrency : 10 }
393
+ ) ;
394
+ } else if (
395
+ this . rushConfiguration . packageManager === 'pnpm' &&
396
+ this . rushConfiguration . pnpmOptions ?. useWorkspaces
397
+ ) {
398
+ // If we're in PNPM workspace mode and PNPM didn't create a shrinkwrap file,
399
+ // there are no dependencies. Generate empty shrinkwrap files for all projects.
400
+ await Async . forEachAsync (
401
+ this . rushConfiguration . projects ,
402
+ async ( project ) => {
403
+ await BaseProjectShrinkwrapFile . saveEmptyProjectShrinkwrapFileAsync ( project ) ;
404
+ } ,
405
+ { concurrency : 10 }
406
+ ) ;
407
+ } else {
408
+ // This is an unexpected case
409
+ throw new Error (
410
+ 'A shrinkwrap file does not exist after after successful installation. This probably indicates a ' +
411
+ 'bug in the package manager.'
412
+ ) ;
413
+ }
414
+
389
415
// TODO: Remove when "rush link" and "rush unlink" are deprecated
390
416
LastLinkFlagFactory . getCommonTempFlag ( this . rushConfiguration ) . create ( ) ;
391
417
}
0 commit comments