Add device discovery and custom-devices (#14)
Fixed Discovery remote devices #12
This commit is contained in:
@@ -35,23 +35,26 @@ class ELinuxDevice extends Device {
|
|||||||
@required bool desktop,
|
@required bool desktop,
|
||||||
@required String backendType,
|
@required String backendType,
|
||||||
@required String targetArch,
|
@required String targetArch,
|
||||||
|
String sdkNameAndVersion = '',
|
||||||
@required Logger logger,
|
@required Logger logger,
|
||||||
@required ProcessManager processManager,
|
@required ProcessManager processManager,
|
||||||
@required OperatingSystemUtils operatingSystemUtils,
|
@required OperatingSystemUtils operatingSystemUtils,
|
||||||
}) : _desktop = desktop,
|
}) : _desktop = desktop,
|
||||||
_backendType = backendType,
|
_backendType = backendType,
|
||||||
_targetArch = targetArch,
|
_targetArch = targetArch,
|
||||||
|
_sdkNameAndVersion = sdkNameAndVersion,
|
||||||
_logger = logger,
|
_logger = logger,
|
||||||
_processManager = processManager,
|
_processManager = processManager,
|
||||||
_operatingSystemUtils = operatingSystemUtils,
|
_operatingSystemUtils = operatingSystemUtils,
|
||||||
super(id,
|
super(id,
|
||||||
category: Category.desktop,
|
category: desktop ? Category.desktop : Category.mobile,
|
||||||
platformType: PlatformType.custom,
|
platformType: PlatformType.custom,
|
||||||
ephemeral: true);
|
ephemeral: true);
|
||||||
|
|
||||||
final bool _desktop;
|
final bool _desktop;
|
||||||
final String _backendType;
|
final String _backendType;
|
||||||
final String _targetArch;
|
final String _targetArch;
|
||||||
|
final String _sdkNameAndVersion;
|
||||||
final Logger _logger;
|
final Logger _logger;
|
||||||
final ProcessManager _processManager;
|
final ProcessManager _processManager;
|
||||||
final OperatingSystemUtils _operatingSystemUtils;
|
final OperatingSystemUtils _operatingSystemUtils;
|
||||||
@@ -77,7 +80,8 @@ class ELinuxDevice extends Device {
|
|||||||
buildMode != BuildMode.jitRelease;
|
buildMode != BuildMode.jitRelease;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String> get sdkNameAndVersion async => _operatingSystemUtils.name;
|
Future<String> get sdkNameAndVersion async =>
|
||||||
|
_desktop ? _operatingSystemUtils.name : _sdkNameAndVersion;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get name => 'eLinux';
|
String get name => 'eLinux';
|
||||||
|
|||||||
@@ -6,11 +6,14 @@
|
|||||||
|
|
||||||
// @dart = 2.8
|
// @dart = 2.8
|
||||||
|
|
||||||
import 'package:flutter_tools/src/android/android_device_discovery.dart';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter_tools/src/android/android_workflow.dart';
|
import 'package:flutter_tools/src/android/android_workflow.dart';
|
||||||
|
import 'package:flutter_tools/src/base/common.dart';
|
||||||
import 'package:flutter_tools/src/base/context.dart';
|
import 'package:flutter_tools/src/base/context.dart';
|
||||||
import 'package:flutter_tools/src/base/logger.dart';
|
import 'package:flutter_tools/src/base/logger.dart';
|
||||||
import 'package:flutter_tools/src/base/os.dart';
|
import 'package:flutter_tools/src/base/os.dart';
|
||||||
|
import 'package:flutter_tools/src/base/process.dart';
|
||||||
import 'package:flutter_tools/src/build_info.dart';
|
import 'package:flutter_tools/src/build_info.dart';
|
||||||
import 'package:flutter_tools/src/context_runner.dart';
|
import 'package:flutter_tools/src/context_runner.dart';
|
||||||
import 'package:flutter_tools/src/custom_devices/custom_devices_config.dart';
|
import 'package:flutter_tools/src/custom_devices/custom_devices_config.dart';
|
||||||
@@ -27,6 +30,8 @@ import 'package:process/process.dart';
|
|||||||
|
|
||||||
import 'elinux_device.dart';
|
import 'elinux_device.dart';
|
||||||
import 'elinux_doctor.dart';
|
import 'elinux_doctor.dart';
|
||||||
|
import 'elinux_remote_device_config.dart';
|
||||||
|
import 'elinux_remote_devices_config.dart';
|
||||||
|
|
||||||
/// An extended [FlutterDeviceManager] for managing eLinux devices.
|
/// An extended [FlutterDeviceManager] for managing eLinux devices.
|
||||||
class ELinuxDeviceManager extends FlutterDeviceManager {
|
class ELinuxDeviceManager extends FlutterDeviceManager {
|
||||||
@@ -78,8 +83,6 @@ class ELinuxDeviceManager extends FlutterDeviceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Device discovery for eLinux devices.
|
/// Device discovery for eLinux devices.
|
||||||
///
|
|
||||||
/// Source: [AndroidDevices] in `android_device_discovery.dart`
|
|
||||||
class ELinuxDeviceDiscovery extends PollingDeviceDiscovery {
|
class ELinuxDeviceDiscovery extends PollingDeviceDiscovery {
|
||||||
ELinuxDeviceDiscovery({
|
ELinuxDeviceDiscovery({
|
||||||
@required ELinuxWorkflow eLinuxWorkflow,
|
@required ELinuxWorkflow eLinuxWorkflow,
|
||||||
@@ -88,11 +91,20 @@ class ELinuxDeviceDiscovery extends PollingDeviceDiscovery {
|
|||||||
}) : _eLinuxWorkflow = eLinuxWorkflow,
|
}) : _eLinuxWorkflow = eLinuxWorkflow,
|
||||||
_logger = logger,
|
_logger = logger,
|
||||||
_processManager = processManager,
|
_processManager = processManager,
|
||||||
|
_processUtils =
|
||||||
|
ProcessUtils(logger: logger, processManager: processManager),
|
||||||
|
_eLinuxRemoteDevicesConfig = ELinuxRemoteDevicesConfig(
|
||||||
|
platform: globals.platform,
|
||||||
|
fileSystem: globals.fs,
|
||||||
|
logger: logger,
|
||||||
|
),
|
||||||
super('eLinux devices');
|
super('eLinux devices');
|
||||||
|
|
||||||
final ELinuxWorkflow _eLinuxWorkflow;
|
final ELinuxWorkflow _eLinuxWorkflow;
|
||||||
final Logger _logger;
|
final Logger _logger;
|
||||||
final ProcessManager _processManager;
|
final ProcessManager _processManager;
|
||||||
|
final ProcessUtils _processUtils;
|
||||||
|
final ELinuxRemoteDevicesConfig _eLinuxRemoteDevicesConfig;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool get supportsPlatform => _eLinuxWorkflow.appliesToHostPlatform;
|
bool get supportsPlatform => _eLinuxWorkflow.appliesToHostPlatform;
|
||||||
@@ -106,8 +118,47 @@ class ELinuxDeviceDiscovery extends PollingDeviceDiscovery {
|
|||||||
return const <Device>[];
|
return const <Device>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Device>[
|
final List<ELinuxDevice> devices = <ELinuxDevice>[];
|
||||||
ELinuxDevice('eLinux',
|
|
||||||
|
// Adds remote devices.
|
||||||
|
for (final ELinuxRemoteDeviceConfig remoteDevice
|
||||||
|
in _eLinuxRemoteDevicesConfig.devices) {
|
||||||
|
if (!remoteDevice.enabled) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String stdout;
|
||||||
|
RunResult result;
|
||||||
|
try {
|
||||||
|
result = await _processUtils.run(remoteDevice.pingCommand,
|
||||||
|
throwOnError: true);
|
||||||
|
stdout = result.stdout.trim();
|
||||||
|
} on ProcessException catch (ex) {
|
||||||
|
throwToolExit('ping failed to list attached devices:\n$ex');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.exitCode == 0 &&
|
||||||
|
stdout.contains(remoteDevice.pingSuccessRegex)) {
|
||||||
|
final ELinuxDevice device = ELinuxDevice(remoteDevice.id,
|
||||||
|
desktop: false,
|
||||||
|
targetArch: remoteDevice.platform,
|
||||||
|
backendType: remoteDevice.backend,
|
||||||
|
sdkNameAndVersion: remoteDevice.sdkNameAndVersion,
|
||||||
|
logger: _logger ?? globals.logger,
|
||||||
|
processManager: _processManager ?? globals.processManager,
|
||||||
|
operatingSystemUtils: OperatingSystemUtils(
|
||||||
|
fileSystem: globals.fs,
|
||||||
|
logger: _logger ?? globals.logger,
|
||||||
|
platform: globals.platform,
|
||||||
|
processManager: const LocalProcessManager(),
|
||||||
|
));
|
||||||
|
devices.add(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds current desktop host.
|
||||||
|
devices.add(
|
||||||
|
ELinuxDevice('elinux',
|
||||||
desktop: true,
|
desktop: true,
|
||||||
targetArch: _getCurrentHostPlatformArchName(),
|
targetArch: _getCurrentHostPlatformArchName(),
|
||||||
backendType: 'wayland',
|
backendType: 'wayland',
|
||||||
@@ -119,7 +170,9 @@ class ELinuxDeviceDiscovery extends PollingDeviceDiscovery {
|
|||||||
platform: globals.platform,
|
platform: globals.platform,
|
||||||
processManager: const LocalProcessManager(),
|
processManager: const LocalProcessManager(),
|
||||||
)),
|
)),
|
||||||
];
|
);
|
||||||
|
|
||||||
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -0,0 +1,359 @@
|
|||||||
|
// Copyright 2021 Sony Group Corporation. All rights reserved.
|
||||||
|
// 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:meta/meta.dart';
|
||||||
|
|
||||||
|
/// See: [_listsEqual] in `custom_device_config.dart` (exact copy)
|
||||||
|
bool _listsEqual(List<dynamic>? a, List<dynamic>? b) {
|
||||||
|
if (a == b) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (a == null || b == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (a.length != b.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a
|
||||||
|
.asMap()
|
||||||
|
.entries
|
||||||
|
.every((MapEntry<int, dynamic> e) => e.value == b[e.key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See: [_regexesEqual] in `custom_device_config.dart` (exact copy)
|
||||||
|
bool _regexesEqual(RegExp? a, RegExp? b) {
|
||||||
|
if (a == b) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (a == null || b == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.pattern == b.pattern &&
|
||||||
|
a.isMultiLine == b.isMultiLine &&
|
||||||
|
a.isCaseSensitive == b.isCaseSensitive &&
|
||||||
|
a.isUnicode == b.isUnicode &&
|
||||||
|
a.isDotAll == b.isDotAll;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See: [CustomDeviceRevivalException] in `custom_device_config.dart`
|
||||||
|
@immutable
|
||||||
|
class ELinuxRemoteDeviceRevivalException implements Exception {
|
||||||
|
const ELinuxRemoteDeviceRevivalException(this.message);
|
||||||
|
|
||||||
|
const ELinuxRemoteDeviceRevivalException.fromDescriptions(
|
||||||
|
String fieldDescription, String expectedValueDescription)
|
||||||
|
: message = 'Expected $fieldDescription to be $expectedValueDescription.';
|
||||||
|
|
||||||
|
final String message;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return (other is ELinuxRemoteDeviceRevivalException) &&
|
||||||
|
(other.message == message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => message.hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See: [CustomDeviceConfig] in `custom_device_config.dart`
|
||||||
|
@immutable
|
||||||
|
class ELinuxRemoteDeviceConfig {
|
||||||
|
const ELinuxRemoteDeviceConfig(
|
||||||
|
{required this.id,
|
||||||
|
required this.label,
|
||||||
|
required this.sdkNameAndVersion,
|
||||||
|
this.platform = 'arm64',
|
||||||
|
this.backend = 'wayland',
|
||||||
|
required this.enabled,
|
||||||
|
required this.pingCommand,
|
||||||
|
this.pingSuccessRegex,
|
||||||
|
required this.postBuildCommand,
|
||||||
|
required this.installCommand,
|
||||||
|
required this.uninstallCommand,
|
||||||
|
required this.runDebugCommand,
|
||||||
|
this.forwardPortCommand,
|
||||||
|
this.forwardPortSuccessRegex,
|
||||||
|
this.screenshotCommand})
|
||||||
|
: assert(forwardPortCommand == null || forwardPortSuccessRegex != null);
|
||||||
|
|
||||||
|
factory ELinuxRemoteDeviceConfig.fromJson(dynamic json) {
|
||||||
|
final Map<String, dynamic> typedMap =
|
||||||
|
_castJsonObject(json, 'device configuration', 'a JSON object');
|
||||||
|
|
||||||
|
final List<String>? forwardPortCommand = _castStringListOrNull(
|
||||||
|
typedMap[_kForwardPortCommand],
|
||||||
|
_kForwardPortCommand,
|
||||||
|
'null or array of strings with at least one element',
|
||||||
|
minLength: 1);
|
||||||
|
|
||||||
|
final RegExp? forwardPortSuccessRegex = _convertToRegexOrNull(
|
||||||
|
typedMap[_kForwardPortSuccessRegex],
|
||||||
|
_kForwardPortSuccessRegex,
|
||||||
|
'null or string-ified regex');
|
||||||
|
|
||||||
|
if (forwardPortCommand != null && forwardPortSuccessRegex == null) {
|
||||||
|
throw const ELinuxRemoteDeviceRevivalException(
|
||||||
|
'When forwardPort is given, forwardPortSuccessRegex must be specified too.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return ELinuxRemoteDeviceConfig(
|
||||||
|
id: _castString(typedMap[_kId], _kId, 'a string'),
|
||||||
|
label: _castString(typedMap[_kLabel], _kLabel, 'a string'),
|
||||||
|
sdkNameAndVersion: _castString(
|
||||||
|
typedMap[_kSdkNameAndVersion], _kSdkNameAndVersion, 'a string'),
|
||||||
|
enabled: _castBool(typedMap[_kEnabled], _kEnabled, 'a boolean'),
|
||||||
|
platform: _castString(typedMap[_kPlatform], _kPlatform, 'arm64'),
|
||||||
|
backend: _castString(typedMap[_kBackend], _kBackend, 'wayland'),
|
||||||
|
pingCommand: _castStringList(typedMap[_kPingCommand], _kPingCommand,
|
||||||
|
'array of strings with at least one element', minLength: 1),
|
||||||
|
pingSuccessRegex: _convertToRegexOrNull(typedMap[_kPingSuccessRegex],
|
||||||
|
_kPingSuccessRegex, 'null or string-ified regex'),
|
||||||
|
postBuildCommand: _castStringListOrNull(
|
||||||
|
typedMap[_kPostBuildCommand],
|
||||||
|
_kPostBuildCommand,
|
||||||
|
'null or array of strings with at least one element',
|
||||||
|
minLength: 1,
|
||||||
|
),
|
||||||
|
installCommand: _castStringList(
|
||||||
|
typedMap[_kInstallCommand], _kInstallCommand, 'array of strings with at least one element',
|
||||||
|
minLength: 1),
|
||||||
|
uninstallCommand: _castStringList(typedMap[_kUninstallCommand],
|
||||||
|
_kUninstallCommand, 'array of strings with at least one element',
|
||||||
|
minLength: 1),
|
||||||
|
runDebugCommand: _castStringList(
|
||||||
|
typedMap[_kRunDebugCommand], _kRunDebugCommand, 'array of strings with at least one element',
|
||||||
|
minLength: 1),
|
||||||
|
forwardPortCommand: forwardPortCommand,
|
||||||
|
forwardPortSuccessRegex: forwardPortSuccessRegex,
|
||||||
|
screenshotCommand: _castStringListOrNull(typedMap[_kScreenshotCommand], _kScreenshotCommand, 'array of strings with at least one element', minLength: 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const String _kId = 'id';
|
||||||
|
static const String _kLabel = 'label';
|
||||||
|
static const String _kSdkNameAndVersion = 'sdkNameAndVersion';
|
||||||
|
static const String _kPlatform = 'platform';
|
||||||
|
static const String _kEnabled = 'enabled';
|
||||||
|
static const String _kBackend = 'backend';
|
||||||
|
static const String _kPingCommand = 'ping';
|
||||||
|
static const String _kPingSuccessRegex = 'pingSuccessRegex';
|
||||||
|
static const String _kPostBuildCommand = 'postBuild';
|
||||||
|
static const String _kInstallCommand = 'install';
|
||||||
|
static const String _kUninstallCommand = 'uninstall';
|
||||||
|
static const String _kRunDebugCommand = 'runDebug';
|
||||||
|
static const String _kForwardPortCommand = 'forwardPort';
|
||||||
|
static const String _kForwardPortSuccessRegex = 'forwardPortSuccessRegex';
|
||||||
|
static const String _kScreenshotCommand = 'screenshot';
|
||||||
|
|
||||||
|
final String id;
|
||||||
|
final String label;
|
||||||
|
final String sdkNameAndVersion;
|
||||||
|
final String? platform;
|
||||||
|
final String? backend;
|
||||||
|
final bool enabled;
|
||||||
|
final List<String> pingCommand;
|
||||||
|
final RegExp? pingSuccessRegex;
|
||||||
|
final List<String>? postBuildCommand;
|
||||||
|
final List<String> installCommand;
|
||||||
|
final List<String> uninstallCommand;
|
||||||
|
final List<String> runDebugCommand;
|
||||||
|
final List<String>? forwardPortCommand;
|
||||||
|
final RegExp? forwardPortSuccessRegex;
|
||||||
|
final List<String>? screenshotCommand;
|
||||||
|
|
||||||
|
bool get usesPortForwarding => forwardPortCommand != null;
|
||||||
|
|
||||||
|
bool get supportsScreenshotting => screenshotCommand != null;
|
||||||
|
|
||||||
|
static T _maybeRethrowAsRevivalException<T>(T Function() closure,
|
||||||
|
String fieldDescription, String expectedValueDescription) {
|
||||||
|
try {
|
||||||
|
return closure();
|
||||||
|
} on Object {
|
||||||
|
throw ELinuxRemoteDeviceRevivalException.fromDescriptions(
|
||||||
|
fieldDescription, expectedValueDescription);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, dynamic> _castJsonObject(
|
||||||
|
dynamic value, String fieldDescription, String expectedValueDescription) {
|
||||||
|
if (value == null) {
|
||||||
|
throw ELinuxRemoteDeviceRevivalException.fromDescriptions(
|
||||||
|
fieldDescription, expectedValueDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _maybeRethrowAsRevivalException(
|
||||||
|
() => Map<String, dynamic>.from(value as Map<dynamic, dynamic>),
|
||||||
|
fieldDescription,
|
||||||
|
expectedValueDescription,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _castBool(
|
||||||
|
dynamic value, String fieldDescription, String expectedValueDescription) {
|
||||||
|
if (value == null) {
|
||||||
|
throw ELinuxRemoteDeviceRevivalException.fromDescriptions(
|
||||||
|
fieldDescription, expectedValueDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _maybeRethrowAsRevivalException(
|
||||||
|
() => value as bool,
|
||||||
|
fieldDescription,
|
||||||
|
expectedValueDescription,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String _castString(
|
||||||
|
dynamic value, String fieldDescription, String expectedValueDescription) {
|
||||||
|
if (value == null) {
|
||||||
|
throw ELinuxRemoteDeviceRevivalException.fromDescriptions(
|
||||||
|
fieldDescription, expectedValueDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _maybeRethrowAsRevivalException(
|
||||||
|
() => value as String,
|
||||||
|
fieldDescription,
|
||||||
|
expectedValueDescription,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<String> _castStringList(
|
||||||
|
dynamic value,
|
||||||
|
String fieldDescription,
|
||||||
|
String expectedValueDescription, {
|
||||||
|
int minLength = 0,
|
||||||
|
}) {
|
||||||
|
if (value == null) {
|
||||||
|
throw ELinuxRemoteDeviceRevivalException.fromDescriptions(
|
||||||
|
fieldDescription, expectedValueDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<String> list = _maybeRethrowAsRevivalException(
|
||||||
|
() => List<String>.from(value as Iterable<dynamic>),
|
||||||
|
fieldDescription,
|
||||||
|
expectedValueDescription,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (list.length < minLength) {
|
||||||
|
throw ELinuxRemoteDeviceRevivalException.fromDescriptions(
|
||||||
|
fieldDescription, expectedValueDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<String>? _castStringListOrNull(
|
||||||
|
dynamic value,
|
||||||
|
String fieldDescription,
|
||||||
|
String expectedValueDescription, {
|
||||||
|
int minLength = 0,
|
||||||
|
}) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _castStringList(value, fieldDescription, expectedValueDescription,
|
||||||
|
minLength: minLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegExp? _convertToRegexOrNull(
|
||||||
|
dynamic value, String fieldDescription, String expectedValueDescription) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _maybeRethrowAsRevivalException(
|
||||||
|
() => RegExp(value as String),
|
||||||
|
fieldDescription,
|
||||||
|
expectedValueDescription,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object toJson() {
|
||||||
|
return <String, Object?>{
|
||||||
|
_kId: id,
|
||||||
|
_kLabel: label,
|
||||||
|
_kSdkNameAndVersion: sdkNameAndVersion,
|
||||||
|
_kPlatform: platform,
|
||||||
|
_kEnabled: enabled,
|
||||||
|
_kBackend: backend,
|
||||||
|
_kPingCommand: pingCommand,
|
||||||
|
_kPingSuccessRegex: pingSuccessRegex?.pattern,
|
||||||
|
_kPostBuildCommand: postBuildCommand,
|
||||||
|
_kInstallCommand: installCommand,
|
||||||
|
_kUninstallCommand: uninstallCommand,
|
||||||
|
_kRunDebugCommand: runDebugCommand,
|
||||||
|
_kForwardPortCommand: forwardPortCommand,
|
||||||
|
_kForwardPortSuccessRegex: forwardPortSuccessRegex?.pattern,
|
||||||
|
_kScreenshotCommand: screenshotCommand,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is ELinuxRemoteDeviceConfig &&
|
||||||
|
other.id == id &&
|
||||||
|
other.label == label &&
|
||||||
|
other.sdkNameAndVersion == sdkNameAndVersion &&
|
||||||
|
other.platform == platform &&
|
||||||
|
other.enabled == enabled &&
|
||||||
|
other.backend == backend &&
|
||||||
|
_listsEqual(other.pingCommand, pingCommand) &&
|
||||||
|
_regexesEqual(other.pingSuccessRegex, pingSuccessRegex) &&
|
||||||
|
_listsEqual(other.postBuildCommand, postBuildCommand) &&
|
||||||
|
_listsEqual(other.installCommand, installCommand) &&
|
||||||
|
_listsEqual(other.uninstallCommand, uninstallCommand) &&
|
||||||
|
_listsEqual(other.runDebugCommand, runDebugCommand) &&
|
||||||
|
_listsEqual(other.forwardPortCommand, forwardPortCommand) &&
|
||||||
|
_regexesEqual(other.forwardPortSuccessRegex, forwardPortSuccessRegex) &&
|
||||||
|
_listsEqual(other.screenshotCommand, screenshotCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return id.hashCode ^
|
||||||
|
label.hashCode ^
|
||||||
|
sdkNameAndVersion.hashCode ^
|
||||||
|
platform.hashCode ^
|
||||||
|
enabled.hashCode ^
|
||||||
|
backend.hashCode ^
|
||||||
|
pingCommand.hashCode ^
|
||||||
|
(pingSuccessRegex?.pattern).hashCode ^
|
||||||
|
postBuildCommand.hashCode ^
|
||||||
|
installCommand.hashCode ^
|
||||||
|
uninstallCommand.hashCode ^
|
||||||
|
runDebugCommand.hashCode ^
|
||||||
|
forwardPortCommand.hashCode ^
|
||||||
|
(forwardPortSuccessRegex?.pattern).hashCode ^
|
||||||
|
screenshotCommand.hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ELinuxDeviceConfig('
|
||||||
|
'id: $id, '
|
||||||
|
'label: $label, '
|
||||||
|
'sdkNameAndVersion: $sdkNameAndVersion, '
|
||||||
|
'platform: $platform, '
|
||||||
|
'enabled: $enabled, '
|
||||||
|
'backend: $backend, '
|
||||||
|
'pingCommand: $pingCommand, '
|
||||||
|
'pingSuccessRegex: $pingSuccessRegex, '
|
||||||
|
'postBuildCommand: $postBuildCommand, '
|
||||||
|
'installCommand: $installCommand, '
|
||||||
|
'uninstallCommand: $uninstallCommand, '
|
||||||
|
'runDebugCommand: $runDebugCommand, '
|
||||||
|
'forwardPortCommand: $forwardPortCommand, '
|
||||||
|
'forwardPortSuccessRegex: $forwardPortSuccessRegex, '
|
||||||
|
'screenshotCommand: $screenshotCommand)';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
// Copyright 2021 Sony Group Corporation. All rights reserved.
|
||||||
|
// 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_tools/src/base/config.dart';
|
||||||
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
|
import 'package:flutter_tools/src/base/logger.dart';
|
||||||
|
import 'package:flutter_tools/src/base/platform.dart';
|
||||||
|
import 'package:flutter_tools/src/cache.dart';
|
||||||
|
|
||||||
|
import 'elinux_remote_device_config.dart';
|
||||||
|
|
||||||
|
/// See: [CustomDevicesConfig] in `custom_devices_config.dart`
|
||||||
|
class ELinuxRemoteDevicesConfig {
|
||||||
|
ELinuxRemoteDevicesConfig({
|
||||||
|
required Platform platform,
|
||||||
|
required FileSystem fileSystem,
|
||||||
|
required Logger logger,
|
||||||
|
}) : _fileSystem = fileSystem,
|
||||||
|
_logger = logger,
|
||||||
|
_config = Config(_kCustomDevicesConfigName,
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
logger: logger,
|
||||||
|
platform: platform,
|
||||||
|
deleteFileOnFormatException: false) {
|
||||||
|
ensureFileExists();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const String _kCustomDevicesConfigName = 'custom_devices.json';
|
||||||
|
static const String _kCustomDevicesConfigKey = 'custom-devices';
|
||||||
|
static const String _kSchema = r'$schema';
|
||||||
|
static const String _kCustomDevices = 'custom-devices';
|
||||||
|
|
||||||
|
final FileSystem _fileSystem;
|
||||||
|
final Logger _logger;
|
||||||
|
final Config _config;
|
||||||
|
|
||||||
|
String get _defaultSchema {
|
||||||
|
final Uri uri = _fileSystem
|
||||||
|
.directory(Cache.flutterRoot)
|
||||||
|
.childDirectory('packages')
|
||||||
|
.childDirectory('flutter_tools')
|
||||||
|
.childDirectory('static')
|
||||||
|
.childFile('custom-devices.schema.json')
|
||||||
|
.uri;
|
||||||
|
assert(uri.isAbsolute);
|
||||||
|
return uri.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ensureFileExists() {
|
||||||
|
if (!_fileSystem.file(_config.configPath).existsSync()) {
|
||||||
|
_config.setValue(_kSchema, _defaultSchema);
|
||||||
|
_config.setValue(_kCustomDevices, <dynamic>[
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<dynamic>? _getDevicesJsonValue() {
|
||||||
|
final dynamic json = _config.getValue(_kCustomDevicesConfigKey);
|
||||||
|
if (json == null) {
|
||||||
|
return null;
|
||||||
|
} else if (json is! List) {
|
||||||
|
const String msg =
|
||||||
|
"Could not load custom devices config. config['$_kCustomDevicesConfigKey'] is not a JSON array.";
|
||||||
|
_logger.printError(msg);
|
||||||
|
throw const ELinuxRemoteDeviceRevivalException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ELinuxRemoteDeviceConfig> get devices {
|
||||||
|
final List<dynamic>? typedListNullable = _getDevicesJsonValue();
|
||||||
|
if (typedListNullable == null) {
|
||||||
|
return <ELinuxRemoteDeviceConfig>[];
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<dynamic> typedList = typedListNullable;
|
||||||
|
final List<ELinuxRemoteDeviceConfig> revived = <ELinuxRemoteDeviceConfig>[];
|
||||||
|
for (final MapEntry<int, dynamic> entry in typedList.asMap().entries) {
|
||||||
|
try {
|
||||||
|
revived.add(ELinuxRemoteDeviceConfig.fromJson(entry.value));
|
||||||
|
} on ELinuxRemoteDeviceRevivalException catch (e) {
|
||||||
|
final String msg =
|
||||||
|
'Could not load custom device from config index ${entry.key}: $e';
|
||||||
|
_logger.printError(msg);
|
||||||
|
throw ELinuxRemoteDeviceRevivalException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return revived;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ELinuxRemoteDeviceConfig> tryGetDevices() {
|
||||||
|
try {
|
||||||
|
return devices;
|
||||||
|
} on Exception {
|
||||||
|
return <ELinuxRemoteDeviceConfig>[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set devices(List<ELinuxRemoteDeviceConfig> configs) {
|
||||||
|
_config.setValue(
|
||||||
|
_kCustomDevicesConfigKey,
|
||||||
|
configs
|
||||||
|
.map<dynamic>((ELinuxRemoteDeviceConfig c) => c.toJson())
|
||||||
|
.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(ELinuxRemoteDeviceConfig config) {
|
||||||
|
_config.setValue(_kCustomDevicesConfigKey,
|
||||||
|
<dynamic>[...?_getDevicesJsonValue(), config.toJson()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(String deviceId) {
|
||||||
|
return devices
|
||||||
|
.any((ELinuxRemoteDeviceConfig device) => device.id == deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool remove(String deviceId) {
|
||||||
|
final List<ELinuxRemoteDeviceConfig> modifiedDevices = devices;
|
||||||
|
final ELinuxRemoteDeviceConfig? device = modifiedDevices
|
||||||
|
.cast<ELinuxRemoteDeviceConfig?>()
|
||||||
|
.firstWhere((ELinuxRemoteDeviceConfig? d) => d!.id == deviceId,
|
||||||
|
orElse: () => null);
|
||||||
|
|
||||||
|
if (device == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
modifiedDevices.remove(device);
|
||||||
|
devices = modifiedDevices;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String get configPath => _config.configPath;
|
||||||
|
|
||||||
|
void forEach(Null Function(int value) param0, void add) {}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user