@@ -75,8 +75,11 @@ type Flags = {
7575 // outdated, update-interactive
7676 includeWorkspaceDeps : boolean ,
7777
78- // remove, upgrade
78+ // add, remove, upgrade
7979 workspaceRootIsCwd : boolean ,
80+
81+ // focus
82+ focus : boolean ,
8083} ;
8184
8285/**
@@ -155,6 +158,9 @@ function normalizeFlags(config: Config, rawFlags: Object): Flags {
155158
156159 // add, remove, update
157160 workspaceRootIsCwd : rawFlags . workspaceRootIsCwd !== false ,
161+
162+ // focus
163+ focus : ! ! rawFlags . focus ,
158164 } ;
159165
160166 if ( config . getOption ( 'ignore-scripts' ) ) {
@@ -514,6 +520,11 @@ export class Install {
514520 this . reporter . warn ( this . reporter . lang ( 'shrinkwrapWarning' ) ) ;
515521 }
516522
523+ // running a focused install in a workspace root is not allowed
524+ if ( this . flags . focus && ( ! this . config . workspaceRootFolder || this . config . cwd === this . config . workspaceRootFolder ) ) {
525+ throw new MessageError ( this . reporter . lang ( 'workspacesFocusRootCheck' ) ) ;
526+ }
527+
517528 let flattenedTopLevelPatterns : Array < string > = [ ] ;
518529 const steps : Array < ( curr : number , total : number ) => Promise < { bailout : boolean } | void >> = [ ] ;
519530 const {
@@ -545,6 +556,7 @@ export class Install {
545556 isFlat : this . flags . flat ,
546557 isFrozen : this . flags . frozenLockfile ,
547558 workspaceLayout,
559+ focus : this . flags . focus ,
548560 } ) ;
549561 topLevelPatterns = this . preparePatterns ( rawPatterns ) ;
550562 flattenedTopLevelPatterns = await this . flatten ( topLevelPatterns ) ;
@@ -575,6 +587,7 @@ export class Install {
575587 await this . linker . init ( flattenedTopLevelPatterns , workspaceLayout , {
576588 linkDuplicates : this . flags . linkDuplicates ,
577589 ignoreOptional : this . flags . ignoreOptional ,
590+ focus : this . flags . focus ,
578591 } ) ;
579592 } ) ,
580593 ) ;
@@ -633,7 +646,7 @@ export class Install {
633646 ( await fs . exists ( path . join ( this . config . lockfileFolder , constants . LOCKFILE_FILENAME ) ) )
634647 ) {
635648 await this . saveLockfileAndIntegrity ( topLevelPatterns , workspaceLayout ) ;
636- } else {
649+ } else if ( ! this . flags . focus ) {
637650 this . reporter . info ( this . reporter . lang ( 'notSavedLockfileNoDependencies' ) ) ;
638651 }
639652 this . maybeOutputUpdate ( ) ;
@@ -805,7 +818,7 @@ export class Install {
805818 this . scripts . getArtifacts ( ) ,
806819 ) ;
807820
808- // --no-lockfile or --pure-lockfile or --frozen-lockfile flag
821+ // --no-lockfile or --pure-lockfile or --frozen-lockfile or --focus flag
809822 if ( this . flags . lockfile === false || this . flags . pureLockfile || this . flags . frozenLockfile ) {
810823 return ;
811824 }
@@ -884,7 +897,7 @@ export class Install {
884897 }
885898 loc = ref . remote . reference ;
886899 } else {
887- loc = this . config . generateHardModulePath ( ref ) ;
900+ loc = this . config . generateModuleCachePath ( ref ) ;
888901 }
889902 const newPkg = await this . config . readManifest ( loc ) ;
890903 await this . resolver . updateManifest ( ref , newPkg ) ;
@@ -973,6 +986,7 @@ export function hasWrapper(commander: Object, args: Array<string>): boolean {
973986export function setFlags(commander: Object) {
974987 commander . description ( 'Yarn install is used to install all dependencies for a project.' ) ;
975988 commander . usage ( 'install [flags]' ) ;
989+ commander . option ( '--focus' , 'Focus on a single workspace by installing remote copies of its sibling workspaces.' ) ;
976990 commander . option ( '-g, --global' , 'DEPRECATED' ) ;
977991 commander . option ( '-S, --save' , 'DEPRECATED - save package to your `dependencies`' ) ;
978992 commander . option ( '-D, --save-dev' , 'DEPRECATED - save package to your `devDependencies`' ) ;
0 commit comments