mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Reverts https://github.com/flutter/flutter/pull/163753
Relands https://github.com/flutter/flutter/pull/140783
Original PR description below
------
This makes various Flutter version information available at runtime.
It's basically the same as executing `flutter --version`. This is
especially useful for tools like Crashlytics or Sentry (see for example
https://github.com/getsentry/sentry-dart/issues/416).
Usage example:
```dart
FlutterVersion.version; // 3.16.5
FlutterVersion.channel; // stable
FlutterVersion.gitUrl; // https://github.com/flutter/flutter.git
FlutterVersion.frameworkRevision; // 78666c8dc5
FlutterVersion.engineRevision; // 3f3e560236
FlutterVersion.dartVersion; // 3.2.3
```
This approach has prior art as seen in #134179.
Fixes https://github.com/flutter/flutter/issues/61814
<!-- *If you had to change anything in the [flutter/tests] repo, include
a link to the migration guide as per the [breaking change policy].* -->
## Pre-launch Checklist
- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] All existing and new tests are passing.
If you need help, consider asking for advice on the #hackers-new channel
on [Discord].
<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[test-exempt]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat
This commit is contained in:
parent
2bf32d855e
commit
a8d1b62382
@ -20,6 +20,7 @@ export 'src/services/clipboard.dart';
|
||||
export 'src/services/debug.dart';
|
||||
export 'src/services/deferred_component.dart';
|
||||
export 'src/services/flavor.dart';
|
||||
export 'src/services/flutter_version.dart';
|
||||
export 'src/services/font_loader.dart';
|
||||
export 'src/services/haptic_feedback.dart';
|
||||
export 'src/services/hardware_keyboard.dart';
|
||||
|
49
packages/flutter/lib/src/services/flutter_version.dart
Normal file
49
packages/flutter/lib/src/services/flutter_version.dart
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @docImport 'dart:io'
|
||||
|
||||
/// Details about the Flutter version this app was compiled with,
|
||||
/// corresponding to the output of `flutter --version`.
|
||||
///
|
||||
/// When this Flutter version was build from a fork, or when Flutter runs in a
|
||||
/// custom embedder, these values might be unreliable.
|
||||
///
|
||||
/// See also:
|
||||
/// - [Platform.version]
|
||||
abstract final class FlutterVersion {
|
||||
const FlutterVersion._();
|
||||
|
||||
/// The Flutter version used to compile the app.
|
||||
static const String? version =
|
||||
bool.hasEnvironment('FLUTTER_VERSION') ? String.fromEnvironment('FLUTTER_VERSION') : null;
|
||||
|
||||
/// The Flutter channel used to compile the app.
|
||||
static const String? channel =
|
||||
bool.hasEnvironment('FLUTTER_CHANNEL') ? String.fromEnvironment('FLUTTER_CHANNEL') : null;
|
||||
|
||||
/// The URL of the Git repository from which Flutter was obtained.
|
||||
static const String? gitUrl =
|
||||
bool.hasEnvironment('FLUTTER_GIT_URL') ? String.fromEnvironment('FLUTTER_GIT_URL') : null;
|
||||
|
||||
/// The Flutter framework revision, as a (short) Git commit ID.
|
||||
static const String? frameworkRevision =
|
||||
bool.hasEnvironment('FLUTTER_FRAMEWORK_REVISION')
|
||||
? String.fromEnvironment('FLUTTER_FRAMEWORK_REVISION')
|
||||
: null;
|
||||
|
||||
/// The Flutter engine revision.
|
||||
static const String? engineRevision =
|
||||
bool.hasEnvironment('FLUTTER_ENGINE_REVISION')
|
||||
? String.fromEnvironment('FLUTTER_ENGINE_REVISION')
|
||||
: null;
|
||||
|
||||
// This is included since [Platform.version](https://api.dart.dev/stable/dart-io/Platform/version.html)
|
||||
// is not included on web platforms.
|
||||
/// The Dart version used to compile the app.
|
||||
static const String? dartVersion =
|
||||
bool.hasEnvironment('FLUTTER_DART_VERSION')
|
||||
? String.fromEnvironment('FLUTTER_DART_VERSION')
|
||||
: null;
|
||||
}
|
35
packages/flutter/test/services/flutter_version_test.dart
Normal file
35
packages/flutter/test/services/flutter_version_test.dart
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
test('FlutterVersion.version contains the current version', () {
|
||||
expect(FlutterVersion.version, const String.fromEnvironment('FLUTTER_VERSION'));
|
||||
});
|
||||
|
||||
test('FlutterVersion.channel contains the current channel', () {
|
||||
expect(FlutterVersion.channel, const String.fromEnvironment('FLUTTER_CHANNEL'));
|
||||
});
|
||||
|
||||
test('FlutterVersion.gitUrl contains the current git URL', () {
|
||||
expect(FlutterVersion.gitUrl, const String.fromEnvironment('FLUTTER_GIT_URL'));
|
||||
});
|
||||
|
||||
test('FlutterVersion.frameworkRevision contains the current framework revision', () {
|
||||
expect(
|
||||
FlutterVersion.frameworkRevision,
|
||||
const String.fromEnvironment('FLUTTER_FRAMEWORK_REVISION'),
|
||||
);
|
||||
});
|
||||
|
||||
test('FlutterVersion.engineRevision contains the current engine revision', () {
|
||||
expect(FlutterVersion.engineRevision, const String.fromEnvironment('FLUTTER_ENGINE_REVISION'));
|
||||
});
|
||||
|
||||
test('FlutterVersion.dartVersion contains the current Dart version', () {
|
||||
expect(FlutterVersion.dartVersion, const String.fromEnvironment('FLUTTER_DART_VERSION'));
|
||||
});
|
||||
}
|
@ -30,6 +30,7 @@ import '../globals.dart' as globals;
|
||||
import '../project.dart';
|
||||
import '../reporting/reporting.dart';
|
||||
import '../reporting/unified_analytics.dart';
|
||||
import '../version.dart';
|
||||
import 'flutter_command_runner.dart';
|
||||
import 'target_devices.dart';
|
||||
|
||||
@ -182,6 +183,41 @@ abstract class FlutterCommand extends Command<void> {
|
||||
/// The flag name for whether or not to use ipv6.
|
||||
static const String ipv6Flag = 'ipv6';
|
||||
|
||||
/// The dart define used for adding the Flutter version at runtime.
|
||||
@visibleForTesting
|
||||
static const String flutterVersionDefine = 'FLUTTER_VERSION';
|
||||
|
||||
/// The dart define used for adding the Flutter channel at runtime.
|
||||
@visibleForTesting
|
||||
static const String flutterChannelDefine = 'FLUTTER_CHANNEL';
|
||||
|
||||
/// The dart define used for adding the Flutter git URL at runtime.
|
||||
@visibleForTesting
|
||||
static const String flutterGitUrlDefine = 'FLUTTER_GIT_URL';
|
||||
|
||||
/// The dart define used for adding the Flutter framework revision at runtime.
|
||||
@visibleForTesting
|
||||
static const String flutterFrameworkRevisionDefine = 'FLUTTER_FRAMEWORK_REVISION';
|
||||
|
||||
/// The dart define used for adding the Flutter engine revision at runtime.
|
||||
@visibleForTesting
|
||||
static const String flutterEngineRevisionDefine = 'FLUTTER_ENGINE_REVISION';
|
||||
|
||||
/// The dart define used for adding the Dart version at runtime.
|
||||
@visibleForTesting
|
||||
static const String flutterDartVersionDefine = 'FLUTTER_DART_VERSION';
|
||||
|
||||
/// List of all dart defines used for adding Flutter version information at runtime
|
||||
@visibleForTesting
|
||||
static const List<String> flutterVersionDartDefines = <String>[
|
||||
flutterVersionDefine,
|
||||
flutterChannelDefine,
|
||||
flutterGitUrlDefine,
|
||||
flutterFrameworkRevisionDefine,
|
||||
flutterEngineRevisionDefine,
|
||||
flutterDartVersionDefine,
|
||||
];
|
||||
|
||||
@override
|
||||
ArgParser get argParser => _argParser;
|
||||
final ArgParser _argParser = ArgParser(
|
||||
@ -1419,6 +1455,8 @@ abstract class FlutterCommand extends Command<void> {
|
||||
final String? cliFlavor = argParser.options.containsKey('flavor') ? stringArg('flavor') : null;
|
||||
final String? flavor = cliFlavor ?? defaultFlavor;
|
||||
|
||||
_addFlutterVersionToDartDefines(globals.flutterVersion, dartDefines);
|
||||
|
||||
return BuildInfo(
|
||||
buildMode,
|
||||
flavor,
|
||||
@ -1456,6 +1494,34 @@ abstract class FlutterCommand extends Command<void> {
|
||||
);
|
||||
}
|
||||
|
||||
// This adds the Dart defines used to access various Flutter version information at runtime.
|
||||
void _addFlutterVersionToDartDefines(FlutterVersion version, List<String> dartDefines) {
|
||||
for (final String dartDefine in flutterVersionDartDefines) {
|
||||
if (globals.platform.environment[dartDefine] != null) {
|
||||
throwToolExit(
|
||||
'$dartDefine is used by the framework and cannot be set in the environment. '
|
||||
'Use FlutterVersion to access it in Flutter code',
|
||||
);
|
||||
}
|
||||
if (dartDefines.any((String define) => define.startsWith(dartDefine))) {
|
||||
throwToolExit(
|
||||
'$dartDefine is used by the framework and cannot be '
|
||||
'set using --${FlutterOptions.kDartDefinesOption} or --${FlutterOptions.kDartDefineFromFileOption}. '
|
||||
'Use FlutterVersion to access it in Flutter code',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
dartDefines.addAll(<String>[
|
||||
'$flutterVersionDefine=${version.frameworkVersion}',
|
||||
'$flutterChannelDefine=${version.channel}',
|
||||
'$flutterGitUrlDefine=${version.repositoryUrl}',
|
||||
'$flutterFrameworkRevisionDefine=${version.frameworkRevisionShort}',
|
||||
'$flutterEngineRevisionDefine=${version.engineRevisionShort}',
|
||||
'$flutterDartVersionDefine=${version.dartSdkVersion}',
|
||||
]);
|
||||
}
|
||||
|
||||
void setupApplicationPackages() {
|
||||
applicationPackages ??= ApplicationPackageFactory.instance;
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ flutter:
|
||||
'-I=/flutter/packages/flutter_tools/gradle/aar_init_script.gradle',
|
||||
...List<RegExp>.filled(4, RegExp(r'-P[a-zA-Z-]+=.*')),
|
||||
'-q',
|
||||
...List<RegExp>.filled(5, RegExp(r'-P[a-zA-Z-]+=.*')),
|
||||
...List<RegExp>.filled(6, RegExp(r'-P[a-zA-Z-]+=.*')),
|
||||
'assembleAar$buildMode',
|
||||
],
|
||||
onRun: (_) => fs.directory('/build/host/outputs/repo').createSync(recursive: true),
|
||||
|
@ -651,7 +651,7 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg
|
||||
'set(FLUTTER_VERSION_MINOR 0 PARENT_SCOPE)',
|
||||
'set(FLUTTER_VERSION_PATCH 0 PARENT_SCOPE)',
|
||||
'set(FLUTTER_VERSION_BUILD 0 PARENT_SCOPE)',
|
||||
' "DART_DEFINES=Zm9vLmJhcj0y,Zml6ei5mYXI9Mw=="',
|
||||
' "DART_DEFINES=Zm9vLmJhcj0y,Zml6ei5mYXI9Mw==,RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI="',
|
||||
' "DART_OBFUSCATION=true"',
|
||||
' "EXTRA_FRONT_END_OPTIONS=--enable-experiment=non-nullable"',
|
||||
' "EXTRA_GEN_SNAPSHOT_OPTIONS=--enable-experiment=non-nullable"',
|
||||
|
@ -485,7 +485,7 @@ STDERR STUFF
|
||||
'FLUTTER_BUILD_DIR=build',
|
||||
'FLUTTER_BUILD_NAME=1.0.0',
|
||||
'FLUTTER_BUILD_NUMBER=1',
|
||||
'DART_DEFINES=Zm9vLmJhcj0y,Zml6ei5mYXI9Mw==',
|
||||
'DART_DEFINES=Zm9vLmJhcj0y,Zml6ei5mYXI9Mw==,RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
'DART_OBFUSCATION=true',
|
||||
'EXTRA_FRONT_END_OPTIONS=--enable-experiment=non-nullable',
|
||||
'EXTRA_GEN_SNAPSHOT_OPTIONS=--enable-experiment=non-nullable',
|
||||
|
@ -143,7 +143,8 @@ void main() {
|
||||
'HasWebPlugins': 'true',
|
||||
'ServiceWorkerStrategy': 'offline-first',
|
||||
'BuildMode': 'release',
|
||||
'DartDefines': 'Zm9vPWE=',
|
||||
'DartDefines':
|
||||
'Zm9vPWE=,RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
'DartObfuscation': 'false',
|
||||
'TrackWidgetCreation': 'false',
|
||||
'TreeShakeIcons': 'true',
|
||||
@ -204,7 +205,8 @@ void main() {
|
||||
'Dart2jsNoFrequencyBasedMinification': 'false',
|
||||
'Dart2jsOptimization': 'O3',
|
||||
'BuildMode': 'release',
|
||||
'DartDefines': 'Zm9vPWE=,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==',
|
||||
'DartDefines':
|
||||
'Zm9vPWE=,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
'DartObfuscation': 'false',
|
||||
'TrackWidgetCreation': 'false',
|
||||
'TreeShakeIcons': 'true',
|
||||
@ -258,6 +260,8 @@ void main() {
|
||||
'HasWebPlugins': 'true',
|
||||
'ServiceWorkerStrategy': 'offline-first',
|
||||
'BuildMode': 'release',
|
||||
'DartDefines':
|
||||
'RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
'DartObfuscation': 'false',
|
||||
'TrackWidgetCreation': 'false',
|
||||
'TreeShakeIcons': 'true',
|
||||
|
@ -568,7 +568,7 @@ if %errorlevel% neq 0 goto :VCEnd</Command>
|
||||
r'set(FLUTTER_VERSION_MINOR 0 PARENT_SCOPE)',
|
||||
r'set(FLUTTER_VERSION_PATCH 0 PARENT_SCOPE)',
|
||||
r'set(FLUTTER_VERSION_BUILD 0 PARENT_SCOPE)',
|
||||
r' "DART_DEFINES=Zm9vPWE=,YmFyPWI="',
|
||||
r' "DART_DEFINES=Zm9vPWE=,YmFyPWI=,RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI="',
|
||||
r' "DART_OBFUSCATION=true"',
|
||||
r' "EXTRA_FRONT_END_OPTIONS=--enable-experiment=non-nullable"',
|
||||
r' "EXTRA_GEN_SNAPSHOT_OPTIONS=--enable-experiment=non-nullable"',
|
||||
|
@ -381,6 +381,7 @@ void main() {
|
||||
'-PbuildNumber=1.0',
|
||||
'-q',
|
||||
'-Ptarget=${globals.fs.path.join('lib', 'main.dart')}',
|
||||
'-Pdart-defines=RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
'-Pdart-obfuscation=false',
|
||||
'-Pextra-front-end-options=foo,bar',
|
||||
'-Ptrack-widget-creation=true',
|
||||
|
@ -508,6 +508,7 @@ void main() {
|
||||
'-Ptarget-platform=android-arm,android-arm64,android-x64',
|
||||
'-Ptarget=${globals.fs.path.join(tempDir.path, 'flutter_project', 'lib', 'main.dart')}',
|
||||
'-Pbase-application-name=android.app.Application',
|
||||
'-Pdart-defines=RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
'-Pdart-obfuscation=false',
|
||||
'-Ptrack-widget-creation=true',
|
||||
'-Ptree-shake-icons=true',
|
||||
@ -547,6 +548,7 @@ void main() {
|
||||
'-Ptarget-platform=android-arm,android-arm64,android-x64',
|
||||
'-Ptarget=${globals.fs.path.join(tempDir.path, 'flutter_project', 'lib', 'main.dart')}',
|
||||
'-Pbase-application-name=android.app.Application',
|
||||
'-Pdart-defines=RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
'-Pdart-obfuscation=false',
|
||||
'-Psplit-debug-info=${tempDir.path}',
|
||||
'-Ptrack-widget-creation=true',
|
||||
@ -590,6 +592,7 @@ void main() {
|
||||
'-Ptarget-platform=android-arm,android-arm64,android-x64',
|
||||
'-Ptarget=${globals.fs.path.join(tempDir.path, 'flutter_project', 'lib', 'main.dart')}',
|
||||
'-Pbase-application-name=android.app.Application',
|
||||
'-Pdart-defines=RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
'-Pdart-obfuscation=false',
|
||||
'-Pextra-front-end-options=foo,bar',
|
||||
'-Ptrack-widget-creation=true',
|
||||
@ -633,6 +636,7 @@ void main() {
|
||||
'-Ptarget-platform=android-arm,android-arm64,android-x64',
|
||||
'-Ptarget=${globals.fs.path.join(tempDir.path, 'flutter_project', 'lib', 'main.dart')}',
|
||||
'-Pbase-application-name=android.app.Application',
|
||||
'-Pdart-defines=RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
'-Pdart-obfuscation=false',
|
||||
'-Ptrack-widget-creation=true',
|
||||
'-Ptree-shake-icons=true',
|
||||
@ -678,6 +682,7 @@ void main() {
|
||||
'-Ptarget-platform=android-arm,android-arm64,android-x64',
|
||||
'-Ptarget=${globals.fs.path.join(tempDir.path, 'flutter_project', 'lib', 'main.dart')}',
|
||||
'-Pbase-application-name=android.app.Application',
|
||||
'-Pdart-defines=RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
'-Pdart-obfuscation=false',
|
||||
'-Ptrack-widget-creation=true',
|
||||
'-Ptree-shake-icons=true',
|
||||
@ -731,6 +736,7 @@ void main() {
|
||||
'-Ptarget-platform=android-arm,android-arm64,android-x64',
|
||||
'-Ptarget=${globals.fs.path.join(tempDir.path, 'flutter_project', 'lib', 'main.dart')}',
|
||||
'-Pbase-application-name=android.app.Application',
|
||||
'-Pdart-defines=RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
'-Pdart-obfuscation=false',
|
||||
'-Ptrack-widget-creation=true',
|
||||
'-Ptree-shake-icons=true',
|
||||
|
@ -301,6 +301,8 @@ void main() {
|
||||
kBuildMode: 'debug',
|
||||
kTargetPlatform: 'android-arm',
|
||||
kTargetFile: globals.fs.path.join('lib', 'main.dart'),
|
||||
kDartDefines:
|
||||
'RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
kTrackWidgetCreation: 'true',
|
||||
kFileSystemScheme: 'org-dartlang-root',
|
||||
kIconTreeShakerFlag: 'false',
|
||||
@ -343,7 +345,8 @@ void main() {
|
||||
kTargetFile: globals.fs.path.join('lib', 'main.dart'),
|
||||
kTrackWidgetCreation: 'true',
|
||||
kFileSystemScheme: 'org-dartlang-root',
|
||||
kDartDefines: 'Zm9vPWJhcg==',
|
||||
kDartDefines:
|
||||
'Zm9vPWJhcg==,RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
kIconTreeShakerFlag: 'false',
|
||||
kDeferredComponents: 'false',
|
||||
kDartObfuscation: 'false',
|
||||
@ -382,6 +385,8 @@ void main() {
|
||||
kBuildMode: 'debug',
|
||||
kTargetPlatform: 'android-arm',
|
||||
kTargetFile: globals.fs.path.join('lib', 'main.dart'),
|
||||
kDartDefines:
|
||||
'RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
kTrackWidgetCreation: 'true',
|
||||
kFileSystemScheme: 'org-dartlang-root2',
|
||||
kIconTreeShakerFlag: 'false',
|
||||
@ -422,6 +427,8 @@ void main() {
|
||||
kBuildMode: 'debug',
|
||||
kTargetPlatform: 'android-arm',
|
||||
kTargetFile: globals.fs.path.join('lib', 'main.dart'),
|
||||
kDartDefines:
|
||||
'RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
kTrackWidgetCreation: 'true',
|
||||
kFileSystemScheme: 'org-dartlang-root',
|
||||
kFileSystemRoots: 'test1,test2',
|
||||
@ -463,6 +470,8 @@ void main() {
|
||||
kBuildMode: 'debug',
|
||||
kTargetPlatform: 'android-arm',
|
||||
kTargetFile: globals.fs.path.join('lib', 'main.dart'),
|
||||
kDartDefines:
|
||||
'RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
kTrackWidgetCreation: 'true',
|
||||
kFileSystemScheme: 'org-dartlang-root',
|
||||
kExtraFrontEndOptions: '--testflag,--testflag2',
|
||||
@ -504,6 +513,8 @@ void main() {
|
||||
kBuildMode: 'debug',
|
||||
kTargetPlatform: 'android-arm',
|
||||
kTargetFile: globals.fs.path.join('lib', 'main.dart'),
|
||||
kDartDefines:
|
||||
'RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
kTrackWidgetCreation: 'true',
|
||||
kFileSystemScheme: 'org-dartlang-root',
|
||||
kExtraGenSnapshotOptions: '--testflag,--testflag2',
|
||||
@ -550,7 +561,8 @@ void main() {
|
||||
kBuildMode: 'profile',
|
||||
kTargetPlatform: 'android-arm',
|
||||
kTargetFile: globals.fs.path.join('lib', 'main.dart'),
|
||||
kDartDefines: 'Zm9vPWJhcg==',
|
||||
kDartDefines:
|
||||
'Zm9vPWJhcg==,RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
kTrackWidgetCreation: 'true',
|
||||
kFileSystemScheme: 'org-dartlang-root',
|
||||
kFileSystemRoots: 'test1,test2',
|
||||
@ -599,7 +611,8 @@ void main() {
|
||||
kBuildMode: 'release',
|
||||
kTargetPlatform: 'android-arm',
|
||||
kTargetFile: globals.fs.path.join('lib', 'main.dart'),
|
||||
kDartDefines: 'Zm9vPWJhcg==',
|
||||
kDartDefines:
|
||||
'Zm9vPWJhcg==,RkxVVFRFUl9WRVJTSU9OPTAuMC4w,RkxVVFRFUl9DSEFOTkVMPW1hc3Rlcg==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049MTExMTE=,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049YWJjZGU=,RkxVVFRFUl9EQVJUX1ZFUlNJT049MTI=',
|
||||
kTrackWidgetCreation: 'true',
|
||||
kFileSystemScheme: 'org-dartlang-root',
|
||||
kFileSystemRoots: 'test1,test2',
|
||||
|
@ -18,10 +18,12 @@ import 'package:flutter_tools/src/base/time.dart';
|
||||
import 'package:flutter_tools/src/base/user_messages.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
import 'package:flutter_tools/src/commands/run.dart' show RunCommand;
|
||||
import 'package:flutter_tools/src/device.dart';
|
||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
import 'package:flutter_tools/src/pre_run_validator.dart';
|
||||
import 'package:flutter_tools/src/runner/flutter_command.dart';
|
||||
import 'package:flutter_tools/src/version.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:test/fake.dart';
|
||||
import 'package:unified_analytics/testing.dart';
|
||||
@ -1267,6 +1269,196 @@ flutter:
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
group('Flutter version', () {
|
||||
for (final String dartDefine in FlutterCommand.flutterVersionDartDefines) {
|
||||
testUsingContext(
|
||||
"tool exits when $dartDefine is already set in user's environment",
|
||||
() async {
|
||||
final CommandRunner<void> runner = createTestCommandRunner(
|
||||
_TestRunCommandThatOnlyValidates(),
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
runner.run(<String>['run', '--no-pub', '--no-hot']),
|
||||
throwsToolExit(
|
||||
message:
|
||||
'$dartDefine is used by the framework and cannot be set in the environment. '
|
||||
'Use FlutterVersion to access it in Flutter code',
|
||||
),
|
||||
);
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
DeviceManager:
|
||||
() => FakeDeviceManager()..attachedDevices = <Device>[FakeDevice('name', 'id')],
|
||||
Platform:
|
||||
() => FakePlatform(environment: <String, String>{dartDefine: 'I was already set'}),
|
||||
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
|
||||
FileSystem: () {
|
||||
return MemoryFileSystem.test()
|
||||
..file('lib/main.dart').createSync(recursive: true)
|
||||
..file('pubspec.yaml').createSync()
|
||||
..file('.packages').createSync();
|
||||
},
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
FlutterVersion: () => FakeFlutterVersion(),
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'tool exits when $dartDefine is set in --dart-define or --dart-define-from-file',
|
||||
() async {
|
||||
final CommandRunner<void> runner = createTestCommandRunner(
|
||||
_TestRunCommandThatOnlyValidates(),
|
||||
);
|
||||
|
||||
expect(
|
||||
runner.run(<String>[
|
||||
'run',
|
||||
'--dart-define=$dartDefine=AlreadySet',
|
||||
'--no-pub',
|
||||
'--no-hot',
|
||||
]),
|
||||
throwsToolExit(
|
||||
message:
|
||||
'$dartDefine is used by the framework and cannot be set using --dart-define or --dart-define-from-file. '
|
||||
'Use FlutterVersion to access it in Flutter code',
|
||||
),
|
||||
);
|
||||
|
||||
expect(
|
||||
runner.run(<String>[
|
||||
'run',
|
||||
'--dart-define-from-file=config.json',
|
||||
'--no-pub',
|
||||
'--no-hot',
|
||||
]),
|
||||
throwsToolExit(
|
||||
message:
|
||||
'$dartDefine is used by the framework and cannot be set using --dart-define or --dart-define-from-file. '
|
||||
'Use FlutterVersion to access it in Flutter code',
|
||||
),
|
||||
);
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
DeviceManager:
|
||||
() => FakeDeviceManager()..attachedDevices = <Device>[FakeDevice('name', 'id')],
|
||||
Platform: () => FakePlatform(),
|
||||
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
|
||||
FileSystem: () {
|
||||
final MemoryFileSystem fileSystem = MemoryFileSystem.test();
|
||||
fileSystem.file('lib/main.dart').createSync(recursive: true);
|
||||
fileSystem.file('pubspec.yaml').createSync();
|
||||
fileSystem.file('.packages').createSync();
|
||||
fileSystem.file('config.json')
|
||||
..createSync()
|
||||
..writeAsStringSync('{"$dartDefine": "AlreadySet"}');
|
||||
return fileSystem;
|
||||
},
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
FlutterVersion: () => FakeFlutterVersion(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
testUsingContext(
|
||||
'FLUTTER_VERSION is set in dartDefines',
|
||||
() async {
|
||||
final DummyFlutterCommand flutterCommand = DummyFlutterCommand(packagesPath: 'foo');
|
||||
final BuildInfo buildInfo = await flutterCommand.getBuildInfo(
|
||||
forcedBuildMode: BuildMode.debug,
|
||||
);
|
||||
expect(buildInfo.dartDefines, contains('FLUTTER_VERSION=0.0.0'));
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
FlutterVersion: () => FakeFlutterVersion(),
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'FLUTTER_CHANNEL is set in dartDefines',
|
||||
() async {
|
||||
final DummyFlutterCommand flutterCommand = DummyFlutterCommand(packagesPath: 'foo');
|
||||
final BuildInfo buildInfo = await flutterCommand.getBuildInfo(
|
||||
forcedBuildMode: BuildMode.debug,
|
||||
);
|
||||
|
||||
expect(buildInfo.dartDefines, contains('FLUTTER_CHANNEL=master'));
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
FlutterVersion: () => FakeFlutterVersion(),
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'FLUTTER_GIT_URL is set in dartDefines',
|
||||
() async {
|
||||
final DummyFlutterCommand flutterCommand = DummyFlutterCommand(packagesPath: 'foo');
|
||||
final BuildInfo buildInfo = await flutterCommand.getBuildInfo(
|
||||
forcedBuildMode: BuildMode.debug,
|
||||
);
|
||||
|
||||
expect(
|
||||
buildInfo.dartDefines,
|
||||
contains('FLUTTER_GIT_URL=https://github.com/flutter/flutter.git'),
|
||||
);
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
FlutterVersion: () => FakeFlutterVersion(),
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'FLUTTER_FRAMEWORK_REVISION is set in dartDefines',
|
||||
() async {
|
||||
final DummyFlutterCommand flutterCommand = DummyFlutterCommand(packagesPath: 'foo');
|
||||
final BuildInfo buildInfo = await flutterCommand.getBuildInfo(
|
||||
forcedBuildMode: BuildMode.debug,
|
||||
);
|
||||
|
||||
expect(buildInfo.dartDefines, contains('FLUTTER_FRAMEWORK_REVISION=11111'));
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
FlutterVersion: () => FakeFlutterVersion(),
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'FLUTTER_ENGINE_REVISION is set in dartDefines',
|
||||
() async {
|
||||
final DummyFlutterCommand flutterCommand = DummyFlutterCommand(packagesPath: 'foo');
|
||||
final BuildInfo buildInfo = await flutterCommand.getBuildInfo(
|
||||
forcedBuildMode: BuildMode.debug,
|
||||
);
|
||||
|
||||
expect(buildInfo.dartDefines, contains('FLUTTER_ENGINE_REVISION=abcde'));
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
FlutterVersion: () => FakeFlutterVersion(),
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'FLUTTER_DART_VERSION is set in dartDefines',
|
||||
() async {
|
||||
final DummyFlutterCommand flutterCommand = DummyFlutterCommand(packagesPath: 'foo');
|
||||
final BuildInfo buildInfo = await flutterCommand.getBuildInfo(
|
||||
forcedBuildMode: BuildMode.debug,
|
||||
);
|
||||
|
||||
expect(buildInfo.dartDefines, contains('FLUTTER_DART_VERSION=12'));
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
FlutterVersion: () => FakeFlutterVersion(),
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -1378,3 +1570,13 @@ class FakeClock extends Fake implements SystemClock {
|
||||
return DateTime.fromMillisecondsSinceEpoch(times.removeAt(0));
|
||||
}
|
||||
}
|
||||
|
||||
class _TestRunCommandThatOnlyValidates extends RunCommand {
|
||||
@override
|
||||
Future<FlutterCommandResult> runCommand() async {
|
||||
return FlutterCommandResult.success();
|
||||
}
|
||||
|
||||
@override
|
||||
bool get shouldRunPub => false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user