@@ -20,34 +20,16 @@ import 'package:yaml/yaml.dart' as y;
2020// - `-n` for dry-run.
2121void main (List <String > args) {
2222 try {
23- var flagErrors = false ;
24- // General use of verbosity levels:
25- // 0: No extra output.
26- // 1+: Say what is done
27- // 2+: Also say when no change is made.
28- var verbose = 0 ;
29- var dryRun = false ;
30- var nonFlagArgs = < String > [];
31- for (var arg in args) {
32- if (arg.startsWith ('-' )) {
33- for (var i = 1 ; i < arg.length; i++ ) {
34- switch (arg[i]) {
35- case 'n' :
36- dryRun = true ;
37- case 'v' :
38- verbose++ ;
39- case var char:
40- stderr.writeln ('Invalid flag: "$char "' );
41- flagErrors = true ;
42- }
43- }
44- } else {
45- nonFlagArgs.add (arg);
46- }
47- }
48- if (flagErrors) {
49- stderr.writeln (usage);
50- exit (1 );
23+ var (
24+ int verbose,
25+ bool dryRun,
26+ File ? experimentsFile,
27+ Version ? targetVersion,
28+ ) = _parseArguments (args);
29+
30+ var stylePackageDir = _findStylePackageDir ();
31+ if (verbose > 0 ) {
32+ stdout.writeln ('dart_style root: ${stylePackageDir .path }' );
5133 }
5234 if (verbose > 1 ) {
5335 stdout.writeln ('Verbosity: $verbose ' );
@@ -56,44 +38,42 @@ void main(List<String> args) {
5638 if (dryRun || verbose > 1 ) stdout.writeln ('Dry-run: $dryRun ' );
5739 }
5840
59- var stylePackageDir = _findStylePackageDir ();
60- if (verbose > 0 ) {
61- stdout.writeln ('dart_style root: ${stylePackageDir .path }' );
62- }
63- if (findExperimentsFile (nonFlagArgs) case var experimentsFile? ) {
64- // A version number on the command line will be "current version",
65- // otherwise use the maximal version of released experiments in the
66- // experiments file.
67- Version ? version;
68- var experiments = _parseExperiments (experimentsFile);
69- for (var arg in nonFlagArgs) {
70- if (Version .tryParse (arg) case var explicitVersion? ) {
71- version = explicitVersion;
72- if (verbose > 0 ) {
73- stdout.writeln ('SDK version from command line: $version ' );
74- }
75- break ;
76- }
41+ if (experimentsFile == null ) {
42+ experimentsFile = _findExperimentsFile ();
43+ if (experimentsFile == null ) {
44+ stderr
45+ ..writeln ('Cannot find experiments file or SDK directory,' )
46+ ..writeln ('provide path to either on command line.' )
47+ ..writeln (usage);
48+ exit (1 );
49+ return ; // Unreachable, but `exit` has return type `void`.
7750 }
78- if (version == null ) {
79- version = experiments.values.nonNulls.reduce (Version .max);
80- if (verbose > 0 ) {
81- stdout.writeln ('SDK version from experiments: $version ' );
82- }
51+ if (verbose > 0 ) {
52+ stdout.writeln ('Experiments file found: ${experimentsFile .path }' );
8353 }
84-
85- Updater (
86- stylePackageDir,
87- version,
88- experiments,
89- verbose: verbose,
90- dryRun: dryRun,
91- ).run ();
92- } else {
93- stderr.writeln ('Cannot find experiments file.' );
94- stderr.writeln (usage);
54+ } else if (verbose > 0 ) {
55+ stdout.writeln (
56+ 'Experiments file from command line: ${experimentsFile .path }' ,
57+ );
58+ }
59+ var experiments = _parseExperiments (experimentsFile);
60+ var latestReleasedExperiment = experiments.values.fold <Version ?>(
61+ null ,
62+ Version .maxOrNull,
63+ );
64+ if (latestReleasedExperiment == null ) {
65+ stderr.writeln ('No released experiments in experiments file.' );
9566 exit (1 );
67+ return ;
9668 }
69+
70+ Updater (
71+ stylePackageDir,
72+ targetVersion ?? latestReleasedExperiment,
73+ experiments,
74+ verbose: verbose,
75+ dryRun: dryRun,
76+ ).run ();
9777 } catch (e) {
9878 if (e case (: int exitCode)) {
9979 stdout.flush ().then ((_) {
@@ -105,6 +85,64 @@ void main(List<String> args) {
10585 }
10686}
10787
88+ (int verbose, bool dryRun, File ? experimentsFile, Version ? version)
89+ _parseArguments (List <String > args) {
90+ // Parse argument list.
91+ var flagErrors = false ;
92+ // General use of verbosity levels:
93+ // 0: No extra output.
94+ // 1+: Say what is done.
95+ // 2+: Also say when no change is made (what is *not* done).
96+ var verbose = 0 ;
97+ var dryRun = false ;
98+ var printHelp = false ;
99+ File ? experimentsFile;
100+ Version ? targetVersion;
101+ for (var arg in args) {
102+ if (arg.startsWith ('-' )) {
103+ for (var i = 1 ; i < arg.length; i++ ) {
104+ switch (arg[i]) {
105+ case 'n' :
106+ dryRun = true ;
107+ case 'v' :
108+ verbose++ ;
109+ case 'h' :
110+ printHelp = true ;
111+ case var char:
112+ stderr.writeln ('Invalid flag: "$char "' );
113+ flagErrors = true ;
114+ }
115+ }
116+ } else if (Version .tryParse (arg) case var version? ) {
117+ if (targetVersion != null ) {
118+ stderr.writeln (
119+ 'More than one version argument: $targetVersion , $version ' ,
120+ );
121+ flagErrors = true ;
122+ }
123+ targetVersion = version;
124+ } else if (_checkExperimentsFileOrSdk (arg) case var file? ) {
125+ if (experimentsFile != null ) {
126+ stderr.writeln ('More than one experiments or SDK argument: $arg ' );
127+ flagErrors = true ;
128+ }
129+ experimentsFile = file;
130+ } else {
131+ stderr.writeln ('Unrecognized argument: $arg ' );
132+ flagErrors = true ;
133+ }
134+ }
135+ if (flagErrors) {
136+ stderr.writeln (usage);
137+ exit (1 );
138+ }
139+ if (printHelp) {
140+ stdout.writeln (usage);
141+ exit (0 );
142+ }
143+ return (verbose, dryRun, experimentsFile, targetVersion);
144+ }
145+
108146class Updater {
109147 final Directory root;
110148 final Version currentVersion;
@@ -118,6 +156,7 @@ class Updater {
118156 this .verbose = 0 ,
119157 bool dryRun = false ,
120158 }) : files = FileCache (verbose: verbose, dryRun: dryRun);
159+
121160 void run () {
122161 _updatePubspec ();
123162 _updateTests ();
@@ -174,7 +213,7 @@ class Updater {
174213 // Captures:
175214 // - name: The exp-name
176215 static final _experimentRE = RegExp (r' ?\(experiment (?<name>[\w\-]+)\)' );
177-
216+
178217 /// Matches a language version on a format test output line.
179218 static final _languageVersionRE = RegExp (r'(?<=^<<< )\d+\.\d+\b' );
180219
@@ -380,6 +419,7 @@ Directory _findStylePackageDir() {
380419
381420bool _isStylePackageDir (Directory directory) {
382421 var pubspec = File (p.join (directory.path, 'pubspec.yaml' ));
422+ // Could read less, but is unlikely to matter.
383423 return pubspec.existsSync () &&
384424 LineSplitter .split (pubspec.readAsStringSync ()).first ==
385425 'name: dart_style' ;
@@ -388,16 +428,19 @@ bool _isStylePackageDir(Directory directory) {
388428// --------------------------------------------------------------------
389429// Find version and experiments file in SDK.
390430
391- File ? findExperimentsFile (List <String > args) {
392- // Check if argument is SDK directory.
393- if (args.isNotEmpty) {
394- for (var arg in args) {
395- var directory = Directory (p.absolute (arg));
396- if (directory.existsSync ()) {
397- if (_experimentsInSdkDirectory (directory) case var file? ) {
398- return file;
399- }
400- }
431+ /// Used on command line arguments to see if they point to SDK or experiments.
432+ File ? _checkExperimentsFileOrSdk (String path) =>
433+ _tryExperimentsFile (path) ?? _tryExperimentsFileInSdkPath (path);
434+
435+ /// Used to find the experiments file if no command line path is given.
436+ ///
437+ ///
438+ /// Tries to locate an SDK that has a `tools/experimental_features.yaml` file.
439+ File ? _findExperimentsFile () {
440+ var envSdk = Platform .environment['DART_SDK' ];
441+ if (envSdk != null ) {
442+ if (_tryExperimentsFileInSdkPath (envSdk) case var file? ) {
443+ return file;
401444 }
402445 }
403446 // Try relative to `dart` executable.
@@ -408,15 +451,31 @@ File? findExperimentsFile(List<String> args) {
408451 if (parent == cursor) break ;
409452 cursor = parent;
410453 var directory = Directory (cursor);
411- if (_experimentsInSdkDirectory (directory) case var file? ) {
454+ if (_tryExperimentsFileInSdkDirectory (directory) case var file? ) {
412455 return file;
413456 }
414457 }
415458 }
416459 return null ;
417460}
418461
419- File ? _experimentsInSdkDirectory (Directory directory) {
462+ File ? _tryExperimentsFile (String path) {
463+ if (p.basename (path) == 'experimental_features.yaml' ) {
464+ var file = File (path);
465+ if (file.existsSync ()) return file;
466+ }
467+ return null ;
468+ }
469+
470+ File ? _tryExperimentsFileInSdkPath (String path) {
471+ var directory = Directory (p.normalize (path));
472+ if (directory.existsSync ()) {
473+ return _tryExperimentsFileInSdkDirectory (directory);
474+ }
475+ return null ;
476+ }
477+
478+ File ? _tryExperimentsFileInSdkDirectory (Directory directory) {
420479 var experimentsFile = File (
421480 p.join (directory.path, 'tools' , 'experimental_features.yaml' ),
422481 );
@@ -428,9 +487,13 @@ class Version implements Comparable<Version> {
428487 final int major, minor;
429488 Version (this .major, this .minor);
430489
431- static Version max (Version v1, Version v2) => v1.compareTo (v2) >= 0 ? v1 : v2;
490+ static Version ? maxOrNull (Version ? v1, Version ? v2) {
491+ if (v1 == null ) return v2;
492+ if (v2 == null ) return v1;
493+ return max (v1, v2);
494+ }
432495
433- static Version min (Version v1, Version v2) => v1. compareTo (v2) <= 0 ? v1 : v2;
496+ static Version max (Version v1, Version v2) => v1 >= v2 ? v1 : v2;
434497
435498 static Version parse (String version) =>
436499 tryParse (version) ??
@@ -457,36 +520,46 @@ class Version implements Comparable<Version> {
457520
458521 @override
459522 int get hashCode => Object .hash (major, minor);
523+
460524 @override
461525 bool operator == (Object other) =>
462526 other is Version && major == other.major && minor == other.minor;
527+
463528 @override
464529 String toString () => '$major .$minor ' ;
465530
531+ // TODO: (https://dartbug.com/61891) - Remove ignores when issue is fixed.
532+ // ignore: unreachable_from_main
466533 bool operator < (Version other) =>
467534 major < other.major || major == other.major && minor < other.minor;
535+ // ignore: unreachable_from_main
468536 bool operator <= (Version other) =>
469537 major < other.major || major == other.major && minor <= other.minor;
538+ // ignore: unreachable_from_main
470539 bool operator > (Version other) => other < this ;
540+ // ignore: unreachable_from_main
471541 bool operator >= (Version other) => other <= this ;
472542}
473543
474544/// Trailing `'s'` if number is not `1` .
475545String _plural (int number) => number == 1 ? '' : 's' ;
476546
477547final String usage = '''
478- dart tool/update_sdk.dart [-v] [-n] [VERSION] [SDKDIR ]
548+ dart tool/update_sdk.dart [-h] [- v] [-n] [VERSION] [PATH ]
479549
480550Run from inside dart_style directory to be sure to be able to find it.
481551Uses path to `dart` executable to look for SDK directory.
482552
483- VERSION SemVer or ` major.minor` version.
553+ VERSION SemVer or ' major.minor' version.
484554 If provided, use that as SDK version in pubspec.yaml.
485- SDKDIR Path to SDK repository containing experimental_features.yaml file.
555+ If not provided, uses most recent feature release version.
556+ PATH Path to "experimental_features.yaml" or to an SDK repository containing
557+ that file in "tools".
486558 Will be searched for if not provided.
487559
488560-v Verbosity. Can be used multiple times.
489- -n Dryrun. If set, does not write changed files back.
561+ -n Dryrun. If set, does not write changed files back.
562+ -h Show usage.
490563''' ;
491564
492565void exit (int value) {
0 commit comments