Unverified Commit e90e4888 authored by Andrew Kolos's avatar Andrew Kolos Committed by GitHub

in `flutter run`, throw tool exit when `--flavor` is provided but is not...

in `flutter run`, throw tool exit when `--flavor` is provided but is not supported on the target device (#139045)

Fixes https://github.com/flutter/flutter/issues/134197
parent 8c11aa03
...@@ -372,6 +372,9 @@ class AndroidDevice extends Device { ...@@ -372,6 +372,9 @@ class AndroidDevice extends Device {
@override @override
String get name => modelID; String get name => modelID;
@override
bool get supportsFlavors => true;
@override @override
Future<bool> isAppInstalled( Future<bool> isAppInstalled(
ApplicationPackage app, { ApplicationPackage app, {
......
...@@ -610,6 +610,13 @@ class RunCommand extends RunCommandBase { ...@@ -610,6 +610,13 @@ class RunCommand extends RunCommandBase {
webMode = featureFlags.isWebEnabled && webMode = featureFlags.isWebEnabled &&
devices!.length == 1 && devices!.length == 1 &&
await devices!.single.targetPlatform == TargetPlatform.web_javascript; await devices!.single.targetPlatform == TargetPlatform.web_javascript;
final String? flavor = stringArg('flavor');
final bool flavorsSupportedOnEveryDevice = devices!
.every((Device device) => device.supportsFlavors);
if (flavor != null && !flavorsSupportedOnEveryDevice) {
throwToolExit('--flavor is only supported for Android, macOS, and iOS devices.');
}
} }
@visibleForTesting @visibleForTesting
......
...@@ -469,6 +469,10 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts { ...@@ -469,6 +469,10 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
' sdk: flutter\n', ' sdk: flutter\n',
); );
} }
if (stringArg('flavor') != null && !integrationTestDevice.supportsFlavors) {
throwToolExit('--flavor is only supported for Android, macOS, and iOS devices.');
}
} }
final Stopwatch? testRunnerTimeRecorderStopwatch = testTimeRecorder?.start(TestTimePhases.TestRunner); final Stopwatch? testRunnerTimeRecorderStopwatch = testTimeRecorder?.start(TestTimePhases.TestRunner);
......
...@@ -758,6 +758,9 @@ abstract class Device { ...@@ -758,6 +758,9 @@ abstract class Device {
/// Whether the device supports the '--fast-start' development mode. /// Whether the device supports the '--fast-start' development mode.
bool get supportsFastStart => false; bool get supportsFastStart => false;
/// Whether the Flavors feature ('--flavor') is supported for this device.
bool get supportsFlavors => false;
/// Stop an app package on the current device. /// Stop an app package on the current device.
/// ///
/// Specify [userIdentifier] to stop app installed to a profile (Android only). /// Specify [userIdentifier] to stop app installed to a profile (Android only).
......
...@@ -358,6 +358,9 @@ class IOSDevice extends Device { ...@@ -358,6 +358,9 @@ class IOSDevice extends Device {
@override @override
bool get supportsStartPaused => false; bool get supportsStartPaused => false;
@override
bool get supportsFlavors => true;
@override @override
Future<bool> isAppInstalled( Future<bool> isAppInstalled(
ApplicationPackage app, { ApplicationPackage app, {
......
...@@ -392,6 +392,9 @@ class IOSSimulator extends Device { ...@@ -392,6 +392,9 @@ class IOSSimulator extends Device {
@override @override
bool get supportsHotRestart => true; bool get supportsHotRestart => true;
@override
bool get supportsFlavors => true;
@override @override
Future<bool> get supportsHardwareRendering async => false; Future<bool> get supportsHardwareRendering async => false;
......
...@@ -47,6 +47,9 @@ class MacOSDevice extends DesktopDevice { ...@@ -47,6 +47,9 @@ class MacOSDevice extends DesktopDevice {
@override @override
String get name => 'macOS'; String get name => 'macOS';
@override
bool get supportsFlavors => true;
@override @override
Future<TargetPlatform> get targetPlatform async => TargetPlatform.darwin; Future<TargetPlatform> get targetPlatform async => TargetPlatform.darwin;
......
...@@ -48,6 +48,9 @@ class MacOSDesignedForIPadDevice extends DesktopDevice { ...@@ -48,6 +48,9 @@ class MacOSDesignedForIPadDevice extends DesktopDevice {
@override @override
bool isSupported() => _operatingSystemUtils.hostPlatform == HostPlatform.darwin_arm64; bool isSupported() => _operatingSystemUtils.hostPlatform == HostPlatform.darwin_arm64;
@override
bool get supportsFlavors => true;
@override @override
bool isSupportedForProject(FlutterProject flutterProject) { bool isSupportedForProject(FlutterProject flutterProject) {
return flutterProject.ios.existsSync() && _operatingSystemUtils.hostPlatform == HostPlatform.darwin_arm64; return flutterProject.ios.existsSync() && _operatingSystemUtils.hostPlatform == HostPlatform.darwin_arm64;
......
...@@ -90,6 +90,9 @@ class FlutterTesterDevice extends Device { ...@@ -90,6 +90,9 @@ class FlutterTesterDevice extends Device {
@override @override
bool supportsRuntimeMode(BuildMode buildMode) => buildMode == BuildMode.debug; bool supportsRuntimeMode(BuildMode buildMode) => buildMode == BuildMode.debug;
@override
bool get supportsFlavors => true;
@override @override
Future<TargetPlatform> get targetPlatform async => TargetPlatform.tester; Future<TargetPlatform> get targetPlatform async => TargetPlatform.tester;
......
...@@ -431,6 +431,35 @@ void main() { ...@@ -431,6 +431,35 @@ void main() {
Cache: () => Cache.test(processManager: FakeProcessManager.any()), Cache: () => Cache.test(processManager: FakeProcessManager.any()),
}); });
testUsingContext('fails when --flavor is used with an unsupported target platform', () async {
const List<String> runCommand = <String>[
'run',
'--no-pub',
'--no-hot',
'--flavor=vanilla',
'-d',
'all',
];
// Useful for test readability.
// ignore: avoid_redundant_argument_values
final FakeDevice deviceWithoutFlavorSupport = FakeDevice(supportsFlavors: false);
final FakeDevice deviceWithFlavorSupport = FakeDevice(supportsFlavors: true);
testDeviceManager.devices = <Device>[deviceWithoutFlavorSupport, deviceWithFlavorSupport];
await expectLater(
() => createTestCommandRunner(RunCommand()).run(runCommand),
throwsToolExit(
message: '--flavor is only supported for Android, macOS, and iOS devices.',
),
);
}, overrides: <Type, Generator>{
DeviceManager: () => testDeviceManager,
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
});
testUsingContext('forwards --uninstall-only to DebuggingOptions', () async { testUsingContext('forwards --uninstall-only to DebuggingOptions', () async {
final RunCommand command = RunCommand(); final RunCommand command = RunCommand();
final FakeDevice mockDevice = FakeDevice( final FakeDevice mockDevice = FakeDevice(
...@@ -1306,11 +1335,13 @@ class FakeDevice extends Fake implements Device { ...@@ -1306,11 +1335,13 @@ class FakeDevice extends Fake implements Device {
String sdkNameAndVersion = '', String sdkNameAndVersion = '',
PlatformType platformType = PlatformType.ios, PlatformType platformType = PlatformType.ios,
bool isSupported = true, bool isSupported = true,
bool supportsFlavors = false,
}): _isLocalEmulator = isLocalEmulator, }): _isLocalEmulator = isLocalEmulator,
_targetPlatform = targetPlatform, _targetPlatform = targetPlatform,
_sdkNameAndVersion = sdkNameAndVersion, _sdkNameAndVersion = sdkNameAndVersion,
_platformType = platformType, _platformType = platformType,
_isSupported = isSupported; _isSupported = isSupported,
_supportsFlavors = supportsFlavors;
static const int kSuccess = 1; static const int kSuccess = 1;
static const int kFailure = -1; static const int kFailure = -1;
...@@ -1319,6 +1350,7 @@ class FakeDevice extends Fake implements Device { ...@@ -1319,6 +1350,7 @@ class FakeDevice extends Fake implements Device {
final String _sdkNameAndVersion; final String _sdkNameAndVersion;
final PlatformType _platformType; final PlatformType _platformType;
final bool _isSupported; final bool _isSupported;
final bool _supportsFlavors;
@override @override
Category get category => Category.mobile; Category get category => Category.mobile;
...@@ -1346,6 +1378,9 @@ class FakeDevice extends Fake implements Device { ...@@ -1346,6 +1378,9 @@ class FakeDevice extends Fake implements Device {
@override @override
bool get supportsFastStart => false; bool get supportsFastStart => false;
@override
bool get supportsFlavors => _supportsFlavors;
@override @override
bool get ephemeral => true; bool get ephemeral => true;
......
...@@ -864,8 +864,13 @@ dev_dependencies: ...@@ -864,8 +864,13 @@ dev_dependencies:
FileSystem: () => fs, FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => _FakeDeviceManager(<Device>[ DeviceManager: () => _FakeDeviceManager(<Device>[
FakeDevice('ephemeral', 'ephemeral', type: PlatformType.android), FakeDevice(
]), 'ephemeral',
'ephemeral',
type: PlatformType.android,
supportsFlavors: true,
),
]),
}); });
testUsingContext('Builds the asset manifest by default', () async { testUsingContext('Builds the asset manifest by default', () async {
......
...@@ -1164,7 +1164,12 @@ void main() { ...@@ -1164,7 +1164,12 @@ void main() {
fileSystem.file('pubspec.yaml').createSync(); fileSystem.file('pubspec.yaml').createSync();
fileSystem.file('.packages').createSync(); fileSystem.file('.packages').createSync();
final FakeDevice device = FakeDevice('name', 'id'); final FakeDevice device = FakeDevice(
'name',
'id',
type: PlatformType.android,
supportsFlavors: true,
);
testDeviceManager.devices = <Device>[device]; testDeviceManager.devices = <Device>[device];
final _TestRunCommandThatOnlyValidates command = _TestRunCommandThatOnlyValidates(); final _TestRunCommandThatOnlyValidates command = _TestRunCommandThatOnlyValidates();
final CommandRunner<void> runner = createTestCommandRunner(command); final CommandRunner<void> runner = createTestCommandRunner(command);
...@@ -1190,7 +1195,12 @@ void main() { ...@@ -1190,7 +1195,12 @@ void main() {
fileSystem.file('.packages').createSync(); fileSystem.file('.packages').createSync();
fileSystem.file('config.json')..createSync()..writeAsStringSync('{"FLUTTER_APP_FLAVOR": "strawberry"}'); fileSystem.file('config.json')..createSync()..writeAsStringSync('{"FLUTTER_APP_FLAVOR": "strawberry"}');
final FakeDevice device = FakeDevice('name', 'id'); final FakeDevice device = FakeDevice(
'name',
'id',
type: PlatformType.android,
supportsFlavors: true,
);
testDeviceManager.devices = <Device>[device]; testDeviceManager.devices = <Device>[device];
final _TestRunCommandThatOnlyValidates command = _TestRunCommandThatOnlyValidates(); final _TestRunCommandThatOnlyValidates command = _TestRunCommandThatOnlyValidates();
final CommandRunner<void> runner = createTestCommandRunner(command); final CommandRunner<void> runner = createTestCommandRunner(command);
......
...@@ -119,9 +119,11 @@ class FakeDevice extends Device { ...@@ -119,9 +119,11 @@ class FakeDevice extends Device {
PlatformType type = PlatformType.web, PlatformType type = PlatformType.web,
LaunchResult? launchResult, LaunchResult? launchResult,
this.deviceLogReader, this.deviceLogReader,
bool supportsFlavors = false,
}) : _isSupported = isSupported, }) : _isSupported = isSupported,
_isSupportedForProject = isSupportedForProject, _isSupportedForProject = isSupportedForProject,
_launchResult = launchResult ?? LaunchResult.succeeded(), _launchResult = launchResult ?? LaunchResult.succeeded(),
_supportsFlavors = supportsFlavors,
super( super(
id, id,
platformType: type, platformType: type,
...@@ -131,6 +133,7 @@ class FakeDevice extends Device { ...@@ -131,6 +133,7 @@ class FakeDevice extends Device {
final bool _isSupported; final bool _isSupported;
final bool _isSupportedForProject; final bool _isSupportedForProject;
final bool _supportsFlavors;
final LaunchResult _launchResult; final LaunchResult _launchResult;
DeviceLogReader? deviceLogReader; DeviceLogReader? deviceLogReader;
...@@ -174,6 +177,9 @@ class FakeDevice extends Device { ...@@ -174,6 +177,9 @@ class FakeDevice extends Device {
@override @override
bool isSupported() => _isSupported; bool isSupported() => _isSupported;
@override
bool get supportsFlavors => _supportsFlavors;
@override @override
bool isConnected; bool isConnected;
......
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