2
2
// Use of this source code is governed by a BSD-style license that can be
3
3
// found in the LICENSE file.
4
4
5
+ import 'dart:io' as io;
5
6
import 'dart:math' ;
6
7
7
8
import 'package:args/command_runner.dart' ;
@@ -72,11 +73,18 @@ abstract class PluginCommand extends Command<void> {
72
73
);
73
74
argParser.addFlag (_runOnChangedPackagesArg,
74
75
help: 'Run the command on changed packages/plugins.\n '
75
- 'If the $_packagesArg is specified, this flag is ignored.\n '
76
76
'If no packages have changed, or if there have been changes that may\n '
77
77
'affect all packages, the command runs on all packages.\n '
78
78
'The packages excluded with $_excludeArg is also excluded even if changed.\n '
79
- 'See $_kBaseSha if a custom base is needed to determine the diff.' );
79
+ 'See $_kBaseSha if a custom base is needed to determine the diff.\n\n '
80
+ 'Cannot be combined with $_packagesArg .\n ' );
81
+ argParser.addFlag (_packagesForBranchArg,
82
+ help:
83
+ 'This runs on all packages (equivalent to no package selection flag)\n '
84
+ 'on master, and behaves like --run-on-changed-packages on any other branch.\n\n '
85
+ 'Cannot be combined with $_packagesArg .\n\n '
86
+ 'This is intended for use in CI.\n ' ,
87
+ hide: true );
80
88
argParser.addOption (_kBaseSha,
81
89
help: 'The base sha used to determine git diff. \n '
82
90
'This is useful when $_runOnChangedPackagesArg is specified.\n '
@@ -89,6 +97,7 @@ abstract class PluginCommand extends Command<void> {
89
97
static const String _shardCountArg = 'shardCount' ;
90
98
static const String _excludeArg = 'exclude' ;
91
99
static const String _runOnChangedPackagesArg = 'run-on-changed-packages' ;
100
+ static const String _packagesForBranchArg = 'packages-for-branch' ;
92
101
static const String _kBaseSha = 'base-sha' ;
93
102
94
103
/// The directory containing the plugin packages.
@@ -266,15 +275,50 @@ abstract class PluginCommand extends Command<void> {
266
275
/// is a sibling of the packages directory. This is used for a small number
267
276
/// of packages in the flutter/packages repository.
268
277
Stream <PackageEnumerationEntry > _getAllPackages () async * {
278
+ final Set <String > packageSelectionFlags = < String > {
279
+ _packagesArg,
280
+ _runOnChangedPackagesArg,
281
+ _packagesForBranchArg,
282
+ };
283
+ if (packageSelectionFlags
284
+ .where ((String flag) => argResults! .wasParsed (flag))
285
+ .length >
286
+ 1 ) {
287
+ printError ('Only one of --$_packagesArg , --$_runOnChangedPackagesArg , or '
288
+ '--$_packagesForBranchArg can be provided.' );
289
+ throw ToolExit (exitInvalidArguments);
290
+ }
291
+
269
292
Set <String > plugins = Set <String >.from (getStringListArg (_packagesArg));
270
293
294
+ final bool runOnChangedPackages;
295
+ if (getBoolArg (_runOnChangedPackagesArg)) {
296
+ runOnChangedPackages = true ;
297
+ } else if (getBoolArg (_packagesForBranchArg)) {
298
+ final String ? branch = await _getBranch ();
299
+ if (branch == null ) {
300
+ printError ('Unabled to determine branch; --$_packagesForBranchArg can '
301
+ 'only be used in a git repository.' );
302
+ throw ToolExit (exitInvalidArguments);
303
+ } else {
304
+ runOnChangedPackages = branch != 'master' ;
305
+ // Log the mode for auditing what was intended to run.
306
+ print ('--$_packagesForBranchArg : running on '
307
+ '${runOnChangedPackages ? 'changed' : 'all' } packages' );
308
+ }
309
+ } else {
310
+ runOnChangedPackages = false ;
311
+ }
312
+
271
313
final Set <String > excludedPluginNames = getExcludedPackageNames ();
272
314
273
- final bool runOnChangedPackages = getBoolArg (_runOnChangedPackagesArg);
274
- if (plugins.isEmpty &&
275
- runOnChangedPackages &&
276
- ! (await _changesRequireFullTest ())) {
277
- plugins = await _getChangedPackages ();
315
+ if (runOnChangedPackages) {
316
+ final GitVersionFinder gitVersionFinder = await retrieveVersionFinder ();
317
+ final List <String > changedFiles =
318
+ await gitVersionFinder.getChangedFiles ();
319
+ if (! _changesRequireFullTest (changedFiles)) {
320
+ plugins = _getChangedPackages (changedFiles);
321
+ }
278
322
}
279
323
280
324
final Directory thirdPartyPackagesDirectory = packagesDir.parent
@@ -374,15 +418,13 @@ abstract class PluginCommand extends Command<void> {
374
418
return gitVersionFinder;
375
419
}
376
420
377
- // Returns packages that have been changed relative to the git base.
378
- Future <Set <String >> _getChangedPackages () async {
379
- final GitVersionFinder gitVersionFinder = await retrieveVersionFinder ();
380
-
381
- final List <String > allChangedFiles =
382
- await gitVersionFinder.getChangedFiles ();
421
+ // Returns packages that have been changed given a list of changed files.
422
+ //
423
+ // The paths must use POSIX separators (e.g., as provided by git output).
424
+ Set <String > _getChangedPackages (List <String > changedFiles) {
383
425
final Set <String > packages = < String > {};
384
- for (final String path in allChangedFiles ) {
385
- final List <String > pathComponents = path. split ('/' );
426
+ for (final String path in changedFiles ) {
427
+ final List <String > pathComponents = p.posix. split (path );
386
428
final int packagesIndex =
387
429
pathComponents.indexWhere ((String element) => element == 'packages' );
388
430
if (packagesIndex != - 1 ) {
@@ -398,11 +440,19 @@ abstract class PluginCommand extends Command<void> {
398
440
return packages;
399
441
}
400
442
443
+ Future <String ?> _getBranch () async {
444
+ final io.ProcessResult branchResult = await (await gitDir).runCommand (
445
+ < String > ['rev-parse' , '--abbrev-ref' , 'HEAD' ],
446
+ throwOnError: false );
447
+ if (branchResult.exitCode != 0 ) {
448
+ return null ;
449
+ }
450
+ return (branchResult.stdout as String ).trim ();
451
+ }
452
+
401
453
// Returns true if one or more files changed that have the potential to affect
402
454
// any plugin (e.g., CI script changes).
403
- Future <bool > _changesRequireFullTest () async {
404
- final GitVersionFinder gitVersionFinder = await retrieveVersionFinder ();
405
-
455
+ bool _changesRequireFullTest (List <String > changedFiles) {
406
456
const List <String > specialFiles = < String > [
407
457
'.ci.yaml' , // LUCI config.
408
458
'.cirrus.yml' , // Cirrus config.
@@ -417,9 +467,7 @@ abstract class PluginCommand extends Command<void> {
417
467
// check below is done via string prefixing.
418
468
assert (specialDirectories.every ((String dir) => dir.endsWith ('/' )));
419
469
420
- final List <String > allChangedFiles =
421
- await gitVersionFinder.getChangedFiles ();
422
- return allChangedFiles.any ((String path) =>
470
+ return changedFiles.any ((String path) =>
423
471
specialFiles.contains (path) ||
424
472
specialDirectories.any ((String dir) => path.startsWith (dir)));
425
473
}
0 commit comments