diff --git a/packages/flutter_tools/lib/src/version.dart b/packages/flutter_tools/lib/src/version.dart index 4902f732ea1..4f6b56634c5 100644 --- a/packages/flutter_tools/lib/src/version.dart +++ b/packages/flutter_tools/lib/src/version.dart @@ -128,7 +128,7 @@ abstract class FlutterVersion { fetchTags: fetchTags, ); final String frameworkVersion = gitTagVersion.frameworkVersionFor(frameworkRevision); - return _FlutterVersionGit._( + final _FlutterVersionGit result = _FlutterVersionGit._( clock: clock, flutterRoot: flutterRoot, frameworkRevision: frameworkRevision, @@ -136,6 +136,10 @@ abstract class FlutterVersion { gitTagVersion: gitTagVersion, fs: fs, ); + if (fetchTags) { + result.ensureVersionFile(); + } + return result; } /// Ensure the latest git tags are fetched and recalculate [FlutterVersion]. diff --git a/packages/flutter_tools/test/general.shard/version_test.dart b/packages/flutter_tools/test/general.shard/version_test.dart index ecd4221faf2..8f0c339859f 100644 --- a/packages/flutter_tools/test/general.shard/version_test.dart +++ b/packages/flutter_tools/test/general.shard/version_test.dart @@ -6,6 +6,7 @@ import 'dart:convert'; import 'package:file/file.dart'; import 'package:file/memory.dart'; +import 'package:file_testing/file_testing.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/process.dart'; @@ -60,13 +61,19 @@ void main() { const String flutterRoot = '/path/to/flutter'; setUpAll(() { - fs = MemoryFileSystem.test(); Cache.disableLocking(); VersionFreshnessValidator.timeToPauseToLetUserReadTheMessage = Duration.zero; }); + setUp(() { + fs = MemoryFileSystem.test(); + fs.directory(flutterRoot).createSync(recursive: true); + FlutterVersion.getVersionFile(fs, flutterRoot).createSync(recursive: true); + fs.file(fs.path.join(flutterRoot, 'version')).createSync(recursive: true); + }); + testUsingContext( - 'prints nothing when Flutter installation looks fresh', + 'prints nothing when Flutter installation looks fresh $channel', () async { const String flutterUpstreamUrl = 'https://github.com/flutter/flutter.git'; processManager.addCommands([ @@ -227,6 +234,199 @@ void main() { overrides: {ProcessManager: () => processManager, Cache: () => cache}, ); + // Regression test for https://github.com/flutter/flutter/issues/142521 + testUsingContext( + 'does not remove version files when fetching tags', + () async { + const String flutterUpstreamUrl = 'https://github.com/flutter/flutter.git'; + processManager.addCommands([ + const FakeCommand( + command: [ + 'git', + '-c', + 'log.showSignature=false', + 'log', + '-n', + '1', + '--pretty=format:%H', + ], + stdout: '1234abcd', + ), + const FakeCommand(command: ['git', 'symbolic-ref', '--short', 'HEAD']), + const FakeCommand( + command: [ + 'git', + 'fetch', + 'https://github.com/flutter/flutter.git', + '--tags', + '-f', + ], + ), + const FakeCommand(command: ['git', 'tag', '--points-at', '1234abcd']), + const FakeCommand( + command: [ + 'git', + 'describe', + '--match', + '*.*.*', + '--long', + '--tags', + '1234abcd', + ], + stdout: '0.1.2-3-1234abcd', + ), + FakeCommand( + command: const ['git', 'symbolic-ref', '--short', 'HEAD'], + stdout: channel, + ), + FakeCommand( + command: const [ + 'git', + 'rev-parse', + '--abbrev-ref', + '--symbolic', + '@{upstream}', + ], + stdout: 'origin/$channel', + ), + const FakeCommand( + command: ['git', 'ls-remote', '--get-url', 'origin'], + stdout: flutterUpstreamUrl, + ), + FakeCommand( + command: const [ + 'git', + '-c', + 'log.showSignature=false', + 'log', + 'HEAD', + '-n', + '1', + '--pretty=format:%ad', + '--date=iso', + ], + stdout: getChannelUpToDateVersion().toString(), + ), + FakeCommand( + command: const [ + 'git', + '-c', + 'log.showSignature=false', + 'log', + 'abcdefg', + '-n', + '1', + '--pretty=format:%ad', + '--date=iso', + ], + stdout: getChannelUpToDateVersion().toString(), + ), + FakeCommand( + command: const [ + 'git', + '-c', + 'log.showSignature=false', + 'log', + 'HEAD', + '-n', + '1', + '--pretty=format:%ad', + '--date=iso', + ], + stdout: getChannelUpToDateVersion().toString(), + ), + const FakeCommand(command: ['git', 'fetch', '--tags']), + FakeCommand( + command: const [ + 'git', + '-c', + 'log.showSignature=false', + 'log', + '@{upstream}', + '-n', + '1', + '--pretty=format:%ad', + '--date=iso', + ], + stdout: getChannelUpToDateVersion().toString(), + ), + const FakeCommand( + command: [ + 'git', + '-c', + 'log.showSignature=false', + 'log', + '-n', + '1', + '--pretty=format:%ar', + ], + stdout: '1 second ago', + ), + FakeCommand( + command: const [ + 'git', + '-c', + 'log.showSignature=false', + 'log', + 'HEAD', + '-n', + '1', + '--pretty=format:%ad', + '--date=iso', + ], + stdout: getChannelUpToDateVersion().toString(), + ), + const FakeCommand( + command: [ + 'git', + '-c', + 'log.showSignature=false', + 'log', + '-n', + '1', + '--pretty=format:%ar', + 'abcdefg', + ], + stdout: '2 seconds ago', + ), + ]); + + final FlutterVersion flutterVersion = FlutterVersion( + clock: _testClock, + fs: fs, + flutterRoot: flutterRoot, + fetchTags: true, + ); + await flutterVersion.checkFlutterVersionFreshness(); + + // Verify the version files exist and have been repopulated after the fetch. + expect(FlutterVersion.getVersionFile(fs, flutterRoot), exists); // flutter.version.json + expect(fs.file(fs.path.join(flutterRoot, 'version')), exists); // legacy + + expect(flutterVersion.channel, channel); + expect(flutterVersion.repositoryUrl, flutterUpstreamUrl); + expect(flutterVersion.frameworkRevision, '1234abcd'); + expect(flutterVersion.frameworkRevisionShort, '1234abcd'); + expect(flutterVersion.frameworkVersion, '0.0.0-unknown'); + expect( + flutterVersion.toString(), + 'Flutter • channel $channel • $flutterUpstreamUrl\n' + 'Framework • revision 1234abcd (1 second ago) • ${getChannelUpToDateVersion()}\n' + 'Engine • revision abcdefg (2 seconds ago) • ${getChannelUpToDateVersion()}\n' + 'Tools • Dart 2.12.0 • DevTools 2.8.0', + ); + expect(flutterVersion.frameworkAge, '1 second ago'); + expect(flutterVersion.getVersionString(), '$channel/1234abcd'); + expect(flutterVersion.getBranchName(), channel); + expect(flutterVersion.getVersionString(redactUnknownBranches: true), '$channel/1234abcd'); + expect(flutterVersion.getBranchName(redactUnknownBranches: true), channel); + + expect(testLogger.statusText, isEmpty); + expect(processManager, hasNoRemainingExpectations); + }, + overrides: {ProcessManager: () => processManager, Cache: () => cache}, + ); + testUsingContext( 'does not crash when git log outputs malformed output', () async {