mirror of
https://github.com/flutter/flutter
synced 2024-10-13 19:52:53 +00:00
Reland fix --version
(#52141)
This commit is contained in:
parent
db1f33fd70
commit
e13e17009d
|
@ -6,6 +6,7 @@ import 'dart:async';
|
|||
|
||||
import '../base/common.dart';
|
||||
import '../doctor.dart';
|
||||
import '../globals.dart' as globals;
|
||||
import '../runner/flutter_command.dart';
|
||||
|
||||
class DoctorCommand extends FlutterCommand {
|
||||
|
@ -42,6 +43,7 @@ class DoctorCommand extends FlutterCommand {
|
|||
|
||||
@override
|
||||
Future<FlutterCommandResult> runCommand() async {
|
||||
globals.flutterVersion.fetchTagsAndUpdate();
|
||||
if (argResults.wasParsed('check-for-remote-artifacts')) {
|
||||
final String engineRevision = stringArg('check-for-remote-artifacts');
|
||||
if (engineRevision.startsWith(RegExp(r'[a-f0-9]{1,40}'))) {
|
||||
|
|
|
@ -322,6 +322,7 @@ class FlutterCommandRunner extends CommandRunner<void> {
|
|||
|
||||
if (topLevelResults['version'] as bool) {
|
||||
globals.flutterUsage.sendCommand('version');
|
||||
globals.flutterVersion.fetchTagsAndUpdate();
|
||||
String status;
|
||||
if (machineFlag) {
|
||||
status = const JsonEncoder.withIndent(' ').convert(globals.flutterVersion.toJson());
|
||||
|
|
|
@ -23,6 +23,9 @@ enum Channel {
|
|||
stable,
|
||||
}
|
||||
|
||||
/// The flutter GitHub repository.
|
||||
const String _flutterGit = 'https://github.com/flutter/flutter.git';
|
||||
|
||||
/// Retrieve a human-readable name for a given [channel].
|
||||
///
|
||||
/// Requires [FlutterVersion.officialChannels] to be correctly ordered.
|
||||
|
@ -42,13 +45,29 @@ Channel getChannelForName(String name) {
|
|||
}
|
||||
|
||||
class FlutterVersion {
|
||||
/// Parses the Flutter version from currently available tags in the local
|
||||
/// repo.
|
||||
///
|
||||
/// Call [fetchTagsAndUpdate] to update the version based on the latest tags
|
||||
/// available upstream.
|
||||
FlutterVersion([this._clock = const SystemClock(), this._workingDirectory]) {
|
||||
_frameworkRevision = _runGit(
|
||||
gitLog(<String>['-n', '1', '--pretty=format:%H']).join(' '),
|
||||
processUtils,
|
||||
_workingDirectory,
|
||||
);
|
||||
_gitTagVersion = GitTagVersion.determine(processUtils, _workingDirectory);
|
||||
_gitTagVersion = GitTagVersion.determine(processUtils, workingDirectory: _workingDirectory, fetchTags: false);
|
||||
_frameworkVersion = gitTagVersion.frameworkVersionFor(_frameworkRevision);
|
||||
}
|
||||
|
||||
/// Fetchs tags from the upstream Flutter repository and re-calculates the
|
||||
/// version.
|
||||
///
|
||||
/// This carries a performance penalty, and should only be called when the
|
||||
/// user explicitly wants to get the version, e.g. for `flutter --version` or
|
||||
/// `flutter doctor`.
|
||||
void fetchTagsAndUpdate() {
|
||||
_gitTagVersion = GitTagVersion.determine(processUtils, workingDirectory: _workingDirectory, fetchTags: true);
|
||||
_frameworkVersion = gitTagVersion.frameworkVersionFor(_frameworkRevision);
|
||||
}
|
||||
|
||||
|
@ -233,7 +252,7 @@ class FlutterVersion {
|
|||
'remote',
|
||||
'add',
|
||||
_versionCheckRemote,
|
||||
'https://github.com/flutter/flutter.git',
|
||||
_flutterGit,
|
||||
]);
|
||||
await _run(<String>['git', 'fetch', _versionCheckRemote, branch]);
|
||||
return _latestGitCommitDate(
|
||||
|
@ -701,7 +720,10 @@ class GitTagVersion {
|
|||
/// The git hash (or an abbreviation thereof) for this commit.
|
||||
final String hash;
|
||||
|
||||
static GitTagVersion determine(ProcessUtils processUtils, [String workingDirectory]) {
|
||||
static GitTagVersion determine(ProcessUtils processUtils, {String workingDirectory, bool fetchTags = false}) {
|
||||
if (fetchTags) {
|
||||
_runGit('git fetch $_flutterGit --tags', processUtils, workingDirectory);
|
||||
}
|
||||
return parse(_runGit('git describe --match v*.*.* --first-parent --long --tags', processUtils, workingDirectory));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,12 +4,17 @@
|
|||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/artifacts.dart';
|
||||
import 'package:flutter_tools/src/base/common.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/io.dart';
|
||||
|
||||
import 'package:flutter_tools/src/base/terminal.dart';
|
||||
import 'package:flutter_tools/src/base/user_messages.dart';
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
import 'package:flutter_tools/src/commands/doctor.dart';
|
||||
import 'package:flutter_tools/src/doctor.dart';
|
||||
import 'package:flutter_tools/src/features.dart';
|
||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
|
@ -722,6 +727,50 @@ void main() {
|
|||
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
|
||||
ProcessManager: () => MockProcessManager(),
|
||||
});
|
||||
|
||||
testUsingContext('Fetches tags to get the right version', () async {
|
||||
Cache.disableLocking();
|
||||
|
||||
final DoctorCommand doctorCommand = DoctorCommand();
|
||||
final CommandRunner<void> commandRunner = createTestCommandRunner(doctorCommand);
|
||||
|
||||
await commandRunner.run(<String>['doctor']);
|
||||
|
||||
verify(mockFlutterVersion.fetchTagsAndUpdate()).called(1);
|
||||
|
||||
Cache.enableLocking();
|
||||
}, overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
FileSystem: () => MemoryFileSystem.test(),
|
||||
FlutterVersion: () => mockFlutterVersion,
|
||||
Doctor: () => NoOpDoctor(),
|
||||
}, initializeFlutterRoot: false);
|
||||
}
|
||||
|
||||
class NoOpDoctor implements Doctor {
|
||||
@override
|
||||
bool get canLaunchAnything => true;
|
||||
|
||||
@override
|
||||
bool get canListAnything => true;
|
||||
|
||||
@override
|
||||
Future<bool> checkRemoteArtifacts(String engineRevision) async => true;
|
||||
|
||||
@override
|
||||
Future<bool> diagnose({ bool androidLicenses = false, bool verbose = true, bool showColor = true }) async => true;
|
||||
|
||||
@override
|
||||
List<ValidatorTask> startValidatorTasks() => <ValidatorTask>[];
|
||||
|
||||
@override
|
||||
Future<void> summary() => null;
|
||||
|
||||
@override
|
||||
List<DoctorValidator> get validators => <DoctorValidator>[];
|
||||
|
||||
@override
|
||||
List<Workflow> get workflows => <Workflow>[];
|
||||
}
|
||||
|
||||
class MockUsage extends Mock implements Usage {}
|
||||
|
@ -1062,4 +1111,3 @@ class VsCodeValidatorTestTargets extends VsCodeValidator {
|
|||
}
|
||||
|
||||
class MockProcessManager extends Mock implements ProcessManager {}
|
||||
class MockFlutterVersion extends Mock implements FlutterVersion {}
|
||||
|
|
|
@ -88,6 +88,18 @@ void main() {
|
|||
Platform: () => platform,
|
||||
}, initializeFlutterRoot: false);
|
||||
|
||||
testUsingContext('Fetches tags when --version is used', () async {
|
||||
final MockFlutterVersion version = globals.flutterVersion as MockFlutterVersion;
|
||||
|
||||
await runner.run(<String>['--version']);
|
||||
|
||||
verify(version.fetchTagsAndUpdate()).called(1);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
Platform: () => platform,
|
||||
}, initializeFlutterRoot: false);
|
||||
|
||||
testUsingContext('throw tool exit if the version file cannot be written', () async {
|
||||
final MockFlutterVersion version = globals.flutterVersion as MockFlutterVersion;
|
||||
when(version.ensureVersionFile()).thenThrow(const FileSystemException());
|
||||
|
@ -165,6 +177,8 @@ void main() {
|
|||
workingDirectory: Cache.flutterRoot)).thenReturn(result);
|
||||
when(processManager.runSync(FlutterVersion.gitLog('-n 1 --pretty=format:%ar'.split(' ')),
|
||||
workingDirectory: Cache.flutterRoot)).thenReturn(result);
|
||||
when(processManager.runSync('git fetch https://github.com/flutter/flutter.git --tags'.split(' '),
|
||||
workingDirectory: Cache.flutterRoot)).thenReturn(result);
|
||||
when(processManager.runSync('git describe --match v*.*.* --first-parent --long --tags'.split(' '),
|
||||
workingDirectory: Cache.flutterRoot)).thenReturn(result);
|
||||
when(processManager.runSync(FlutterVersion.gitLog('-n 1 --pretty=format:%ad --date=iso'.split(' ')),
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'dart:convert';
|
|||
import 'package:collection/collection.dart' show ListEquality;
|
||||
import 'package:flutter_tools/src/base/context.dart';
|
||||
import 'package:flutter_tools/src/base/io.dart';
|
||||
import 'package:flutter_tools/src/base/process.dart';
|
||||
import 'package:flutter_tools/src/base/time.dart';
|
||||
import 'package:flutter_tools/src/base/utils.dart';
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
|
@ -411,6 +412,60 @@ void main() {
|
|||
'Could not interpret results of "git describe": v1.2.3-4-gxabcdef\n',
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('determine does not call fetch --tags', () {
|
||||
final MockProcessUtils processUtils = MockProcessUtils();
|
||||
when(processUtils.runSync(
|
||||
<String>['git', 'fetch', 'https://github.com/flutter/flutter.git', '--tags'],
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
environment: anyNamed('environment'),
|
||||
)).thenReturn(RunResult(ProcessResult(105, 0, '', ''), <String>['git', 'fetch']));
|
||||
when(processUtils.runSync(
|
||||
<String>['git', 'describe', '--match', 'v*.*.*', '--first-parent', '--long', '--tags'],
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
environment: anyNamed('environment'),
|
||||
)).thenReturn(RunResult(ProcessResult(106, 0, 'v0.1.2-3-1234abcd', ''), <String>['git', 'describe']));
|
||||
|
||||
GitTagVersion.determine(processUtils, workingDirectory: '.');
|
||||
|
||||
verifyNever(processUtils.runSync(
|
||||
<String>['git', 'fetch', 'https://github.com/flutter/flutter.git', '--tags'],
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
environment: anyNamed('environment'),
|
||||
));
|
||||
verify(processUtils.runSync(
|
||||
<String>['git', 'describe', '--match', 'v*.*.*', '--first-parent', '--long', '--tags'],
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
environment: anyNamed('environment'),
|
||||
)).called(1);
|
||||
});
|
||||
|
||||
testUsingContext('determine calls fetch --tags', () {
|
||||
final MockProcessUtils processUtils = MockProcessUtils();
|
||||
when(processUtils.runSync(
|
||||
<String>['git', 'fetch', 'https://github.com/flutter/flutter.git', '--tags'],
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
environment: anyNamed('environment'),
|
||||
)).thenReturn(RunResult(ProcessResult(105, 0, '', ''), <String>['git', 'fetch']));
|
||||
when(processUtils.runSync(
|
||||
<String>['git', 'describe', '--match', 'v*.*.*', '--first-parent', '--long', '--tags'],
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
environment: anyNamed('environment'),
|
||||
)).thenReturn(RunResult(ProcessResult(106, 0, 'v0.1.2-3-1234abcd', ''), <String>['git', 'describe']));
|
||||
|
||||
GitTagVersion.determine(processUtils, workingDirectory: '.', fetchTags: true);
|
||||
|
||||
verify(processUtils.runSync(
|
||||
<String>['git', 'fetch', 'https://github.com/flutter/flutter.git', '--tags'],
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
environment: anyNamed('environment'),
|
||||
)).called(1);
|
||||
verify(processUtils.runSync(
|
||||
<String>['git', 'describe', '--match', 'v*.*.*', '--first-parent', '--long', '--tags'],
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
environment: anyNamed('environment'),
|
||||
)).called(1);
|
||||
});
|
||||
}
|
||||
|
||||
void _expectVersionMessage(String message) {
|
||||
|
@ -489,6 +544,8 @@ void fakeData(
|
|||
// Careful here! argsAre accepts 9 arguments and FlutterVersion.gitLog adds 4.
|
||||
} else if (remoteCommitDate != null && listArgsAre(FlutterVersion.gitLog(<String>['__flutter_version_check__/$channel', '-n', '1', '--pretty=format:%ad', '--date=iso']))) {
|
||||
return success(remoteCommitDate.toString());
|
||||
} else if (argsAre('git', 'fetch', 'https://github.com/flutter/flutter.git', '--tags')) {
|
||||
return success('');
|
||||
}
|
||||
|
||||
throw StateError('Unexpected call to ProcessManager.run(${invocation.positionalArguments}, ${invocation.namedArguments})');
|
||||
|
@ -519,13 +576,18 @@ void fakeData(
|
|||
workingDirectory: anyNamed('workingDirectory'),
|
||||
environment: anyNamed('environment'),
|
||||
)).thenReturn(ProcessResult(104, 0, '1 second ago', ''));
|
||||
when(pm.runSync(
|
||||
<String>['git', 'fetch', 'https://github.com/flutter/flutter', '--tags'],
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
environment: anyNamed('environment'),
|
||||
)).thenReturn(ProcessResult(105, 0, '', ''));
|
||||
when(pm.runSync(
|
||||
<String>['git', 'describe', '--match', 'v*.*.*', '--first-parent', '--long', '--tags'],
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
environment: anyNamed('environment'),
|
||||
)).thenReturn(ProcessResult(105, 0, 'v0.1.2-3-1234abcd', ''));
|
||||
)).thenReturn(ProcessResult(106, 0, 'v0.1.2-3-1234abcd', ''));
|
||||
}
|
||||
|
||||
class MockProcessManager extends Mock implements ProcessManager {}
|
||||
|
||||
class MockProcessUtils extends Mock implements ProcessUtils {}
|
||||
class MockCache extends Mock implements Cache {}
|
||||
|
|
|
@ -647,6 +647,9 @@ class FakeHttpHeaders extends HttpHeaders {
|
|||
}
|
||||
|
||||
class FakeFlutterVersion implements FlutterVersion {
|
||||
@override
|
||||
void fetchTagsAndUpdate() { }
|
||||
|
||||
@override
|
||||
String get channel => 'master';
|
||||
|
||||
|
|
Loading…
Reference in a new issue