44import * as colors from 'colors' ;
55import * as os from 'os' ;
66import { Interleaver } from '@microsoft/stream-collator' ;
7+ import {
8+ Terminal , ConsoleTerminalProvider , ITerminalProvider
9+ } from '@microsoft/node-core-library' ;
710
811import { Stopwatch } from '../../utilities/Stopwatch' ;
912import { ITask , ITaskDefinition } from './ITask' ;
@@ -15,9 +18,7 @@ import { TaskError } from './TaskError';
1518 * Any class of task definition may be registered, and dependencies between tasks are
1619 * easily specified. Initially, and at the end of each task execution, all unblocked tasks
1720 * are added to a ready queue which is then executed. This is done continually until all
18- * tasks are complete, or prematurely fails if any of the tasks fail. Note that all task
19- * definitions must
20- * @todo #168352: add unit tests
21+ * tasks are complete, or prematurely fails if any of the tasks fail.
2122 */
2223export class TaskRunner {
2324 private _tasks : Map < string , ITask > ;
@@ -29,15 +30,20 @@ export class TaskRunner {
2930 private _currentActiveTasks : number ;
3031 private _totalTasks : number ;
3132 private _completedTasks : number ;
32-
33- constructor ( quietMode : boolean ,
34- parallelism : string | undefined ,
35- changedProjectsOnly : boolean ) {
33+ private _terminal : Terminal ;
34+
35+ constructor (
36+ quietMode : boolean ,
37+ parallelism : string | undefined ,
38+ changedProjectsOnly : boolean ,
39+ customTerminal ?: ITerminalProvider
40+ ) {
3641 this . _tasks = new Map < string , ITask > ( ) ;
3742 this . _buildQueue = [ ] ;
3843 this . _quietMode = quietMode ;
3944 this . _hasAnyFailures = false ;
4045 this . _changedProjectsOnly = changedProjectsOnly ;
46+ this . _terminal = new Terminal ( customTerminal || new ConsoleTerminalProvider ( ) ) ;
4147
4248 const numberOfCores : number = os . cpus ( ) . length ;
4349
@@ -53,8 +59,7 @@ export class TaskRunner {
5359
5460 this . _parallelism = parallelismInt ;
5561 }
56-
57- } else {
62+ } else {
5863 // If an explicit parallelism number wasn't provided, then choose a sensible
5964 // default.
6065 if ( os . platform ( ) === 'win32' ) {
@@ -86,7 +91,7 @@ export class TaskRunner {
8691 this . _tasks . set ( task . name , task ) ;
8792
8893 if ( ! this . _quietMode ) {
89- console . log ( `Registered ${ task . name } ` ) ;
94+ this . _terminal . writeLine ( `Registered ${ task . name } ` ) ;
9095 }
9196 }
9297
@@ -131,7 +136,7 @@ export class TaskRunner {
131136 this . _currentActiveTasks = 0 ;
132137 this . _completedTasks = 0 ;
133138 this . _totalTasks = this . _tasks . size ;
134- console . log ( `Executing a maximum of ${ this . _parallelism } simultaneous processes...${ os . EOL } ` ) ;
139+ this . _terminal . writeLine ( `Executing a maximum of ${ this . _parallelism } simultaneous processes...${ os . EOL } ` ) ;
135140
136141 this . _checkForCyclicDependencies ( this . _tasks . values ( ) , [ ] ) ;
137142
@@ -194,7 +199,7 @@ export class TaskRunner {
194199 this . _currentActiveTasks ++ ;
195200 const task : ITask = ctask ;
196201 task . status = TaskStatus . Executing ;
197- console . log ( colors . white ( `[${ task . name } ] started` ) ) ;
202+ this . _terminal . writeLine ( colors . white ( `[${ task . name } ] started` ) ) ;
198203
199204 task . stopwatch = Stopwatch . start ( ) ;
200205 task . writer = Interleaver . registerTask ( task . name , this . _quietMode ) ;
@@ -230,7 +235,7 @@ export class TaskRunner {
230235 task . error = error ;
231236 this . _markTaskAsFailed ( task ) ;
232237 }
233- ) . then ( ( ) => this . _startAvailableTasks ( ) ) ) ;
238+ ) . then ( ( ) => this . _startAvailableTasks ( ) ) ) ;
234239 }
235240
236241 return Promise . all ( taskPromises ) . then ( ( ) => { /* collapse void[] to void */ } ) ;
@@ -240,7 +245,7 @@ export class TaskRunner {
240245 * Marks a task as having failed and marks each of its dependents as blocked
241246 */
242247 private _markTaskAsFailed ( task : ITask ) : void {
243- console . log ( colors . red ( `${ os . EOL } ${ this . _getCurrentCompletedTaskString ( ) } [${ task . name } ] failed to build!` ) ) ;
248+ this . _terminal . writeErrorLine ( `${ os . EOL } ${ this . _getCurrentCompletedTaskString ( ) } [${ task . name } ] failed to build!` ) ;
244249 task . status = TaskStatus . Failure ;
245250 task . dependents . forEach ( ( dependent : ITask ) => {
246251 this . _markTaskAsBlocked ( dependent , task ) ;
@@ -253,8 +258,8 @@ export class TaskRunner {
253258 private _markTaskAsBlocked ( task : ITask , failedTask : ITask ) : void {
254259 if ( task . status === TaskStatus . Ready ) {
255260 this . _completedTasks ++ ;
256- console . log ( colors . red ( `${ this . _getCurrentCompletedTaskString ( ) } `
257- + `[${ task . name } ] blocked by [${ failedTask . name } ]!` ) ) ;
261+ this . _terminal . writeErrorLine ( `${ this . _getCurrentCompletedTaskString ( ) } `
262+ + `[${ task . name } ] blocked by [${ failedTask . name } ]!` ) ;
258263 task . status = TaskStatus . Blocked ;
259264 task . dependents . forEach ( ( dependent : ITask ) => {
260265 this . _markTaskAsBlocked ( dependent , failedTask ) ;
@@ -266,7 +271,7 @@ export class TaskRunner {
266271 * Marks a task as being completed, and removes it from the dependencies list of all its dependents
267272 */
268273 private _markTaskAsSuccess ( task : ITask ) : void {
269- console . log ( colors . green ( `${ this . _getCurrentCompletedTaskString ( ) } `
274+ this . _terminal . writeLine ( colors . green ( `${ this . _getCurrentCompletedTaskString ( ) } `
270275 + `[${ task . name } ] completed successfully in ${ task . stopwatch . toString ( ) } ` ) ) ;
271276 task . status = TaskStatus . Success ;
272277
@@ -283,8 +288,8 @@ export class TaskRunner {
283288 * list of all its dependents
284289 */
285290 private _markTaskAsSuccessWithWarning ( task : ITask ) : void {
286- console . log ( colors . yellow ( `${ this . _getCurrentCompletedTaskString ( ) } `
287- + `[${ task . name } ] completed with warnings in ${ task . stopwatch . toString ( ) } ` ) ) ;
291+ this . _terminal . writeWarningLine ( `${ this . _getCurrentCompletedTaskString ( ) } `
292+ + `[${ task . name } ] completed with warnings in ${ task . stopwatch . toString ( ) } ` ) ;
288293 task . status = TaskStatus . SuccessWithWarning ;
289294 task . dependents . forEach ( ( dependent : ITask ) => {
290295 if ( ! this . _changedProjectsOnly ) {
@@ -298,7 +303,7 @@ export class TaskRunner {
298303 * Marks a task as skipped.
299304 */
300305 private _markTaskAsSkipped ( task : ITask ) : void {
301- console . log ( colors . green ( `${ this . _getCurrentCompletedTaskString ( ) } [${ task . name } ] skipped` ) ) ;
306+ this . _terminal . writeLine ( colors . green ( `${ this . _getCurrentCompletedTaskString ( ) } [${ task . name } ] skipped` ) ) ;
302307 task . status = TaskStatus . Skipped ;
303308 task . dependents . forEach ( ( dependent : ITask ) => {
304309 dependent . dependencies . delete ( task ) ;
@@ -330,7 +335,6 @@ export class TaskRunner {
330335 * the furthest away "root" node
331336 */
332337 private _calculateCriticalPaths ( task : ITask ) : number {
333-
334338 // Return the memoized value
335339 if ( task . criticalPathLength !== undefined ) {
336340 return task . criticalPathLength ;
@@ -360,7 +364,7 @@ export class TaskRunner {
360364 }
361365 } ) ;
362366
363- console . log ( '' ) ;
367+ this . _terminal . writeLine ( '' ) ;
364368
365369 this . _printStatus ( TaskStatus . Executing , tasksByStatus , colors . yellow ) ;
366370 this . _printStatus ( TaskStatus . Ready , tasksByStatus , colors . white ) ;
@@ -374,12 +378,12 @@ export class TaskRunner {
374378 if ( tasksWithErrors ) {
375379 tasksWithErrors . forEach ( ( task : ITask ) => {
376380 if ( task . error ) {
377- console . log ( colors . red ( `[${ task . name } ] ${ task . error . message } ` ) ) ;
381+ this . _terminal . writeErrorLine ( `[${ task . name } ] ${ task . error . message } ` ) ;
378382 }
379383 } ) ;
380384 }
381385
382- console . log ( '' ) ;
386+ this . _terminal . writeLine ( '' ) ;
383387 }
384388
385389 private _printStatus (
@@ -390,16 +394,16 @@ export class TaskRunner {
390394 const tasks : ITask [ ] = tasksByStatus [ status ] ;
391395
392396 if ( tasks && tasks . length ) {
393- console . log ( color ( `${ status } (${ tasks . length } )` ) ) ;
394- console . log ( color ( '================================' ) ) ;
397+ this . _terminal . writeLine ( color ( `${ status } (${ tasks . length } )` ) ) ;
398+ this . _terminal . writeLine ( color ( '================================' ) ) ;
395399 for ( let i : number = 0 ; i < tasks . length ; i ++ ) {
396400 const task : ITask = tasks [ i ] ;
397401
398402 switch ( status ) {
399403 case TaskStatus . Executing :
400404 case TaskStatus . Ready :
401405 case TaskStatus . Skipped :
402- console . log ( color ( task . name ) ) ;
406+ this . _terminal . writeLine ( color ( task . name ) ) ;
403407 break ;
404408
405409 case TaskStatus . Success :
@@ -408,9 +412,9 @@ export class TaskRunner {
408412 case TaskStatus . Failure :
409413 if ( task . stopwatch ) {
410414 const time : string = task . stopwatch . toString ( ) ;
411- console . log ( color ( `${ task . name } (${ time } )` ) ) ;
415+ this . _terminal . writeLine ( color ( `${ task . name } (${ time } )` ) ) ;
412416 } else {
413- console . log ( color ( `${ task . name } ` ) ) ;
417+ this . _terminal . writeLine ( color ( `${ task . name } ` ) ) ;
414418 }
415419 break ;
416420 }
@@ -422,13 +426,13 @@ export class TaskRunner {
422426 . map ( text => text . trim ( ) )
423427 . filter ( text => text )
424428 . join ( os . EOL ) ;
425-
426- console . log ( stderr + ( i !== tasks . length - 1 ? os . EOL : '' ) ) ;
429+ this . _terminal . writeLine ( stderr + ( i !== tasks . length - 1 ? os . EOL : '' ) ) ;
427430 }
428431 }
429432 }
430433
431- console . log ( color ( '================================' + os . EOL ) ) ;
434+ this . _terminal . writeLine ( color ( '================================' + os . EOL ) ) ;
432435 }
433436 }
437+
434438}
0 commit comments