Skip to content

Commit 476d998

Browse files
authored
Refactor verifyVersion into typed Version object, use it (flutter#172780)
Towards flutter#171900.
1 parent e97f612 commit 476d998

File tree

4 files changed

+101
-36
lines changed

4 files changed

+101
-36
lines changed

dev/bots/post_process_docs.dart

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'dart:convert';
66
import 'dart:io';
7+
import 'package:file/local.dart';
78
import 'package:intl/intl.dart';
89
import 'package:meta/meta.dart';
910

@@ -12,6 +13,8 @@ import 'package:platform/platform.dart' as platform;
1213

1314
import 'package:process/process.dart';
1415

16+
import 'utils.dart';
17+
1518
class CommandException implements Exception {}
1619

1720
Future<void> main() async {
@@ -46,12 +49,15 @@ Future<void> postProcess() async {
4649

4750
// Generate versions file.
4851
await runProcessWithValidations(<String>['flutter', '--version'], docsPath);
49-
final File versionFile = File(path.join(checkoutPath, 'bin', 'cache', 'flutter.version.json'));
50-
final String version = () {
51-
final Map<String, Object?> json =
52-
jsonDecode(versionFile.readAsStringSync()) as Map<String, Object?>;
53-
return json['flutterVersion']! as String;
54-
}();
52+
final String version;
53+
switch (await Version.resolveIn(const LocalFileSystem().directory(checkoutPath))) {
54+
case VersionError(:final String error):
55+
print('Could not read flutter version: $error');
56+
exit(1);
57+
case VersionOk(version: final String parsedVersion):
58+
version = parsedVersion;
59+
}
60+
5561
// Recreate footer
5662
final String publishPath = path.join(docsPath, '..', 'docs', 'doc', 'flutter', 'footer.js');
5763
final File footerFile = File(publishPath)..createSync(recursive: true);

dev/bots/suite_runners/run_test_harness_tests.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,8 @@ Future<void> testHarnessTestsRunner() async {
128128
}
129129

130130
// Verify that we correctly generated the version file.
131-
final String? versionError = await verifyVersion(File(path.join(flutterRoot, 'version')));
132-
if (versionError != null) {
133-
foundError(<String>[versionError]);
131+
if (await Version.resolveIn() case final VersionError e) {
132+
foundError(<String>[e.error]);
134133
}
135134
}
136135

dev/bots/test/test_test.dart

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'dart:convert';
56
import 'dart:io' hide Platform;
67

78
import 'package:collection/collection.dart';
@@ -50,12 +51,12 @@ void main() {
5051
'1.2.3-5.0.pre.12',
5152
];
5253
for (final String version in valid_versions) {
53-
final File file = fileSystem.file('version');
54-
file.writeAsStringSync(version);
54+
final fs.File file = fileSystem.file('version');
55+
file.writeAsStringSync(jsonEncode(<String, String>{'flutterVersion': version}));
5556

56-
expect(
57-
await verifyVersion(file),
58-
isNull,
57+
await expectLater(
58+
Version.resolveFile(file),
59+
completion(isA<VersionOk>()),
5960
reason: '$version is valid but verifyVersionFile said it was bad',
6061
);
6162
}
@@ -72,12 +73,18 @@ void main() {
7273
'1.2.3-hotfix.1',
7374
];
7475
for (final String version in invalid_versions) {
75-
final File file = fileSystem.file('version');
76-
file.writeAsStringSync(version);
77-
78-
expect(
79-
await verifyVersion(file),
80-
'The version logic generated an invalid version string: "$version".',
76+
final fs.File file = fileSystem.file('version');
77+
file.writeAsStringSync(jsonEncode(<String, String>{'flutterVersion': version}));
78+
79+
await expectLater(
80+
Version.resolveFile(file),
81+
completion(
82+
isA<VersionError>().having(
83+
(VersionError e) => e.error,
84+
'error',
85+
'The version logic generated an invalid version string: "$version".',
86+
),
87+
),
8188
reason: '$version is invalid but verifyVersionFile said it was fine',
8289
);
8390
}

dev/bots/utils.dart

Lines changed: 69 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -735,22 +735,75 @@ Future<void> _runFromList(
735735
}
736736
}
737737

738-
/// Checks the given file's contents to determine if they match the allowed
739-
/// pattern for version strings.
740-
///
741-
/// Returns null if the contents are good. Returns a string if they are bad.
742-
/// The string is an error message.
743-
Future<String?> verifyVersion(File file) async {
744-
final RegExp pattern = RegExp(r'^(\d+)\.(\d+)\.(\d+)((-\d+\.\d+)?\.pre([-\.]\d+)?)?$');
745-
if (!file.existsSync()) {
746-
return 'The version logic failed to create the Flutter version file.';
747-
}
748-
final String version = await file.readAsString();
749-
if (version == '0.0.0-unknown') {
750-
return 'The version logic failed to determine the Flutter version.';
738+
/// Provides access to read and parse the `bin/cache/flutter.version.json`.
739+
sealed class Version {
740+
static final RegExp _pattern = RegExp(r'^(\d+)\.(\d+)\.(\d+)((-\d+\.\d+)?\.pre([-\.]\d+)?)?$');
741+
742+
/// Attempts to read and resolve the version stored in the [checkoutPath].
743+
///
744+
/// If omitted, defaults the current flutter root using the real file system.
745+
static Future<Version> resolveIn([fs.Directory? checkoutPath]) async {
746+
checkoutPath ??= const LocalFileSystem().directory(flutterRoot);
747+
return resolveFile(
748+
checkoutPath.childDirectory('bin').childDirectory('cache').childFile('flutter.version.json'),
749+
);
750+
}
751+
752+
/// Attempts to read and resolve the version stored in [file].
753+
static Future<Version> resolveFile(fs.File file) async {
754+
if (!file.existsSync()) {
755+
return VersionError._(
756+
'The version logic failed to create the Flutter version file: ${file.path}',
757+
contents: null,
758+
);
759+
}
760+
final Object? json = jsonDecode(await file.readAsString());
761+
if (json is! Map<String, Object?>) {
762+
return VersionError._('The version file was in an unexpected format.', contents: '$json');
763+
}
764+
final String? version = json['flutterVersion'] as String?;
765+
if (version == null) {
766+
return VersionError._(
767+
'The version file was missing the key "flutterVersion".',
768+
contents: '$json',
769+
);
770+
}
771+
if (version == '0.0.0-unknown') {
772+
return VersionError._(
773+
'The version logic failed to determine the Flutter version.',
774+
contents: version,
775+
);
776+
}
777+
if (!version.contains(_pattern)) {
778+
return VersionError._(
779+
'The version logic generated an invalid version string: "$version".',
780+
contents: version,
781+
);
782+
}
783+
return VersionOk._(version);
751784
}
752-
if (!version.contains(pattern)) {
753-
return 'The version logic generated an invalid version string: "$version".';
785+
}
786+
787+
/// A failed result of [Version.resolveFile].
788+
final class VersionError implements Version {
789+
const VersionError._(this.error, {required this.contents});
790+
791+
/// Describes the error state.
792+
final String error;
793+
794+
/// The contents of the version file, if any.
795+
final String? contents;
796+
797+
@override
798+
String toString() {
799+
return error;
754800
}
755-
return null;
801+
}
802+
803+
/// A successful result of [Version.resolveFile].
804+
final class VersionOk implements Version {
805+
const VersionOk._(this.version);
806+
807+
/// The contents of the version file, successfully parsed.
808+
final String version;
756809
}

0 commit comments

Comments
 (0)