Skip to content

Commit 2396616

Browse files
Support old and new git release tag formats (flutter#53715)
1 parent ab14307 commit 2396616

File tree

8 files changed

+146
-65
lines changed

8 files changed

+146
-65
lines changed

packages/flutter_tools/lib/src/commands/upgrade.dart

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ class UpgradeCommandRunner {
131131
);
132132
}
133133
recordState(flutterVersion);
134-
await resetChanges(gitTagVersion);
135134
await upgradeChannel(flutterVersion);
136135
final bool alreadyUpToDate = await attemptFastForward(flutterVersion);
137136
if (alreadyUpToDate) {
@@ -219,34 +218,6 @@ class UpgradeCommandRunner {
219218
}
220219
}
221220

222-
/// Attempts to reset to the last non-hotfix tag.
223-
///
224-
/// If the git history is on a hotfix, doing a fast forward will not pick up
225-
/// major or minor version upgrades. By resetting to the point before the
226-
/// hotfix, doing a git fast forward should succeed.
227-
Future<void> resetChanges(GitTagVersion gitTagVersion) async {
228-
String tag;
229-
if (gitTagVersion == const GitTagVersion.unknown()) {
230-
tag = 'v0.0.0';
231-
} else {
232-
tag = 'v${gitTagVersion.x}.${gitTagVersion.y}.${gitTagVersion.z}';
233-
}
234-
try {
235-
await processUtils.run(
236-
<String>['git', 'reset', '--hard', tag],
237-
throwOnError: true,
238-
workingDirectory: workingDirectory,
239-
);
240-
} on ProcessException catch (error) {
241-
throwToolExit(
242-
'Unable to upgrade Flutter: The tool could not update to the version $tag. '
243-
'This may be due to git not being installed or an internal error. '
244-
'Please ensure that git is installed on your computer and retry again.'
245-
'\nError: $error.'
246-
);
247-
}
248-
}
249-
250221
/// Attempts to upgrade the channel.
251222
///
252223
/// If the user is on a deprecated channel, attempts to migrate them off of

