mirror of
https://github.com/Lakr233/vphone-cli.git
synced 2026-04-04 20:39:05 +08:00
boot: add --install-ipa auto-install option (#236)
This commit is contained in:
@@ -13,6 +13,7 @@ class VPhoneAppDelegate: NSObject, NSApplicationDelegate {
|
||||
private var appWindowController: VPhoneAppWindowController?
|
||||
private var locationProvider: VPhoneLocationProvider?
|
||||
private var sigintSource: DispatchSourceSignal?
|
||||
private var didAttemptAutoInstall = false
|
||||
|
||||
init(cli: VPhoneBootCLI) {
|
||||
self.cli = cli
|
||||
@@ -154,6 +155,9 @@ class VPhoneAppDelegate: NSObject, NSApplicationDelegate {
|
||||
}
|
||||
mc?.syncBatteryFromHost()
|
||||
mc?.syncLowPowerModeFromHost()
|
||||
Task { @MainActor [weak self] in
|
||||
await self?.installPackageIfRequested(caps: caps)
|
||||
}
|
||||
}
|
||||
control.onDisconnect = { [weak mc, weak provider = locationProvider] in
|
||||
mc?.updateConnectAvailability(available: false)
|
||||
@@ -174,6 +178,9 @@ class VPhoneAppDelegate: NSObject, NSApplicationDelegate {
|
||||
} else {
|
||||
print("[location] guest does not support location simulation")
|
||||
}
|
||||
Task { @MainActor [weak self] in
|
||||
await self?.installPackageIfRequested(caps: caps)
|
||||
}
|
||||
}
|
||||
control.onDisconnect = { [weak provider = locationProvider] in
|
||||
provider?.stopReplay()
|
||||
@@ -182,6 +189,42 @@ class VPhoneAppDelegate: NSObject, NSApplicationDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func installPackageIfRequested(caps: [String]) async {
|
||||
guard !didAttemptAutoInstall else { return }
|
||||
guard let packageURL = cli.installPackageURL else { return }
|
||||
|
||||
guard FileManager.default.fileExists(atPath: packageURL.path) else {
|
||||
didAttemptAutoInstall = true
|
||||
print("[install] requested package not found: \(packageURL.path)")
|
||||
return
|
||||
}
|
||||
guard VPhoneInstallPackage.isSupportedFile(packageURL) else {
|
||||
didAttemptAutoInstall = true
|
||||
print("[install] unsupported package type: \(packageURL.path)")
|
||||
return
|
||||
}
|
||||
guard caps.contains("ipa_install") else {
|
||||
print(
|
||||
"[install] guest does not advertise ipa_install; reconnect or reboot the guest so the updated daemon can take over"
|
||||
)
|
||||
return
|
||||
}
|
||||
guard let control else {
|
||||
print("[install] control channel is not ready")
|
||||
return
|
||||
}
|
||||
|
||||
didAttemptAutoInstall = true
|
||||
print("[install] auto-installing \(packageURL.lastPathComponent)")
|
||||
do {
|
||||
let result = try await control.installIPA(localURL: packageURL)
|
||||
print("[install] \(result)")
|
||||
} catch {
|
||||
print("[install] failed: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func applicationShouldTerminateAfterLastWindowClosed(_: NSApplication) -> Bool {
|
||||
!cli.noGraphics
|
||||
}
|
||||
|
||||
@@ -44,11 +44,21 @@ struct VPhoneBootCLI: ParsableCommand {
|
||||
@Option(help: "Path to signed vphoned binary for guest auto-update")
|
||||
var vphonedBin: String = ".vphoned.signed"
|
||||
|
||||
@Option(
|
||||
help: "Automatically install the given IPA/TIPA after the guest control channel connects.",
|
||||
transform: URL.init(fileURLWithPath:)
|
||||
)
|
||||
var installIPA: URL?
|
||||
|
||||
/// DFU mode runs headless (no GUI).
|
||||
var noGraphics: Bool {
|
||||
dfu
|
||||
}
|
||||
|
||||
var installPackageURL: URL? {
|
||||
installIPA?.standardizedFileURL
|
||||
}
|
||||
|
||||
/// Resolve final options by merging manifest values.
|
||||
func resolveOptions() throws -> VPhoneVirtualMachine.Options {
|
||||
let manifest = try VPhoneVirtualMachineManifest.load(from: config)
|
||||
|
||||
Reference in New Issue
Block a user