- MDMClient: error handling verbessert - SuperviseRunner: robustere EOF-nach-Success Erkennung - EnrollView: Enrollment-Status-Polling, Retry-Logik - SuperviseView: UX-Verbesserungen - ConfigureView: minor cleanup - flow_backup.go: backup flow für supervise-magic Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
65 lines
2.7 KiB
Swift
65 lines
2.7 KiB
Swift
import Foundation
|
|
|
|
/// Wrapper um das `rebreak-supervise-magic` Go-binary aus
|
|
/// `ops/mdm/supervise-magic/bin/`. Spawnt es als child-process + streamt
|
|
/// stdout zeilenweise in die UI.
|
|
enum SuperviseRunner {
|
|
enum RunnerError: Error, LocalizedError {
|
|
case binaryMissing
|
|
case nonZeroExit(Int32)
|
|
|
|
var errorDescription: String? {
|
|
switch self {
|
|
case .binaryMissing:
|
|
return "supervise-magic Binary nicht gefunden. Bitte aus `ops/mdm/supervise-magic/` via `make build` bauen oder REBREAK_SUPERVISE_MAGIC_BIN setzen."
|
|
case .nonZeroExit(let code):
|
|
return "supervise-magic ist mit Exit-Code \(code) abgebrochen."
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Pre-Flight Check: liest FMI/SDP-Status + IsSupervised.
|
|
/// Returnt das geparste output. Mit -v für detaillierte logs.
|
|
@MainActor
|
|
static func check(onLine: @escaping (String) -> Void) async throws -> ProcessRunner.Result {
|
|
guard let bin = Paths.firstExecutable(in: Paths.superviseMagicCandidates) else {
|
|
throw RunnerError.binaryMissing
|
|
}
|
|
return try await ProcessRunner.stream(bin, arguments: ["check", "-v"], onLine: onLine)
|
|
}
|
|
|
|
/// Schreibt CloudConfigurationDetails.plist auf das iPhone + reboot.
|
|
/// supervise-magic macht die ganze MobileBackup2-Sandwich-Logik.
|
|
@MainActor
|
|
static func supervise(
|
|
organizationName: String = "ReBreak",
|
|
force: Bool = true,
|
|
verbose: Bool = false,
|
|
onLine: @escaping (String) -> Void
|
|
) async throws -> ProcessRunner.Result {
|
|
guard let bin = Paths.firstExecutable(in: Paths.superviseMagicCandidates) else {
|
|
throw RunnerError.binaryMissing
|
|
}
|
|
// -yes ist Pflicht: ohne TTY-Pipe hängt der Bestätigungs-Prompt sonst endlos.
|
|
// CLI-Konvention: <command> [flags] — command MUSS zuerst kommen.
|
|
var args: [String] = ["supervise", "-yes"]
|
|
if verbose { args.append("-v") }
|
|
if force { args.append("-force") }
|
|
args.append(contentsOf: ["-org", organizationName])
|
|
let result = try await ProcessRunner.stream(bin, arguments: args, onLine: onLine)
|
|
if result.exitCode != 0 {
|
|
throw RunnerError.nonZeroExit(result.exitCode)
|
|
}
|
|
return result
|
|
}
|
|
|
|
/// Reverse-Operation für Tests / Recovery.
|
|
@MainActor
|
|
static func unsupervise(onLine: @escaping (String) -> Void) async throws -> ProcessRunner.Result {
|
|
guard let bin = Paths.firstExecutable(in: Paths.superviseMagicCandidates) else {
|
|
throw RunnerError.binaryMissing
|
|
}
|
|
return try await ProcessRunner.stream(bin, arguments: ["unsupervise", "-v", "-yes"], onLine: onLine)
|
|
}
|
|
}
|