11// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
22// See LICENSE in the project root for license information.
33
4- import * as os from 'os' ;
54import * as colors from 'colors' ;
6- import { CommandLineParser , CommandLineFlagParameter } from '@microsoft/ts-command-line' ;
5+ import * as os from 'os' ;
6+ import * as path from 'path' ;
7+
8+ import { CommandLineParser , CommandLineFlagParameter , CommandLineAction } from '@microsoft/ts-command-line' ;
79
810import { RushConfiguration } from '../api/RushConfiguration' ;
11+ import { RushConstants } from '../api/RushConstants' ;
12+ import { CommandLineConfiguration } from '../api/CommandLineConfiguration' ;
13+ import { CommandJson } from '../api/CommandLineJson' ;
914import { Utilities } from '../utilities/Utilities' ;
15+ import { BaseScriptAction } from '../cli/scriptActions/BaseScriptAction' ;
16+
1017import { ChangeAction } from './actions/ChangeAction' ;
1118import { CheckAction } from './actions/CheckAction' ;
1219import { UpdateAction } from './actions/UpdateAction' ;
@@ -17,7 +24,9 @@ import { PurgeAction } from './actions/PurgeAction';
1724import { UnlinkAction } from './actions/UnlinkAction' ;
1825import { ScanAction } from './actions/ScanAction' ;
1926import { VersionAction } from './actions/VersionAction' ;
20- import { CustomCommandFactory } from './custom/CustomCommandFactory' ;
27+
28+ import { BulkScriptAction } from './scriptActions/BulkScriptAction' ;
29+ import { GlobalScriptAction } from './scriptActions/GlobalScriptAction' ;
2130
2231import { Telemetry } from '../logic/Telemetry' ;
2332import { AlreadyReportedError } from '../utilities/AlreadyReportedError' ;
@@ -100,17 +109,117 @@ export class RushCommandLineParser extends CommandLineParser {
100109 this . addAction ( new UnlinkAction ( this ) ) ;
101110 this . addAction ( new VersionAction ( this ) ) ;
102111
103- CustomCommandFactory . addActions ( this ) ;
112+ this . _populateScriptActions ( ) ;
104113
105114 } catch ( error ) {
106115 this . _reportErrorAndSetExitCode ( error ) ;
107116 }
108117 }
109118
119+ private _populateScriptActions ( ) : void {
120+ if ( ! this . rushConfiguration ) {
121+ return ;
122+ }
123+
124+ const commandLineConfigFile : string = path . join (
125+ this . rushConfiguration . commonRushConfigFolder , RushConstants . commandLineFilename
126+ ) ;
127+ const commandLineConfiguration : CommandLineConfiguration
128+ = CommandLineConfiguration . loadFromFileOrDefault ( commandLineConfigFile ) ;
129+
130+ const documentationForBuild : string = 'The Rush build command assumes that the package.json file for each'
131+ + ' project contains a "scripts" entry for "npm run build". It invokes'
132+ + ' this commands to build each project. Projects are built in parallel where'
133+ + ' possible, but always respecting the dependency graph for locally linked projects.'
134+ + ' The number of simultaneous processes will be based on the number of machine cores'
135+ + ' unless overridden by the --parallelism flag.' ;
136+
137+ // always create a build and a rebuild command
138+ this . addAction ( new BulkScriptAction ( {
139+ actionName : 'build' ,
140+ summary : '(EXPERIMENTAL) Build all projects that haven\'t been built, or have changed since they were last '
141+ + 'built.' ,
142+ documentation : documentationForBuild ,
143+
144+ parser : this ,
145+ commandLineConfiguration : commandLineConfiguration ,
146+
147+ enableParallelism : true ,
148+ ignoreMissingScript : false
149+ } ) ) ;
150+
151+ this . addAction ( new BulkScriptAction ( {
152+ actionName : 'rebuild' ,
153+ summary : 'Clean and rebuild the entire set of projects' ,
154+ documentation : documentationForBuild ,
155+
156+ parser : this ,
157+ commandLineConfiguration : commandLineConfiguration ,
158+
159+ enableParallelism : true ,
160+ ignoreMissingScript : false
161+ } ) ) ;
162+
163+ // Register each custom command
164+ for ( const command of commandLineConfiguration . commands ) {
165+ if ( this . tryGetAction ( command . name ) ) {
166+ throw new Error ( `${ RushConstants . commandLineFilename } defines a command "${ command . name } "`
167+ + ` using a name that already exists` ) ;
168+ }
169+
170+ switch ( command . commandKind ) {
171+ case 'bulk' :
172+ this . addAction ( new BulkScriptAction ( {
173+ actionName : command . name ,
174+ summary : command . summary ,
175+ documentation : command . description || command . summary ,
176+
177+ parser : this ,
178+ commandLineConfiguration : commandLineConfiguration ,
179+
180+ enableParallelism : command . enableParallelism ,
181+ ignoreMissingScript : command . ignoreMissingScript || false
182+ } ) ) ;
183+ break ;
184+ case 'global' :
185+ this . addAction ( new GlobalScriptAction ( {
186+ actionName : command . name ,
187+ summary : command . summary ,
188+ documentation : command . description || command . summary ,
189+
190+ parser : this ,
191+ commandLineConfiguration : commandLineConfiguration ,
192+
193+ shellCommand : command . shellCommand
194+ } ) ) ;
195+ break ;
196+ default :
197+ throw new Error ( `${ RushConstants . commandLineFilename } defines a command "${ command ! . name } "`
198+ + ` using an unsupported command kind "${ command ! . commandKind } "` ) ;
199+ }
200+ }
201+
202+ // Check for any invalid associations
203+ for ( const parameter of commandLineConfiguration . parameters ) {
204+ for ( const associatedCommand of parameter . associatedCommands ) {
205+ const action : CommandLineAction | undefined = this . tryGetAction ( associatedCommand ) ;
206+ if ( ! action ) {
207+ throw new Error ( `${ RushConstants . commandLineFilename } defines a parameter "${ parameter . longName } "`
208+ + ` that is associated with a nonexistent command "${ associatedCommand } "` ) ;
209+ }
210+ if ( ! ( action instanceof BaseScriptAction ) ) {
211+ throw new Error ( `${ RushConstants . commandLineFilename } defines a parameter "${ parameter . longName } "`
212+ + ` that is associated with a command "${ associatedCommand } ", but that command does not`
213+ + ` support custom parameters` ) ;
214+ }
215+ }
216+ }
217+ }
218+
110219 private _reportErrorAndSetExitCode ( error : Error ) : void {
111220 if ( ! ( error instanceof AlreadyReportedError ) ) {
112221 const prefix : string = 'ERROR: ' ;
113- console . error ( os . EOL + colors . red ( prefix + Utilities . wrapWords ( error . message ) . trim ( ) ) ) ;
222+ console . error ( os . EOL + colors . red ( Utilities . wrapWords ( prefix + error . message ) ) ) ;
114223 }
115224
116225 if ( this . _debugParameter . value ) {
@@ -127,6 +236,10 @@ export class RushCommandLineParser extends CommandLineParser {
127236 // performs nontrivial work that can throw an exception. Either the Rush class would need
128237 // to handle reporting for those exceptions, or else _populateActions() should be moved
129238 // to a RushCommandLineParser lifecycle stage that can handle it.
130- process . exit ( 1 ) ;
239+ if ( process . exitCode > 0 ) {
240+ process . exit ( process . exitCode ) ;
241+ } else {
242+ process . exit ( 1 ) ;
243+ }
131244 }
132245}
0 commit comments