diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 89be0142..35088205 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -359,7 +359,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 274; + CURRENT_PROJECT_VERSION = 280; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; @@ -367,7 +367,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.274; + MARKETING_VERSION = 1.0.280; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -490,7 +490,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 274; + CURRENT_PROJECT_VERSION = 280; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; @@ -498,7 +498,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.274; + MARKETING_VERSION = 1.0.280; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -515,7 +515,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 274; + CURRENT_PROJECT_VERSION = 280; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; @@ -523,7 +523,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.274; + MARKETING_VERSION = 1.0.280; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; diff --git a/lib/data/model/pkg/manager.dart b/lib/data/model/pkg/manager.dart index 69325a59..09c9d0d7 100644 --- a/lib/data/model/pkg/manager.dart +++ b/lib/data/model/pkg/manager.dart @@ -1 +1,119 @@ -enum PkgManager { apt, yum, zypper, pacman, opkg } +import 'package:toolbox/data/model/server/dist.dart'; + +enum PkgManager { + apt, + yum, + zypper, + pacman, + opkg, + apk; + + String? get listUpdate { + switch (this) { + case PkgManager.yum: + return 'yum check-update'; + case PkgManager.apt: + return 'apt list --upgradeable'; + case PkgManager.zypper: + return 'zypper lu'; + case PkgManager.pacman: + return 'pacman -Qu'; + case PkgManager.opkg: + return 'opkg list-upgradable'; + case PkgManager.apk: + return 'apk list --upgradable'; + default: + return null; + } + } + + String? get update { + switch (this) { + case PkgManager.apt: + return 'apt update'; + case PkgManager.pacman: + return 'pacman -Sy'; + case PkgManager.opkg: + return 'opkg update'; + case PkgManager.apk: + return 'apk update'; + default: + return null; + } + } + + String? upgrade(String args) { + switch (this) { + case PkgManager.yum: + return 'yum upgrade -y'; + case PkgManager.apt: + return 'apt upgrade -y'; + case PkgManager.zypper: + return 'zypper up -y'; + case PkgManager.pacman: + return 'pacman -Syu --noconfirm'; + case PkgManager.opkg: + return 'opkg upgrade $args'; + case PkgManager.apk: + return 'apk upgrade'; + default: + return null; + } + } + + List updateListRemoveUnused(List list) { + switch (this) { + case PkgManager.yum: + list = list.sublist(2); + list.removeWhere((element) => element.isEmpty); + final endLine = list.lastIndexWhere( + (element) => element.contains('Obsoleting Packages')); + list = list.sublist(0, endLine); + break; + case PkgManager.apt: + // avoid other outputs + // such as: [Could not chdir to home directory /home/test: No such file or directory, , WARNING: apt does not have a stable CLI interface. Use with caution in scripts., , Listing...] + final idx = + list.indexWhere((element) => element.contains('[upgradable from:')); + if (idx == -1) { + return []; + } + list = list.sublist(idx); + list.removeWhere((element) => element.isEmpty); + break; + case PkgManager.zypper: + list = list.sublist(4); + break; + case PkgManager.pacman: + case PkgManager.opkg: + case PkgManager.apk: + break; + } + list.removeWhere((element) => element.isEmpty); + return list; + } +} + +PkgManager? fromDist(Dist? dist) { + switch (dist) { + case Dist.centos: + case Dist.rocky: + case Dist.fedora: + return PkgManager.yum; + case Dist.debian: + case Dist.ubuntu: + case Dist.kali: + case Dist.armbian: + return PkgManager.apt; + case Dist.opensuse: + return PkgManager.zypper; + case Dist.wrt: + return PkgManager.opkg; + case Dist.arch: + return PkgManager.pacman; + case Dist.alpine: + return PkgManager.apk; + default: + return null; + } +} diff --git a/lib/data/model/pkg/upgrade_info.dart b/lib/data/model/pkg/upgrade_info.dart index c4c9202d..409778e8 100644 --- a/lib/data/model/pkg/upgrade_info.dart +++ b/lib/data/model/pkg/upgrade_info.dart @@ -25,6 +25,9 @@ class UpgradePkgInfo { case PkgManager.opkg: _parseOpkg(raw); break; + case PkgManager.apk: + _parseApk(raw); + break; default: throw Exception('Unsupported pkg type: $_mgr'); } @@ -72,4 +75,15 @@ class UpgradePkgInfo { newVersion = parts[2]; arch = ''; } + + // libcrypto3-3.0.8-r4 x86_64 {openssl} (Apache-2.0) [upgradable from: libcrypto3-3.0.8-r3] + void _parseApk(String raw) { + final parts = raw.split(' '); + final len = parts.length; + newVersion = parts[len - 1]; + nowVersion = parts[0]; + newVersion = newVersion.substring(0, newVersion.length - 1); + package = nowVersion; + arch = parts[1]; + } } diff --git a/lib/data/provider/pkg.dart b/lib/data/provider/pkg.dart index 269628a2..6aa807e4 100644 --- a/lib/data/provider/pkg.dart +++ b/lib/data/provider/pkg.dart @@ -29,45 +29,23 @@ class PkgProvider extends BusyProvider { String lastLog = ''; bool isRequestingPwd = false; - PkgProvider(); - Future init( - SSHClient client, - Dist? dist, - Function() onUpgrade, - Function() onUpdate, - PwdRequestFunc onPasswordRequest, - String user) async { + SSHClient client, + Dist? dist, + Function() onUpgrade, + Function() onUpdate, + PwdRequestFunc onPasswordRequest, + String user, + ) async { this.client = client; this.dist = dist; this.onUpgrade = onUpgrade; this.onPasswordRequest = onPasswordRequest; whoami = user; - switch (dist) { - case Dist.centos: - case Dist.rocky: - case Dist.fedora: - type = PkgManager.yum; - break; - case Dist.debian: - case Dist.ubuntu: - case Dist.kali: - case Dist.armbian: - type = PkgManager.apt; - break; - case Dist.opensuse: - type = PkgManager.zypper; - break; - case Dist.wrt: - type = PkgManager.opkg; - break; - case Dist.arch: - type = PkgManager.pacman; - break; - case null: - error = 'Unsupported dist: $dist'; - break; + type = fromDist(dist); + if (type == null) { + error = 'Unsupported dist: $dist'; } } @@ -80,9 +58,9 @@ class PkgProvider extends BusyProvider { } Future refresh() async { - final result = await _update(); + final result = await _update();_parse(result); try { - _parse(result); + } catch (e) { error = '[Server Raw]:\n$result\n[App Error]:\n$e'; } finally { @@ -92,87 +70,37 @@ class PkgProvider extends BusyProvider { void _parse(String? raw) { if (raw == null) return; - var list = raw.split('\n'); - switch (type) { - case PkgManager.yum: - list = list.sublist(2); - list.removeWhere((element) => element.isEmpty); - final endLine = list.lastIndexWhere( - (element) => element.contains('Obsoleting Packages')); - list = list.sublist(0, endLine); - break; - case PkgManager.apt: - // avoid other outputs - // such as: [Could not chdir to home directory /home/test: No such file or directory, , WARNING: apt does not have a stable CLI interface. Use with caution in scripts., , Listing...] - final idx = - list.indexWhere((element) => element.contains('[upgradable from:')); - if (idx == -1) { - upgradeable = []; - return; - } - list = list.sublist(idx); - list.removeWhere((element) => element.isEmpty); - break; - case PkgManager.zypper: - list = list.sublist(4); - break; - case PkgManager.pacman: - case PkgManager.opkg: - break; - default: - return; - } - upgradeable = list.map((e) => UpgradePkgInfo(e, type)).toList(); + final list = type + ?.updateListRemoveUnused(raw.split('\n')); + upgradeable = list + ?.map((e) => UpgradePkgInfo(e, type)) + .toList(); } Future _update() async { - switch (type) { - case PkgManager.yum: - return await client?.run(_wrap('yum check-update')).string; - case PkgManager.apt: - await client!.exec( - _wrap('apt update'), - onStderr: _onPwd, - onStdout: (data, sink) { - updateLog = (updateLog ?? '') + data; - notifyListeners(); - if (onUpdate != null) onUpdate!(); - }, - ); - return await client - ?.run('apt list --upgradeable'.withLangExport) - .string; - case PkgManager.zypper: - return await client?.run(_wrap('zypper lu')).string; - case PkgManager.pacman: - await client?.run('pacman -Sy'); - return await client?.run(_wrap('pacman -Qu')).string; - case PkgManager.opkg: - await client?.run('opkg update'); - return await client?.run(_wrap('opkg list-upgradable')).string; - default: - error = 'Unsupported dist: $dist'; - return null; + final updateCmd = type?.update; + if (updateCmd != null) { + await client!.exec( + _wrap(updateCmd), + onStderr: _onPwd, + onStdout: (data, sink) { + updateLog = (updateLog ?? '') + data; + if (onUpdate != null) onUpdate!(); + notifyListeners(); + }, + ); } + final listCmd = type?.listUpdate; + if (listCmd == null) { + error = 'Unsupported dist: $dist'; + return null; + } + return await client?.run(_wrap(listCmd)).string; } Future upgrade() async { - final upgradeCmd = () { - switch (type) { - case PkgManager.yum: - return 'yum upgrade -y'; - case PkgManager.apt: - return 'apt upgrade -y'; - case PkgManager.zypper: - return 'zypper up -y'; - case PkgManager.pacman: - return 'pacman -Syu --noconfirm'; - case PkgManager.opkg: - return 'opkg upgrade ${upgradeable?.map((e) => e.package).join(" ")}'; - default: - return null; - } - }(); + final upgradeCmd = + type?.upgrade(upgradeable?.map((e) => e.package).join(" ") ?? ''); if (upgradeCmd == null) { error = 'Unsupported dist: $dist'; diff --git a/lib/data/res/build_data.dart b/lib/data/res/build_data.dart index 1a91fbc6..d0c035f1 100644 --- a/lib/data/res/build_data.dart +++ b/lib/data/res/build_data.dart @@ -2,8 +2,8 @@ class BuildData { static const String name = "ServerBox"; - static const int build = 274; + static const int build = 280; static const String engine = "3.7.11"; - static const String buildAt = "2023-04-23 14:25:48.263478"; + static const String buildAt = "2023-04-27 18:10:45.464081"; static const int modifications = 4; } diff --git a/lib/view/page/pkg.dart b/lib/view/page/pkg.dart index 9da8c9bb..2364132f 100644 --- a/lib/view/page/pkg.dart +++ b/lib/view/page/pkg.dart @@ -204,6 +204,7 @@ class _PkgManagePageState extends State overflow: TextOverflow.ellipsis, style: grey, ), + initiallyExpanded: true, children: apt.upgradeLog == null ? [ TextButton( @@ -225,11 +226,17 @@ class _PkgManagePageState extends State } Widget _buildUpdateItem(UpgradePkgInfo info, PkgProvider apt) { + final t = () { + if (info.nowVersion.isNotEmpty && info.newVersion.isNotEmpty) { + return '${info.nowVersion} -> ${info.newVersion}'; + } + return info.newVersion; + }(); return ListTile( title: Text(info.package), subtitle: Text( - '${info.nowVersion} -> ${info.newVersion}', - style: grey, + t, + style: grey ), ); }