diff --git a/dev/conductor/core/lib/src/globals.dart b/dev/conductor/core/lib/src/globals.dart index 91f76a6a4a..4072c488f1 100644 --- a/dev/conductor/core/lib/src/globals.dart +++ b/dev/conductor/core/lib/src/globals.dart @@ -54,7 +54,8 @@ Directory get localFlutterRoot { final String checkoutsDirname = fileSystem.path.normalize( fileSystem.path.join( fileSystem.path.dirname(filePath), - '..', // flutter/dev/tools + '..', // flutter/dev/conductor/core + '..', // flutter/dev/conductor '..', // flutter/dev '..', // flutter ), diff --git a/dev/conductor/core/lib/src/start.dart b/dev/conductor/core/lib/src/start.dart index 5a61183494..d48a8c7f92 100644 --- a/dev/conductor/core/lib/src/start.dart +++ b/dev/conductor/core/lib/src/start.dart @@ -382,7 +382,8 @@ class StartContext { // Get framework version final Version lastVersion = Version.fromString(await framework.getFullTag( framework.upstreamRemote.name, candidateBranch, - exact: false)); + exact: false, + ))..ensureValid(candidateBranch, incrementLetter); Version nextVersion; if (incrementLetter == 'm') { nextVersion = Version.fromCandidateBranch(candidateBranch); diff --git a/dev/conductor/core/lib/src/version.dart b/dev/conductor/core/lib/src/version.dart index 20e090ec9e..0389a3f34f 100644 --- a/dev/conductor/core/lib/src/version.dart +++ b/dev/conductor/core/lib/src/version.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import './globals.dart' show ConductorException; +import './globals.dart' show releaseCandidateBranchRegex, ConductorException; /// Possible string formats that `flutter --version` can return. enum VersionType { @@ -251,6 +251,51 @@ class Version { final VersionType type; + /// Validate that the parsed version is valid. + /// + /// Will throw a [ConductorException] if the version is not possible given the + /// [candidateBranch] and [incrementLetter]. + void ensureValid(String candidateBranch, String incrementLetter) { + if (!const {'y', 'z', 'm', 'n'}.contains(incrementLetter)) { + throw ConductorException('Invalid incrementLetter: $incrementLetter'); + } + final RegExpMatch? branchMatch = releaseCandidateBranchRegex.firstMatch(candidateBranch); + if (branchMatch == null) { + throw ConductorException( + 'Candidate branch $candidateBranch does not match the pattern ' + '${releaseCandidateBranchRegex.pattern}', + ); + } + + // These groups are required in the pattern, so these match groups should + // not be null + final String branchX = branchMatch.group(1)!; + if (x != int.tryParse(branchX)) { + throw ConductorException( + 'Parsed version ${toString()} has a different x value than candidate ' + 'branch $candidateBranch', + ); + } + final String branchY = branchMatch.group(2)!; + if (y != int.tryParse(branchY)) { + throw ConductorException( + 'Parsed version ${toString()} has a different y value than candidate ' + 'branch $candidateBranch', + ); + } + + // stable type versions don't have an m field set + if (type != VersionType.stable && incrementLetter != 'm') { + final String branchM = branchMatch.group(3)!; + if (m != int.tryParse(branchM)) { + throw ConductorException( + 'Parsed version ${toString()} has a different m value than candidate ' + 'branch $candidateBranch', + ); + } + } + } + @override String toString() { switch (type) { diff --git a/dev/conductor/core/test/start_test.dart b/dev/conductor/core/test/start_test.dart index a73982567e..3b0ba6906c 100644 --- a/dev/conductor/core/test/start_test.dart +++ b/dev/conductor/core/test/start_test.dart @@ -310,7 +310,7 @@ void main() { const String revision3 = '123abc'; const String previousDartRevision = '171876a4e6cf56ee6da1f97d203926bd7afda7ef'; const String nextDartRevision = 'f6c91128be6b77aef8351e1e3a9d07c85bc2e46e'; - const String previousVersion = '1.2.0-1.0.pre'; + const String previousVersion = '1.2.0-3.0.pre'; const String nextVersion = '1.2.0'; const String incrementLevel = 'z'; diff --git a/dev/conductor/core/test/version_test.dart b/dev/conductor/core/test/version_test.dart index 3a4c08bd57..7bfa529221 100644 --- a/dev/conductor/core/test/version_test.dart +++ b/dev/conductor/core/test/version_test.dart @@ -81,4 +81,77 @@ void main() { }, onPlatform: { 'windows': const Skip('Flutter Conductor only supported on macos/linux'), }); + + group('.ensureValid()', () { + test('throws when x does not match', () { + const String versionString = '1.2.3-4.5.pre'; + const String candidateBranch = 'flutter-3.2-candidate.4'; + final Version version = Version.fromString(versionString); + expect( + () => version.ensureValid(candidateBranch, 'n'), + throwsExceptionWith( + 'Parsed version $versionString has a different x value than ' + 'candidate branch $candidateBranch', + ), + ); + }); + + test('throws when y does not match', () { + const String versionString = '1.2.3'; + const String candidateBranch = 'flutter-1.15-candidate.4'; + final Version version = Version.fromString(versionString); + expect( + () => version.ensureValid(candidateBranch, 'm'), + throwsExceptionWith( + 'Parsed version $versionString has a different y value than ' + 'candidate branch $candidateBranch', + ), + ); + }); + + test('throws when m does not match', () { + const String versionString = '1.2.3-4.5.pre'; + const String candidateBranch = 'flutter-1.2-candidate.0'; + final Version version = Version.fromString(versionString); + expect( + () => version.ensureValid(candidateBranch, 'n'), + throwsExceptionWith( + 'Parsed version $versionString has a different m value than ' + 'candidate branch $candidateBranch', + ), + ); + }); + + test('does not validate m if version type is stable', () { + const String versionString = '1.2.0'; + const String candidateBranch = 'flutter-1.2-candidate.98'; + final Version version = Version.fromString(versionString); + expect( + () => version.ensureValid(candidateBranch, 'n'), + isNot(throwsException), + ); + }); + + test('throws on malformed candidate branch', () { + const String versionString = '1.2.0'; + const String candidateBranch = 'stable'; + final Version version = Version.fromString(versionString); + expect( + () => version.ensureValid(candidateBranch, 'z'), + throwsExceptionWith( + 'Candidate branch $candidateBranch does not match the pattern', + ), + ); + }); + + test('does not validate m if incrementLetter is m', () { + const String versionString = '1.2.0-0.0.pre'; + const String candidateBranch = 'flutter-1.2-candidate.42'; + final Version version = Version.fromString(versionString); + expect( + () => version.ensureValid(candidateBranch, 'm'), + isNot(throwsException), + ); + }); + }); }