Unverified Commit 77487319 authored by Kenzie (Schmoll) Davisson's avatar Kenzie (Schmoll) Davisson Committed by GitHub

Add DevTools version to `flutter --version` and `flutter doctor -v` output. (#93065)

* Add DevTools version to `flutter --version` output.

* review comments

* fix test

* add explanatory comment

* dummy commit to kick bots
Co-authored-by: 's avatarChristopher Fujino <christopherfujino@gmail.com>
parent b8536777
...@@ -24,6 +24,7 @@ class UserMessages { ...@@ -24,6 +24,7 @@ class UserMessages {
String flutterGitUrl(String url) => 'FLUTTER_GIT_URL = $url'; String flutterGitUrl(String url) => 'FLUTTER_GIT_URL = $url';
String engineRevision(String revision) => 'Engine revision $revision'; String engineRevision(String revision) => 'Engine revision $revision';
String dartRevision(String revision) => 'Dart version $revision'; String dartRevision(String revision) => 'Dart version $revision';
String devToolsVersion(String version) => 'DevTools version $version';
String pubMirrorURL(String url) => 'Pub download mirror $url'; String pubMirrorURL(String url) => 'Pub download mirror $url';
String flutterMirrorURL(String url) => 'Flutter download mirror $url'; String flutterMirrorURL(String url) => 'Flutter download mirror $url';
String get flutterBinariesDoNotRun => String get flutterBinariesDoNotRun =>
......
...@@ -361,6 +361,35 @@ class Cache { ...@@ -361,6 +361,35 @@ class Cache {
} }
} }
String get devToolsVersion {
if (_devToolsVersion == null) {
const String devToolsDirPath = 'dart-sdk/bin/resources/devtools';
final Directory devToolsDir = getCacheDir(devToolsDirPath, shouldCreate: false);
if (!devToolsDir.existsSync()) {
throw Exception('Could not find directory at ${devToolsDir.path}');
}
final String versionFilePath = '${devToolsDir.path}/version.json';
final File versionFile = _fileSystem.file(versionFilePath);
if (!versionFile.existsSync()) {
throw Exception('Could not find file at $versionFilePath');
}
final dynamic data = jsonDecode(versionFile.readAsStringSync());
if (data is! Map<String, Object>) {
throw Exception("Expected object of type 'Map<String, Object>' but got one of type '${data.runtimeType}'");
}
final dynamic version = data['version'];
if (version == null) {
throw Exception('Could not parse DevTools version from $version');
}
if (version is! String) {
throw Exception("Could not parse DevTools version. Expected object of type 'String', but got one of type '${version.runtimeType}'");
}
return _devToolsVersion = version;
}
return _devToolsVersion!;
}
String ? _devToolsVersion;
/// The current version of Dart used to build Flutter and run the tool. /// The current version of Dart used to build Flutter and run the tool.
String get dartSdkVersion { String get dartSdkVersion {
if (_dartSdkVersion == null) { if (_dartSdkVersion == null) {
...@@ -444,9 +473,12 @@ class Cache { ...@@ -444,9 +473,12 @@ class Cache {
} }
/// Return a directory in the cache dir. For `pkg`, this will return `bin/cache/pkg`. /// Return a directory in the cache dir. For `pkg`, this will return `bin/cache/pkg`.
Directory getCacheDir(String name) { ///
/// When [shouldCreate] is true, the cache directory at [name] will be created
/// if it does not already exist.
Directory getCacheDir(String name, { bool shouldCreate = true }) {
final Directory dir = _fileSystem.directory(_fileSystem.path.join(getRoot().path, name)); final Directory dir = _fileSystem.directory(_fileSystem.path.join(getRoot().path, name));
if (!dir.existsSync()) { if (!dir.existsSync() && shouldCreate) {
dir.createSync(recursive: true); dir.createSync(recursive: true);
_osUtils.chmod(dir, '755'); _osUtils.chmod(dir, '755');
} }
......
...@@ -91,6 +91,7 @@ class _DefaultDoctorValidatorsProvider implements DoctorValidatorsProvider { ...@@ -91,6 +91,7 @@ class _DefaultDoctorValidatorsProvider implements DoctorValidatorsProvider {
fileSystem: globals.fs, fileSystem: globals.fs,
platform: globals.platform, platform: globals.platform,
flutterVersion: () => globals.flutterVersion, flutterVersion: () => globals.flutterVersion,
devToolsVersion: () => globals.cache.devToolsVersion,
processManager: globals.processManager, processManager: globals.processManager,
userMessages: userMessages, userMessages: userMessages,
artifacts: globals.artifacts!, artifacts: globals.artifacts!,
...@@ -394,6 +395,7 @@ class FlutterValidator extends DoctorValidator { ...@@ -394,6 +395,7 @@ class FlutterValidator extends DoctorValidator {
FlutterValidator({ FlutterValidator({
required Platform platform, required Platform platform,
required FlutterVersion Function() flutterVersion, required FlutterVersion Function() flutterVersion,
required String Function() devToolsVersion,
required UserMessages userMessages, required UserMessages userMessages,
required FileSystem fileSystem, required FileSystem fileSystem,
required Artifacts artifacts, required Artifacts artifacts,
...@@ -401,6 +403,7 @@ class FlutterValidator extends DoctorValidator { ...@@ -401,6 +403,7 @@ class FlutterValidator extends DoctorValidator {
required String Function() flutterRoot, required String Function() flutterRoot,
required OperatingSystemUtils operatingSystemUtils, required OperatingSystemUtils operatingSystemUtils,
}) : _flutterVersion = flutterVersion, }) : _flutterVersion = flutterVersion,
_devToolsVersion = devToolsVersion,
_platform = platform, _platform = platform,
_userMessages = userMessages, _userMessages = userMessages,
_fileSystem = fileSystem, _fileSystem = fileSystem,
...@@ -412,6 +415,7 @@ class FlutterValidator extends DoctorValidator { ...@@ -412,6 +415,7 @@ class FlutterValidator extends DoctorValidator {
final Platform _platform; final Platform _platform;
final FlutterVersion Function() _flutterVersion; final FlutterVersion Function() _flutterVersion;
final String Function() _devToolsVersion;
final String Function() _flutterRoot; final String Function() _flutterRoot;
final UserMessages _userMessages; final UserMessages _userMessages;
final FileSystem _fileSystem; final FileSystem _fileSystem;
...@@ -446,6 +450,7 @@ class FlutterValidator extends DoctorValidator { ...@@ -446,6 +450,7 @@ class FlutterValidator extends DoctorValidator {
))); )));
messages.add(ValidationMessage(_userMessages.engineRevision(version.engineRevisionShort))); messages.add(ValidationMessage(_userMessages.engineRevision(version.engineRevisionShort)));
messages.add(ValidationMessage(_userMessages.dartRevision(version.dartSdkVersion))); messages.add(ValidationMessage(_userMessages.dartRevision(version.dartSdkVersion)));
messages.add(ValidationMessage(_userMessages.devToolsVersion(_devToolsVersion())));
final String? pubUrl = _platform.environment['PUB_HOSTED_URL']; final String? pubUrl = _platform.environment['PUB_HOSTED_URL'];
if (pubUrl != null) { if (pubUrl != null) {
messages.add(ValidationMessage(_userMessages.pubMirrorURL(pubUrl))); messages.add(ValidationMessage(_userMessages.pubMirrorURL(pubUrl)));
......
...@@ -144,6 +144,8 @@ class FlutterVersion { ...@@ -144,6 +144,8 @@ class FlutterVersion {
late String _frameworkVersion; late String _frameworkVersion;
String get frameworkVersion => _frameworkVersion; String get frameworkVersion => _frameworkVersion;
String get devToolsVersion => globals.cache.devToolsVersion;
String get dartSdkVersion => globals.cache.dartSdkVersion; String get dartSdkVersion => globals.cache.dartSdkVersion;
String get engineRevision => globals.cache.engineRevision; String get engineRevision => globals.cache.engineRevision;
...@@ -159,10 +161,10 @@ class FlutterVersion { ...@@ -159,10 +161,10 @@ class FlutterVersion {
final String flutterText = 'Flutter$versionText • channel $channel${repositoryUrl ?? 'unknown source'}'; final String flutterText = 'Flutter$versionText • channel $channel${repositoryUrl ?? 'unknown source'}';
final String frameworkText = 'Framework • revision $frameworkRevisionShort ($frameworkAge) • $frameworkCommitDate'; final String frameworkText = 'Framework • revision $frameworkRevisionShort ($frameworkAge) • $frameworkCommitDate';
final String engineText = 'Engine • revision $engineRevisionShort'; final String engineText = 'Engine • revision $engineRevisionShort';
final String toolsText = 'Tools • Dart $dartSdkVersion'; final String toolsText = 'Tools • Dart $dartSdkVersion • DevTools $devToolsVersion';
// Flutter 1.10.2-pre.69 • channel master • https://github.com/flutter/flutter.git // Flutter 1.10.2-pre.69 • channel master • https://github.com/flutter/flutter.git
// Framework • revision 340c158f32 (84 minutes ago) • 2018-10-26 11:27:22 -0400 // Framework • revision 340c158f32 (85 minutes ago) • 2018-10-26 11:27:22 -0400
// Engine • revision 9c46333e14 // Engine • revision 9c46333e14
// Tools • Dart 2.1.0 (build 2.1.0-dev.8.0 bf26f760b1) // Tools • Dart 2.1.0 (build 2.1.0-dev.8.0 bf26f760b1)
...@@ -177,6 +179,7 @@ class FlutterVersion { ...@@ -177,6 +179,7 @@ class FlutterVersion {
'frameworkCommitDate': frameworkCommitDate, 'frameworkCommitDate': frameworkCommitDate,
'engineRevision': engineRevision, 'engineRevision': engineRevision,
'dartSdkVersion': dartSdkVersion, 'dartSdkVersion': dartSdkVersion,
'devToolsVersion': devToolsVersion,
}; };
String get frameworkDate => frameworkCommitDate; String get frameworkDate => frameworkCommitDate;
......
...@@ -894,6 +894,12 @@ void main() { ...@@ -894,6 +894,12 @@ void main() {
expect(pub.calledGet, 1); expect(pub.calledGet, 1);
}); });
testUsingContext('Check current DevTools version', () async {
final String currentDevToolsVersion = globals.cache.devToolsVersion;
final RegExp devToolsVersionFormat = RegExp(r'\d+\.\d+\.\d+(?:-\S+)?');
expect(devToolsVersionFormat.allMatches(currentDevToolsVersion).length, 1,);
});
// Check that the build number matches the format documented here: // Check that the build number matches the format documented here:
// https://dart.dev/get-dart#release-channels // https://dart.dev/get-dart#release-channels
testUsingContext('Check current Dart SDK build number', () async { testUsingContext('Check current Dart SDK build number', () async {
...@@ -1060,7 +1066,7 @@ class FakeSecondaryCache extends Fake implements Cache { ...@@ -1060,7 +1066,7 @@ class FakeSecondaryCache extends Fake implements Cache {
Directory getArtifactDirectory(String name) => artifactDirectory; Directory getArtifactDirectory(String name) => artifactDirectory;
@override @override
Directory getCacheDir(String name) { Directory getCacheDir(String name, { bool shouldCreate = true }) {
return artifactDirectory.childDirectory(name); return artifactDirectory.childDirectory(name);
} }
......
...@@ -44,6 +44,7 @@ void main() { ...@@ -44,6 +44,7 @@ void main() {
environment: <String, String>{}, environment: <String, String>{},
), ),
flutterVersion: () => flutterVersion, flutterVersion: () => flutterVersion,
devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
artifacts: artifacts, artifacts: artifacts,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -85,6 +86,7 @@ void main() { ...@@ -85,6 +86,7 @@ void main() {
environment: <String, String>{}, environment: <String, String>{},
), ),
flutterVersion: () => flutterVersion, flutterVersion: () => flutterVersion,
devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
artifacts: Artifacts.test(), artifacts: Artifacts.test(),
fileSystem: MemoryFileSystem.test(), fileSystem: MemoryFileSystem.test(),
...@@ -106,6 +108,7 @@ void main() { ...@@ -106,6 +108,7 @@ void main() {
final FlutterValidator flutterValidator = FlutterValidator( final FlutterValidator flutterValidator = FlutterValidator(
platform: FakePlatform(operatingSystem: 'windows', localeName: 'en_US.UTF-8'), platform: FakePlatform(operatingSystem: 'windows', localeName: 'en_US.UTF-8'),
flutterVersion: () => FakeThrowingFlutterVersion(), flutterVersion: () => FakeThrowingFlutterVersion(),
devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
artifacts: Artifacts.test(), artifacts: Artifacts.test(),
fileSystem: MemoryFileSystem.test(), fileSystem: MemoryFileSystem.test(),
...@@ -141,6 +144,7 @@ void main() { ...@@ -141,6 +144,7 @@ void main() {
final FlutterValidator flutterValidator = FlutterValidator( final FlutterValidator flutterValidator = FlutterValidator(
platform: platform, platform: platform,
flutterVersion: () => flutterVersion, flutterVersion: () => flutterVersion,
devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
artifacts: artifacts, artifacts: artifacts,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -168,6 +172,7 @@ void main() { ...@@ -168,6 +172,7 @@ void main() {
}, },
), ),
flutterVersion: () => FakeFlutterVersion(frameworkVersion: '1.0.0'), flutterVersion: () => FakeFlutterVersion(frameworkVersion: '1.0.0'),
devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
artifacts: Artifacts.test(), artifacts: Artifacts.test(),
fileSystem: MemoryFileSystem.test(), fileSystem: MemoryFileSystem.test(),
...@@ -188,6 +193,7 @@ void main() { ...@@ -188,6 +193,7 @@ void main() {
final FlutterValidator flutterValidator = FlutterValidator( final FlutterValidator flutterValidator = FlutterValidator(
platform: FakePlatform(localeName: 'en_US.UTF-8'), platform: FakePlatform(localeName: 'en_US.UTF-8'),
flutterVersion: () => FakeFlutterVersion(frameworkVersion: '1.0.0'), flutterVersion: () => FakeFlutterVersion(frameworkVersion: '1.0.0'),
devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
artifacts: Artifacts.test(), artifacts: Artifacts.test(),
fileSystem: MemoryFileSystem.test(), fileSystem: MemoryFileSystem.test(),
...@@ -210,6 +216,7 @@ void main() { ...@@ -210,6 +216,7 @@ void main() {
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
repositoryUrl: null, repositoryUrl: null,
), ),
devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
artifacts: Artifacts.test(), artifacts: Artifacts.test(),
fileSystem: MemoryFileSystem.test(), fileSystem: MemoryFileSystem.test(),
......
...@@ -141,6 +141,16 @@ void main() { ...@@ -141,6 +141,16 @@ void main() {
}); });
testUsingContext('create local report', () async { testUsingContext('create local report', () async {
// Since crash reporting calls the doctor, which checks for the devtools
// version file in the cache, write a version file to the memory fs.
Cache.flutterRoot = '/path/to/flutter';
final Directory devtoolsDir = globals.fs.directory(
'${Cache.flutterRoot}/bin/cache/dart-sdk/bin/resources/devtools',
)..createSync(recursive: true);
devtoolsDir.childFile('version.json').writeAsStringSync(
'{"version": "1.2.3"}',
);
final Completer<void> completer = Completer<void>(); final Completer<void> completer = Completer<void>();
// runner.run() asynchronously calls the exit function set above, so we // runner.run() asynchronously calls the exit function set above, so we
// catch it in a zone. // catch it in a zone.
......
...@@ -126,7 +126,7 @@ void main() { ...@@ -126,7 +126,7 @@ void main() {
'Flutter • channel $channel • unknown source\n' 'Flutter • channel $channel • unknown source\n'
'Framework • revision 1234abcd (1 second ago) • ${getChannelUpToDateVersion()}\n' 'Framework • revision 1234abcd (1 second ago) • ${getChannelUpToDateVersion()}\n'
'Engine • revision abcdefg\n' 'Engine • revision abcdefg\n'
'Tools • Dart 2.12.0', 'Tools • Dart 2.12.0 • DevTools 2.8.0',
); );
expect(flutterVersion.frameworkAge, '1 second ago'); expect(flutterVersion.frameworkAge, '1 second ago');
expect(flutterVersion.getVersionString(), '$channel/1234abcd'); expect(flutterVersion.getVersionString(), '$channel/1234abcd');
...@@ -605,6 +605,9 @@ class FakeCache extends Fake implements Cache { ...@@ -605,6 +605,9 @@ class FakeCache extends Fake implements Cache {
@override @override
String get engineRevision => 'abcdefg'; String get engineRevision => 'abcdefg';
@override
String get devToolsVersion => '2.8.0';
@override @override
String get dartSdkVersion => '2.12.0'; String get dartSdkVersion => '2.12.0';
......
...@@ -320,6 +320,7 @@ class FakeFlutterVersion implements FlutterVersion { ...@@ -320,6 +320,7 @@ class FakeFlutterVersion implements FlutterVersion {
FakeFlutterVersion({ FakeFlutterVersion({
this.channel = 'unknown', this.channel = 'unknown',
this.dartSdkVersion = '12', this.dartSdkVersion = '12',
this.devToolsVersion = '2.8.0',
this.engineRevision = 'abcdefghijklmnopqrstuvwxyz', this.engineRevision = 'abcdefghijklmnopqrstuvwxyz',
this.engineRevisionShort = 'abcde', this.engineRevisionShort = 'abcde',
this.repositoryUrl = 'https://github.com/flutter/flutter.git', this.repositoryUrl = 'https://github.com/flutter/flutter.git',
...@@ -340,6 +341,9 @@ class FakeFlutterVersion implements FlutterVersion { ...@@ -340,6 +341,9 @@ class FakeFlutterVersion implements FlutterVersion {
@override @override
final String channel; final String channel;
@override
final String devToolsVersion;
@override @override
final String dartSdkVersion; final String dartSdkVersion;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment