@@ -139,18 +139,44 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
139
139
}
140
140
}
141
141
142
+ /**
143
+ * @return Whether or not the migration was performed successfully.
144
+ */
145
+ private async executeMigration (
146
+ packageName : string ,
147
+ collectionPath : string ,
148
+ migrationName : string ,
149
+ commit ?: boolean ,
150
+ ) : Promise < boolean > {
151
+ const collection = this . workflow . engine . createCollection ( collectionPath ) ;
152
+ const name = collection . listSchematicNames ( ) . find ( name => name === migrationName ) ;
153
+ if ( ! name ) {
154
+ this . logger . error ( `Cannot find migration '${ migrationName } ' in '${ packageName } '.` ) ;
155
+
156
+ return false ;
157
+ }
158
+
159
+ const schematic = this . workflow . engine . createSchematic ( name , collection ) ;
160
+
161
+ this . logger . info (
162
+ colors . cyan ( `** Executing '${ migrationName } ' of package '${ packageName } ' **\n` ) ,
163
+ ) ;
164
+
165
+ return this . executePackageMigrations ( [ schematic . description ] , packageName , commit ) ;
166
+ }
167
+
142
168
/**
143
169
* @return Whether or not the migrations were performed successfully.
144
170
*/
145
171
private async executeMigrations (
146
172
packageName : string ,
147
173
collectionPath : string ,
148
174
range : semver . Range ,
149
- commit = false ,
175
+ commit ?: boolean ,
150
176
) : Promise < boolean > {
151
177
const collection = this . workflow . engine . createCollection ( collectionPath ) ;
152
-
153
178
const migrations = [ ] ;
179
+
154
180
for ( const name of collection . listSchematicNames ( ) ) {
155
181
const schematic = this . workflow . engine . createSchematic ( name , collection ) ;
156
182
const description = schematic . description as typeof schematic . description & {
@@ -166,16 +192,21 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
166
192
}
167
193
}
168
194
195
+ migrations . sort ( ( a , b ) => semver . compare ( a . version , b . version ) || a . name . localeCompare ( b . name ) ) ;
196
+
169
197
if ( migrations . length === 0 ) {
170
198
return true ;
171
199
}
172
200
173
- migrations . sort ( ( a , b ) => semver . compare ( a . version , b . version ) || a . name . localeCompare ( b . name ) ) ;
174
-
175
201
this . logger . info (
176
202
colors . cyan ( `** Executing migrations of package '${ packageName } ' **\n` ) ,
177
203
) ;
178
204
205
+ return this . executePackageMigrations ( migrations , packageName , commit ) ;
206
+ }
207
+
208
+ // tslint:disable-next-line: no-any
209
+ private async executePackageMigrations ( migrations : any [ ] , packageName : string , commit = false ) : Promise < boolean > {
179
210
for ( const migration of migrations ) {
180
211
this . logger . info ( `${ colors . symbols . pointer } ${ migration . description . replace ( / \. / g, '.\n ' ) } ` ) ;
181
212
@@ -242,6 +273,10 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
242
273
return 1 ;
243
274
}
244
275
276
+ if ( options . migrateOnly && packageIdentifier . rawSpec ) {
277
+ this . logger . warn ( 'Package specifier has no effect when using "migrate-only" option.' ) ;
278
+ }
279
+
245
280
// If next option is used and no specifier supplied, use next tag
246
281
if ( options . next && ! packageIdentifier . rawSpec ) {
247
282
packageIdentifier . fetchSpec = 'next' ;
@@ -334,8 +369,8 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
334
369
}
335
370
336
371
if ( options . migrateOnly ) {
337
- if ( ! options . from ) {
338
- this . logger . error ( '"from" option is required when using the "migrate-only" option.' ) ;
372
+ if ( ! options . from && typeof options . migrateOnly !== 'string' ) {
373
+ this . logger . error ( '"from" option is required when using the "migrate-only" option without a migration name .' ) ;
339
374
340
375
return 1 ;
341
376
} else if ( packages . length !== 1 ) {
@@ -346,13 +381,6 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
346
381
return 1 ;
347
382
}
348
383
349
- const from = coerceVersionNumber ( options . from ) ;
350
- if ( ! from ) {
351
- this . logger . error ( `"from" value [${ options . from } ] is not a valid version.` ) ;
352
-
353
- return 1 ;
354
- }
355
-
356
384
if ( options . next ) {
357
385
this . logger . warn ( '"next" option has no effect when using "migrate-only" option.' ) ;
358
386
}
@@ -430,16 +458,33 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
430
458
}
431
459
}
432
460
433
- const migrationRange = new semver . Range (
434
- '>' + from + ' <=' + ( options . to || packageNode . package . version ) ,
435
- ) ;
461
+ let success = false ;
462
+ if ( typeof options . migrateOnly == 'string' ) {
463
+ success = await this . executeMigration (
464
+ packageName ,
465
+ migrations ,
466
+ options . migrateOnly ,
467
+ options . createCommits ,
468
+ ) ;
469
+ } else {
470
+ const from = coerceVersionNumber ( options . from ) ;
471
+ if ( ! from ) {
472
+ this . logger . error ( `"from" value [${ options . from } ] is not a valid version.` ) ;
436
473
437
- const success = await this . executeMigrations (
438
- packageName ,
439
- migrations ,
440
- migrationRange ,
441
- options . createCommits ,
442
- ) ;
474
+ return 1 ;
475
+ }
476
+
477
+ const migrationRange = new semver . Range (
478
+ '>' + from + ' <=' + ( options . to || packageNode . package . version ) ,
479
+ ) ;
480
+
481
+ success = await this . executeMigrations (
482
+ packageName ,
483
+ migrations ,
484
+ migrationRange ,
485
+ options . createCommits ,
486
+ ) ;
487
+ }
443
488
444
489
if ( success ) {
445
490
if (
0 commit comments