packages/flutter_tools/lib/src/commands/version.dart

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ class VersionCommand extends FlutterCommand {
4545
RunResult runResult;
4646
try {
4747
runResult = await processUtils.run(
48-
<String>['git', 'tag', '-l', 'v*', '--sort=-creatordate'],
48+
<String>['git', 'tag', '-l', '*.*.*', '--sort=-creatordate'],
4949
throwOnError: true,
5050
workingDirectory: Cache.flutterRoot,
5151
);
5252
} on ProcessException catch (error) {
5353
throwToolExit(
5454
'Unable to get the tags. '
55-
'This might be due to git not being installed or an internal error'
55+
'This is likely due to an internal git error.'
5656
'\nError: $error.'
5757
);
5858
}
@@ -88,8 +88,14 @@ class VersionCommand extends FlutterCommand {
8888
}
8989

9090
final String version = argResults.rest[0].replaceFirst('v', '');
91-
if (!tags.contains('v$version')) {
91+
final List<String> matchingTags = tags.where((String tag) => tag.contains(version)).toList();
92+
String matchingTag;
93+
// TODO(fujino): make this a tool exit and fix tests
94+
if (matchingTags.isEmpty) {
9295
globals.printError('There is no version: $version');
96+
matchingTag = version;
97+
} else {
98+
matchingTag = matchingTags.first.trim();
9399
}
94100

95101
// check min supported version
@@ -113,7 +119,7 @@ class VersionCommand extends FlutterCommand {
113119

114120
try {
115121
await processUtils.run(
116-
<String>['git', 'checkout', 'v$version'],
122+
<String>['git', 'checkout', matchingTag],
117123
throwOnError: true,
118124
workingDirectory: Cache.flutterRoot,
119125
);

packages/flutter_tools/lib/src/version.dart

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -692,14 +692,26 @@ String _shortGitRevision(String revision) {
692692
return revision.length > 10 ? revision.substring(0, 10) : revision;
693693
}
694694

695+
/// Version of Flutter SDK parsed from git
695696
class GitTagVersion {
696-
const GitTagVersion(this.x, this.y, this.z, this.hotfix, this.commits, this.hash);
697+
const GitTagVersion({
698+
this.x,
699+
this.y,
700+
this.z,
701+
this.hotfix,
702+
this.devVersion,
703+
this.devPatch,
704+
this.commits,
705+
this.hash,
706+
});
697707
const GitTagVersion.unknown()
698708
: x = null,
699709
y = null,
700710
z = null,
701711
hotfix = null,
702712
commits = 0,
713+
devVersion = null,
714+
devPatch = null,
703715
hash = '';
704716

705717
/// The X in vX.Y.Z.
@@ -720,6 +732,12 @@ class GitTagVersion {
720732
/// The git hash (or an abbreviation thereof) for this commit.
721733
final String hash;
722734

735+
/// The N in X.Y.Z-dev.N.M
736+
final int devVersion;
737+
738+
/// The M in X.Y.Z-dev.N.M
739+
final int devPatch;
740+
723741
static GitTagVersion determine(ProcessUtils processUtils, {String workingDirectory, bool fetchTags = false}) {
724742
if (fetchTags) {
725743
final String channel = _runGit('git rev-parse --abbrev-ref HEAD', processUtils, workingDirectory);
@@ -729,18 +747,73 @@ class GitTagVersion {
729747
_runGit('git fetch $_flutterGit --tags', processUtils, workingDirectory);
730748
}
731749
}
732-
return parse(_runGit('git describe --match v*.*.* --first-parent --long --tags', processUtils, workingDirectory));
750+
// `--match` glob must match old version tag `v1.2.3` and new `1.2.3-dev.4.5`
751+
return parse(_runGit('git describe --match *.*.* --first-parent --long --tags', processUtils, workingDirectory));
733752
}
734753

735-
static GitTagVersion parse(String version) {
736-
final RegExp versionPattern = RegExp(r'^v([0-9]+)\.([0-9]+)\.([0-9]+)(?:\+hotfix\.([0-9]+))?-([0-9]+)-g([a-f0-9]+)$');
754+
// TODO(fujino): Deprecate this https://github.com/flutter/flutter/issues/53850
755+
/// Check for the release tag format pre-v1.17.0
756+
static GitTagVersion parseLegacyVersion(String version) {
757+
final RegExp versionPattern = RegExp(
758+
r'^v([0-9]+)\.([0-9]+)\.([0-9]+)(?:\+hotfix\.([0-9]+))?-([0-9]+)-g([a-f0-9]+)$');
759+
737760
final List<String> parts = versionPattern.matchAsPrefix(version)?.groups(<int>[1, 2, 3, 4, 5, 6]);
738761
if (parts == null) {
739-
globals.printTrace('Could not interpret results of "git describe": $version');
740762
return const GitTagVersion.unknown();
741763
}
742764
final List<int> parsedParts = parts.take(5).map<int>((String source) => source == null ? null : int.tryParse(source)).toList();
743-
return GitTagVersion(parsedParts[0], parsedParts[1], parsedParts[2], parsedParts[3], parsedParts[4], parts[5]);
765+
return GitTagVersion(
766+
x: parsedParts[0],
767+
y: parsedParts[1],
768+
z: parsedParts[2],
769+
hotfix: parsedParts[3],
770+
commits: parsedParts[4],
771+
hash: parts[5],
772+
);
773+
}
774+
775+
/// Check for the release tag format from v1.17.0 on
776+
static GitTagVersion parseVersion(String version) {
777+
final RegExp versionPattern = RegExp(
778+
r'^([0-9]+)\.([0-9]+)\.([0-9]+)(-dev\.[0-9]+\.[0-9]+)?-([0-9]+)-g([a-f0-9]+)$');
779+
final List<String> parts = versionPattern.matchAsPrefix(version)?.groups(<int>[1, 2, 3, 4, 5, 6]);
780+
if (parts == null) {
781+
return const GitTagVersion.unknown();
782+
}
783+
final List<int> parsedParts = parts.take(5).map<int>((String source) => source == null ? null : int.tryParse(source)).toList();
784+
List<int> devParts = <int>[null, null];
785+
if (parts[3] != null) {
786+
devParts = RegExp(r'^-dev\.(\d+)\.(\d+)')
787+
.matchAsPrefix(parts[3])
788+
?.groups(<int>[1, 2])
789+
?.map<int>(
790+
(String source) => source == null ? null : int.tryParse(source)
791+
)?.toList() ?? <int>[null, null];
792+
}
793+
return GitTagVersion(
794+
x: parsedParts[0],
795+
y: parsedParts[1],
796+
z: parsedParts[2],
797+
devVersion: devParts[0],
798+
devPatch: devParts[1],
799+
commits: parsedParts[4],
800+
hash: parts[5],
801+
);
802+
}
803+
804+
static GitTagVersion parse(String version) {
805+
GitTagVersion gitTagVersion;
806+
807+
gitTagVersion = parseLegacyVersion(version);
808+
if (gitTagVersion != const GitTagVersion.unknown()) {
809+
return gitTagVersion;
810+
}
811+
gitTagVersion = parseVersion(version);
812+
if (gitTagVersion != const GitTagVersion.unknown()) {
813+
return gitTagVersion;
814+
}
815+
globals.printTrace('Could not interpret results of "git describe": $version');
816+
return const GitTagVersion.unknown();
744817
}
745818

746819
String frameworkVersionFor(String revision) {

packages/flutter_tools/test/commands.shard/hermetic/version_test.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ void main() {
4242
'version',
4343
'--no-pub',
4444
]);
45-
expect(testLogger.statusText, equals('v10.0.0\r\nv20.0.0\n'));
45+
expect(testLogger.statusText, equals('v10.0.0\r\nv20.0.0\r\n30.0.0-dev.0.0\n'));
4646
}, overrides: <Type, Generator>{
4747
ProcessManager: () => MockProcessManager(),
4848
Stdio: () => mockStdio,
@@ -187,7 +187,7 @@ void main() {
187187
await createTestCommandRunner(command).run(<String>[
188188
'version',
189189
]);
190-
expect(testLogger.statusText, equals('v10.0.0\r\nv20.0.0\n'));
190+
expect(testLogger.statusText, equals('v10.0.0\r\nv20.0.0\r\n30.0.0-dev.0.0\n'));
191191
}, overrides: <Type, Generator>{
192192
ProcessManager: () => MockProcessManager(),
193193
Stdio: () => mockStdio,
@@ -236,7 +236,7 @@ class MockProcessManager extends Mock implements ProcessManager {
236236
if (failGitTag) {
237237
return ProcessResult(0, 1, '', '');
238238
}
239-
return ProcessResult(0, 0, 'v10.0.0\r\nv20.0.0', '');
239+
return ProcessResult(0, 0, 'v10.0.0\r\nv20.0.0\r\n30.0.0-dev.0.0', '');
240240
}
241241
if (command[0] == 'git' && command[1] == 'checkout') {
242242
version = command[2] as String;
@@ -259,7 +259,7 @@ class MockProcessManager extends Mock implements ProcessManager {
259259
return ProcessResult(0, 0, '000000000000000000000', '');
260260
}
261261
if (commandStr ==
262-
'git describe --match v*.*.* --first-parent --long --tags') {
262+
'git describe --match *.*.* --first-parent --long --tags') {
263263
if (version.isNotEmpty) {
264264
return ProcessResult(0, 0, '$version-0-g00000000', '');
265265
}

packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,14 @@ void main() {
2929
MockProcessManager processManager;
3030
FakePlatform fakePlatform;
3131
final MockFlutterVersion flutterVersion = MockFlutterVersion();
32-
const GitTagVersion gitTagVersion = GitTagVersion(1, 2, 3, 4, 5, 'asd');
32+
const GitTagVersion gitTagVersion = GitTagVersion(
33+
x: 1,
34+
y: 2,
35+
z: 3,
36+
hotfix: 4,
37+
commits: 5,
38+
hash: 'asd',
39+
);
3340
when(flutterVersion.channel).thenReturn('dev');
3441

3542
setUp(() {
@@ -231,7 +238,7 @@ void main() {
231238
fakeProcessManager = FakeProcessManager.list(<FakeCommand>[
232239
const FakeCommand(
233240
command: <String>[
234-
'git', 'describe', '--match', 'v*.*.*', '--first-parent', '--long', '--tags',
241+
'git', 'describe', '--match', '*.*.*', '--first-parent', '--long', '--tags',
235242
],
236243
stdout: 'v1.12.16-19-gb45b676af',
237244
),
@@ -336,9 +343,6 @@ class FakeUpgradeCommandRunner extends UpgradeCommandRunner {
336343
@override
337344
Future<bool> hasUncomittedChanges() async => willHaveUncomittedChanges;
338345

339-
@override
340-
Future<void> resetChanges(GitTagVersion gitTagVersion) async {}
341-
342346
@override
343347
Future<void> upgradeChannel(FlutterVersion flutterVersion) async {}
344348

packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ void main() {
179179
workingDirectory: Cache.flutterRoot)).thenReturn(result);
180180
when(processManager.runSync('git fetch https://github.com/flutter/flutter.git --tags'.split(' '),
181181
workingDirectory: Cache.flutterRoot)).thenReturn(result);
182-
when(processManager.runSync('git describe --match v*.*.* --first-parent --long --tags'.split(' '),
182+
when(processManager.runSync('git describe --match *.*.* --first-parent --long --tags'.split(' '),
183183
workingDirectory: Cache.flutterRoot)).thenReturn(result);
184184
when(processManager.runSync(FlutterVersion.gitLog('-n 1 --pretty=format:%ad --date=iso'.split(' ')),
185185
workingDirectory: Cache.flutterRoot)).thenReturn(result);

0 commit comments

Comments
 (0)