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 {
@override
String get name => modelID;
@override
bool get supportsFlavors => true;
@override
Future<bool> isAppInstalled(
ApplicationPackage app, {
......
......@@ -610,6 +610,13 @@ class RunCommand extends RunCommandBase {
webMode = featureFlags.isWebEnabled &&
devices!.length == 1 &&
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
......
......@@ -469,6 +469,10 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
' 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);
......
......@@ -758,6 +758,9 @@ abstract class Device {
/// Whether the device supports the '--fast-start' development mode.
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.
///
/// Specify [userIdentifier] to stop app installed to a profile (Android only).
......
......@@ -358,6 +358,9 @@ class IOSDevice extends Device {
@override
bool get supportsStartPaused => false;
@override
bool get supportsFlavors => true;
@override
Future<bool> isAppInstalled(
ApplicationPackage app, {
......
......@@ -392,6 +392,9 @@ class IOSSimulator extends Device {
@override
bool get supportsHotRestart => true;
@override
bool get supportsFlavors => true;
@override
Future<bool> get supportsHardwareRendering async => false;
......
......@@ -47,6 +47,9 @@ class MacOSDevice extends DesktopDevice {
@override
String get name => 'macOS';
@override
bool get supportsFlavors => true;
@override
Future<TargetPlatform> get targetPlatform async => TargetPlatform.darwin;
......
......@@ -48,6 +48,9 @@ class MacOSDesignedForIPadDevice extends DesktopDevice {
@override
bool isSupported() => _operatingSystemUtils.hostPlatform == HostPlatform.darwin_arm64;
@override
bool get supportsFlavors => true;
@override
bool isSupportedForProject(FlutterProject flutterProject) {
return flutterProject.ios.existsSync() && _operatingSystemUtils.hostPlatform == HostPlatform.darwin_arm64;
......
......@@ -90,6 +90,9 @@ class FlutterTesterDevice extends Device {
@override
bool supportsRuntimeMode(BuildMode buildMode) => buildMode == BuildMode.debug;
@override
bool get supportsFlavors => true;
@override
Future<TargetPlatform> get targetPlatform async => TargetPlatform.tester;
......
......@@ -431,6 +431,35 @@ void main() {
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 {
final RunCommand command = RunCommand();
final FakeDevice mockDevice = FakeDevice(
......@@ -1306,11 +1335,13 @@ class FakeDevice extends Fake implements Device {
String sdkNameAndVersion = '',
PlatformType platformType = PlatformType.ios,
bool isSupported = true,
bool supportsFlavors = false,
}): _isLocalEmulator = isLocalEmulator,
_targetPlatform = targetPlatform,
_sdkNameAndVersion = sdkNameAndVersion,
_platformType = platformType,
_isSupported = isSupported;
_isSupported = isSupported,
_supportsFlavors = supportsFlavors;
static const int kSuccess = 1;
static const int kFailure = -1;
......@@ -1319,6 +1350,7 @@ class FakeDevice extends Fake implements Device {
final String _sdkNameAndVersion;
final PlatformType _platformType;
final bool _isSupported;
final bool _supportsFlavors;
@override
Category get category => Category.mobile;
......@@ -1346,6 +1378,9 @@ class FakeDevice extends Fake implements Device {
@override
bool get supportsFastStart => false;
@override
bool get supportsFlavors => _supportsFlavors;
@override
bool get ephemeral => true;
......
......@@ -864,8 +864,13 @@ dev_dependencies:
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
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 {
......
......@@ -1164,7 +1164,12 @@ void main() {
fileSystem.file('pubspec.yaml').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];
final _TestRunCommandThatOnlyValidates command = _TestRunCommandThatOnlyValidates();
final CommandRunner<void> runner = createTestCommandRunner(command);
......@@ -1190,7 +1195,12 @@ void main() {
fileSystem.file('.packages').createSync();
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];
final _TestRunCommandThatOnlyValidates command = _TestRunCommandThatOnlyValidates();
final CommandRunner<void> runner = createTestCommandRunner(command);
......
......@@ -119,9 +119,11 @@ class FakeDevice extends Device {
PlatformType type = PlatformType.web,
LaunchResult? launchResult,
this.deviceLogReader,
bool supportsFlavors = false,
}) : _isSupported = isSupported,
_isSupportedForProject = isSupportedForProject,
_launchResult = launchResult ?? LaunchResult.succeeded(),
_supportsFlavors = supportsFlavors,
super(
id,
platformType: type,
......@@ -131,6 +133,7 @@ class FakeDevice extends Device {
final bool _isSupported;
final bool _isSupportedForProject;
final bool _supportsFlavors;
final LaunchResult _launchResult;
DeviceLogReader? deviceLogReader;
......@@ -174,6 +177,9 @@ class FakeDevice extends Device {
@override
bool isSupported() => _isSupported;
@override
bool get supportsFlavors => _supportsFlavors;
@override
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