Skip to content

Commit 2f4e1c6

Browse files
committed
Rewritten a little.
1 parent eea3178 commit 2f4e1c6

File tree

1 file changed

+154
-81
lines changed

1 file changed

+154
-81
lines changed

tool/update_sdk.dart

Lines changed: 154 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -20,34 +20,16 @@ import 'package:yaml/yaml.dart' as y;
2020
// - `-n` for dry-run.
2121
void 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+
108146
class 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

381420
bool _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`.
475545
String _plural(int number) => number == 1 ? '' : 's';
476546

477547
final String usage = '''
478-
dart tool/update_sdk.dart [-v] [-n] [VERSION] [SDKDIR]
548+
dart tool/update_sdk.dart [-h] [-v] [-n] [VERSION] [PATH]
479549
480550
Run from inside dart_style directory to be sure to be able to find it.
481551
Uses 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

492565
void exit(int value) {

0 commit comments

Comments
 (0)