From 29eb6f6c21863f50f3a73543cc60af2269bf6169 Mon Sep 17 00:00:00 2001 From: Hidenori Matsubayashi Date: Wed, 28 Jul 2021 10:51:37 +0900 Subject: [PATCH] Add install/uninstall to/from remote devices (#25) --- lib/elinux_device.dart | 73 +++++++++++++++++++++++++++++--- lib/elinux_device_discovery.dart | 3 ++ lib/elinux_package.dart | 20 +++++++++ 3 files changed, 91 insertions(+), 5 deletions(-) diff --git a/lib/elinux_device.dart b/lib/elinux_device.dart index b8f95c7..7a21843 100644 --- a/lib/elinux_device.dart +++ b/lib/elinux_device.dart @@ -13,8 +13,10 @@ import 'package:flutter_tools/src/android/android_device.dart'; import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/logger.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/convert.dart'; +import 'package:flutter_tools/src/custom_devices/custom_device.dart'; import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/device_port_forwarder.dart'; import 'package:flutter_tools/src/project.dart'; @@ -25,6 +27,7 @@ import 'package:process/process.dart'; import 'elinux_builder.dart'; import 'elinux_package.dart'; +import 'elinux_remote_device_config.dart'; /// eLinux device implementation. /// @@ -32,6 +35,7 @@ import 'elinux_package.dart'; class ELinuxDevice extends Device { ELinuxDevice( String id, { + @required ELinuxRemoteDeviceConfig config, @required bool desktop, @required String backendType, @required String targetArch, @@ -39,24 +43,29 @@ class ELinuxDevice extends Device { @required Logger logger, @required ProcessManager processManager, @required OperatingSystemUtils operatingSystemUtils, - }) : _desktop = desktop, + }) : _config = config, + _desktop = desktop, _backendType = backendType, _targetArch = targetArch, _sdkNameAndVersion = sdkNameAndVersion, _logger = logger, _processManager = processManager, + _processUtils = + ProcessUtils(processManager: processManager, logger: logger), _operatingSystemUtils = operatingSystemUtils, super(id, category: desktop ? Category.desktop : Category.mobile, platformType: PlatformType.custom, ephemeral: true); + final ELinuxRemoteDeviceConfig _config; final bool _desktop; final String _backendType; final String _targetArch; final String _sdkNameAndVersion; final Logger _logger; final ProcessManager _processManager; + final ProcessUtils _processUtils; final OperatingSystemUtils _operatingSystemUtils; final Set _runningProcesses = {}; final ELinuxLogReader _logReader = ELinuxLogReader(); @@ -88,22 +97,31 @@ class ELinuxDevice extends Device { @override Future isAppInstalled(ELinuxApp app, {String userIdentifier}) async { - return true; + return false; } @override Future isLatestBuildInstalled(ELinuxApp app) async { - return true; + return false; } @override Future installApp(ELinuxApp app, {String userIdentifier}) async { - return true; + if (!await tryUninstall(appName: app.name)) { + return false; + } + + final String bundlePath = + app.outputDirectory(BuildMode.fromName('debug'), _targetArch); + final bool result = + await tryInstall(localPath: bundlePath, appName: app.name); + + return result; } @override Future uninstallApp(ELinuxApp app, {String userIdentifier}) async { - return true; + return tryUninstall(appName: app.name); } /// Source: [AndroidDevice.startApp] in `android_device.dart` @@ -337,6 +355,51 @@ class ELinuxDevice extends Device { finish(); return environment; } + + /// Source: [tryUninstall] in `custom_device.dart` + Future tryUninstall( + {@required String appName, + Duration timeout, + Map additionalReplacementValues = + const {}}) async { + final List interpolated = interpolateCommand( + _config.uninstallCommand, {'appName': appName}, + additionalReplacementValues: additionalReplacementValues); + + try { + await _processUtils.run(interpolated, + throwOnError: true, timeout: timeout); + _logger.printStatus('Uninstallation Success: $appName'); + return true; + } on ProcessException catch (e) { + _logger.printError( + 'Error executing uninstall command for custom device $id: $e'); + return false; + } + } + + /// Source: [tryInstall] in `custom_device.dart` + Future tryInstall( + {@required String localPath, + @required String appName, + Duration timeout, + Map additionalReplacementValues = + const {}}) async { + final List interpolated = interpolateCommand(_config.installCommand, + {'localPath': localPath, 'appName': appName}, + additionalReplacementValues: additionalReplacementValues); + + try { + await _processUtils.run(interpolated, + throwOnError: true, timeout: timeout); + _logger.printStatus('Installation Success: $appName ($localPath)'); + return true; + } on ProcessException catch (e) { + _logger.printError( + 'Error executing install command for custom device $id: $e'); + return false; + } + } } class ELinuxLogReader extends DeviceLogReader { diff --git a/lib/elinux_device_discovery.dart b/lib/elinux_device_discovery.dart index 505dc5a..a3df0f3 100644 --- a/lib/elinux_device_discovery.dart +++ b/lib/elinux_device_discovery.dart @@ -122,6 +122,7 @@ class ELinuxDeviceDiscovery extends PollingDeviceDiscovery { // Adds current desktop host. devices.add( ELinuxDevice('elinux-wayland', + config: null, desktop: true, targetArch: _getCurrentHostPlatformArchName(), backendType: 'wayland', @@ -136,6 +137,7 @@ class ELinuxDeviceDiscovery extends PollingDeviceDiscovery { ); devices.add( ELinuxDevice('elinux-x11', + config: null, desktop: true, targetArch: _getCurrentHostPlatformArchName(), backendType: 'x11', @@ -169,6 +171,7 @@ class ELinuxDeviceDiscovery extends PollingDeviceDiscovery { if (result.exitCode == 0 && stdout.contains(remoteDevice.pingSuccessRegex)) { final ELinuxDevice device = ELinuxDevice(remoteDevice.id, + config: remoteDevice, desktop: false, targetArch: remoteDevice.platform, backendType: remoteDevice.backend, diff --git a/lib/elinux_package.dart b/lib/elinux_package.dart index 77fa10b..0c7b164 100644 --- a/lib/elinux_package.dart +++ b/lib/elinux_package.dart @@ -56,6 +56,7 @@ abstract class ELinuxApp extends ApplicationPackage { factory ELinuxApp.fromPrebuiltApp(FileSystemEntity applicationBinary) { return PrebuiltELinuxApp( executable: applicationBinary.path, + outputDirectory: applicationBinary.path, ); } @@ -63,19 +64,28 @@ abstract class ELinuxApp extends ApplicationPackage { String get displayName => id; String executable(BuildMode buildMode, String targetArch); + + String outputDirectory(BuildMode buildMode, String targetArch); } class PrebuiltELinuxApp extends ELinuxApp { PrebuiltELinuxApp({ @required String executable, + @required String outputDirectory, }) : _executable = executable, + _outputDirectory = outputDirectory, super(projectBundleId: executable); final String _executable; + final String _outputDirectory; @override String executable(BuildMode buildMode, String targetArch) => _executable; + @override + String outputDirectory(BuildMode buildMode, String targetArch) => + _outputDirectory; + @override String get name => _executable; } @@ -98,6 +108,16 @@ class BuildableELinuxApp extends ELinuxApp { ); } + @override + String outputDirectory(BuildMode buildMode, String targetArch) { + return globals.fs.path.join( + 'build/elinux/', + targetArch, + getNameForBuildMode(buildMode), + 'bundle', + ); + } + @override String get name => project.parent.manifest.appName; }