Fix `frameworkVersionFor` for flutter doctor and usage (#54217)
diff --git a/packages/flutter_tools/lib/src/version.dart b/packages/flutter_tools/lib/src/version.dart index fa899e1..bbd6cef 100644 --- a/packages/flutter_tools/lib/src/version.dart +++ b/packages/flutter_tools/lib/src/version.dart
@@ -703,6 +703,7 @@ this.devPatch, this.commits, this.hash, + this.gitTag, }); const GitTagVersion.unknown() : x = null, @@ -712,7 +713,8 @@ commits = 0, devVersion = null, devPatch = null, - hash = ''; + hash = '', + gitTag = ''; /// The X in vX.Y.Z. final int x; @@ -738,6 +740,9 @@ /// The M in X.Y.Z-dev.N.M final int devPatch; + /// The git tag that is this version's closest ancestor. + final String gitTag; + static GitTagVersion determine(ProcessUtils processUtils, {String workingDirectory, bool fetchTags = false}) { if (fetchTags) { final String channel = _runGit('git rev-parse --abbrev-ref HEAD', processUtils, workingDirectory); @@ -752,35 +757,16 @@ } // TODO(fujino): Deprecate this https://github.com/flutter/flutter/issues/53850 - /// Check for the release tag format pre-v1.17.0 + /// Check for the release tag format of the form x.y.z-dev.m.n static GitTagVersion parseLegacyVersion(String version) { final RegExp versionPattern = RegExp( - r'^v([0-9]+)\.([0-9]+)\.([0-9]+)(?:\+hotfix\.([0-9]+))?-([0-9]+)-g([a-f0-9]+)$'); - - final List<String> parts = versionPattern.matchAsPrefix(version)?.groups(<int>[1, 2, 3, 4, 5, 6]); - if (parts == null) { - return const GitTagVersion.unknown(); - } - final List<int> parsedParts = parts.take(5).map<int>((String source) => source == null ? null : int.tryParse(source)).toList(); - return GitTagVersion( - x: parsedParts[0], - y: parsedParts[1], - z: parsedParts[2], - hotfix: parsedParts[3], - commits: parsedParts[4], - hash: parts[5], - ); - } - - /// Check for the release tag format from v1.17.0 on - static GitTagVersion parseVersion(String version) { - final RegExp versionPattern = RegExp( r'^([0-9]+)\.([0-9]+)\.([0-9]+)(-dev\.[0-9]+\.[0-9]+)?-([0-9]+)-g([a-f0-9]+)$'); final List<String> parts = versionPattern.matchAsPrefix(version)?.groups(<int>[1, 2, 3, 4, 5, 6]); if (parts == null) { return const GitTagVersion.unknown(); } - final List<int> parsedParts = parts.take(5).map<int>((String source) => source == null ? null : int.tryParse(source)).toList(); + final List<int> parsedParts = parts.take(5).map<int>( + (String source) => source == null ? null : int.tryParse(source)).toList(); List<int> devParts = <int>[null, null]; if (parts[3] != null) { devParts = RegExp(r'^-dev\.(\d+)\.(\d+)') @@ -798,6 +784,38 @@ devPatch: devParts[1], commits: parsedParts[4], hash: parts[5], + gitTag: '${parts[0]}.${parts[1]}.${parts[2]}${parts[3] ?? ''}', // x.y.z-dev.m.n + ); + } + + /// Check for the release tag format of the form x.y.z-m.n.pre + static GitTagVersion parseVersion(String version) { + final RegExp versionPattern = RegExp( + r'^(\d+)\.(\d+)\.(\d+)(-\d+\.\d+\.pre)?-(\d+)-g([a-f0-9]+)$'); + final List<String> parts = versionPattern.matchAsPrefix(version)?.groups(<int>[1, 2, 3, 4, 5, 6]); + if (parts == null) { + return const GitTagVersion.unknown(); + } + final List<int> parsedParts = parts.take(5).map<int>( + (String source) => source == null ? null : int.tryParse(source)).toList(); + List<int> devParts = <int>[null, null]; + if (parts[3] != null) { + devParts = RegExp(r'^-(\d+)\.(\d+)\.pre') + .matchAsPrefix(parts[3]) + ?.groups(<int>[1, 2]) + ?.map<int>( + (String source) => source == null ? null : int.tryParse(source) + )?.toList() ?? <int>[null, null]; + } + return GitTagVersion( + x: parsedParts[0], + y: parsedParts[1], + z: parsedParts[2], + devVersion: devParts[0], + devPatch: devParts[1], + commits: parsedParts[4], + hash: parts[5], + gitTag: '${parts[0]}.${parts[1]}.${parts[2]}${parts[3] ?? ''}', // x.y.z-m.n.pre ); } @@ -821,15 +839,16 @@ return '0.0.0-unknown'; } if (commits == 0) { - if (hotfix != null) { - return '$x.$y.$z+hotfix.$hotfix'; - } - return '$x.$y.$z'; + return gitTag; } if (hotfix != null) { - return '$x.$y.$z+hotfix.${hotfix + 1}-pre.$commits'; + // This is an unexpected state where untagged commits exist past a hotfix + return '$x.$y.$z+hotfix.${hotfix + 1}.pre.$commits'; } - return '$x.$y.${z + 1}-pre.$commits'; + if (devPatch != null && devVersion != null) { + return '$x.$y.$z-${devVersion + 1}.0.pre.$commits'; + } + return '$x.$y.${z + 1}.pre.$commits'; } }
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart index cdbed86..0365e10 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart
@@ -239,7 +239,7 @@ return ProcessResult(0, 0, 'v10.0.0\r\nv20.0.0\r\n30.0.0-dev.0.0', ''); } if (command[0] == 'git' && command[1] == 'checkout') { - version = command[2] as String; + version = (command[2] as String).replaceFirst('v', ''); } return ProcessResult(0, 0, '', ''); }
diff --git a/packages/flutter_tools/test/general.shard/version_test.dart b/packages/flutter_tools/test/general.shard/version_test.dart index 83e8cab..f47e5a2 100644 --- a/packages/flutter_tools/test/general.shard/version_test.dart +++ b/packages/flutter_tools/test/general.shard/version_test.dart
@@ -394,29 +394,44 @@ const String hash = 'abcdef'; GitTagVersion gitTagVersion; - // legacy tag release format - gitTagVersion = GitTagVersion.parse('v1.2.3-4-g$hash'); - expect(gitTagVersion.frameworkVersionFor(hash), '1.2.4-pre.4'); - expect(gitTagVersion.devVersion, null); - expect(gitTagVersion.devPatch, null); - - // new dev tag release format - gitTagVersion = GitTagVersion.parse('1.2.3-dev.4.5-13-g$hash'); - expect(gitTagVersion.frameworkVersionFor(hash), '1.2.4-pre.13'); + // legacy tag format (x.y.z-dev.m.n), master channel + gitTagVersion = GitTagVersion.parse('1.2.3-dev.4.5-4-g$hash'); + expect(gitTagVersion.frameworkVersionFor(hash), '1.2.3-5.0.pre.4'); + expect(gitTagVersion.gitTag, '1.2.3-dev.4.5'); expect(gitTagVersion.devVersion, 4); expect(gitTagVersion.devPatch, 5); - // new stable tag release format + // new tag release format, master channel + gitTagVersion = GitTagVersion.parse('1.2.3-4.5.pre-13-g$hash'); + expect(gitTagVersion.frameworkVersionFor(hash), '1.2.3-5.0.pre.13'); + expect(gitTagVersion.gitTag, '1.2.3-4.5.pre'); + expect(gitTagVersion.devVersion, 4); + expect(gitTagVersion.devPatch, 5); + gitTagVersion = GitTagVersion.parse('1.2.3-13-g$hash'); - expect(gitTagVersion.frameworkVersionFor(hash), '1.2.4-pre.13'); + expect(gitTagVersion.frameworkVersionFor(hash), '1.2.4.pre.13'); + expect(gitTagVersion.gitTag, '1.2.3'); expect(gitTagVersion.devVersion, null); expect(gitTagVersion.devPatch, null); - expect(GitTagVersion.parse('98.76.54-32-g$hash').frameworkVersionFor(hash), '98.76.55-pre.32'); + // new tag release format, dev channel + gitTagVersion = GitTagVersion.parse('1.2.3-4.5.pre-0-g$hash'); + expect(gitTagVersion.frameworkVersionFor(hash), '1.2.3-4.5.pre'); + expect(gitTagVersion.gitTag, '1.2.3-4.5.pre'); + expect(gitTagVersion.devVersion, 4); + expect(gitTagVersion.devPatch, 5); + + // new tag release format, stable channel + gitTagVersion = GitTagVersion.parse('1.2.3-13-g$hash'); + expect(gitTagVersion.frameworkVersionFor(hash), '1.2.4.pre.13'); + expect(gitTagVersion.gitTag, '1.2.3'); + expect(gitTagVersion.devVersion, null); + expect(gitTagVersion.devPatch, null); + + expect(GitTagVersion.parse('98.76.54-32-g$hash').frameworkVersionFor(hash), '98.76.55.pre.32'); expect(GitTagVersion.parse('10.20.30-0-g$hash').frameworkVersionFor(hash), '10.20.30'); - expect(GitTagVersion.parse('v1.2.3+hotfix.1-4-g$hash').frameworkVersionFor(hash), '1.2.3+hotfix.2-pre.4'); expect(testLogger.traceText, ''); - expect(GitTagVersion.parse('1.2.3+hotfix.1-4-g$hash').frameworkVersionFor(hash), '0.0.0-unknown'); + expect(GitTagVersion.parse('v1.2.3+hotfix.1-4-g$hash').frameworkVersionFor(hash), '0.0.0-unknown'); expect(GitTagVersion.parse('x1.2.3-4-g$hash').frameworkVersionFor(hash), '0.0.0-unknown'); expect(GitTagVersion.parse('1.0.0-unknown-0-g$hash').frameworkVersionFor(hash), '0.0.0-unknown'); expect(GitTagVersion.parse('beta-1-g$hash').frameworkVersionFor(hash), '0.0.0-unknown'); @@ -425,7 +440,7 @@ expect(testLogger.errorText, ''); expect( testLogger.traceText, - 'Could not interpret results of "git describe": 1.2.3+hotfix.1-4-gabcdef\n' + 'Could not interpret results of "git describe": v1.2.3+hotfix.1-4-gabcdef\n' 'Could not interpret results of "git describe": x1.2.3-4-gabcdef\n' 'Could not interpret results of "git describe": 1.0.0-unknown-0-gabcdef\n' 'Could not interpret results of "git describe": beta-1-gabcdef\n'