Handle helper installation errors

This commit is contained in:
Brandon Evans 2021-01-22 22:18:59 -07:00
parent d834f3ed74
commit e21e4d9cdf
No known key found for this signature in database
GPG key ID: D58A4B8DB64F8E93
5 changed files with 44 additions and 26 deletions

View file

@ -303,11 +303,10 @@ extension AppState {
} }
func enableDeveloperMode() -> AnyPublisher<Void, Error> { func enableDeveloperMode() -> AnyPublisher<Void, Error> {
if helperInstallState == .notInstalled { installHelperIfNecessary()
installHelper() .flatMap {
} Current.helper.devToolsSecurityEnable()
}
return Current.helper.devToolsSecurityEnable()
.flatMap { .flatMap {
Current.helper.addStaffToDevelopersGroup() Current.helper.addStaffToDevelopersGroup()
} }
@ -315,20 +314,18 @@ extension AppState {
} }
func approveLicense(for xcode: InstalledXcode) -> AnyPublisher<Void, Error> { func approveLicense(for xcode: InstalledXcode) -> AnyPublisher<Void, Error> {
if helperInstallState == .notInstalled { installHelperIfNecessary()
installHelper() .flatMap {
} Current.helper.acceptXcodeLicense(xcode.path.string)
}
return Current.helper.acceptXcodeLicense(xcode.path.string)
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
func installComponents(for xcode: InstalledXcode) -> AnyPublisher<Void, Swift.Error> { func installComponents(for xcode: InstalledXcode) -> AnyPublisher<Void, Swift.Error> {
if helperInstallState == .notInstalled { installHelperIfNecessary()
installHelper() .flatMap {
} Current.helper.runFirstLaunch(xcode.path.string)
}
return Current.helper.runFirstLaunch(xcode.path.string)
.flatMap { .flatMap {
Current.shell.getUserCacheDir().map { $0.out } Current.shell.getUserCacheDir().map { $0.out }
.combineLatest( .combineLatest(

View file

@ -203,9 +203,29 @@ class AppState: ObservableObject {
// MARK: - Helper // MARK: - Helper
func installHelper() { func installHelperIfNecessary() {
Current.helper.install() installHelperIfNecessary()
checkIfHelperIsInstalled() .sink(
receiveCompletion: { [unowned self] completion in
if case let .failure(error) = completion {
self.error = error
}
},
receiveValue: {}
)
.store(in: &cancellables)
}
func installHelperIfNecessary() -> AnyPublisher<Void, Error> {
Result {
if helperInstallState == .notInstalled {
try Current.helper.install()
checkIfHelperIsInstalled()
}
}
.publisher
.subscribe(on: DispatchQueue.main)
.eraseToAnyPublisher()
} }
private func checkIfHelperIsInstalled() { private func checkIfHelperIsInstalled() {
@ -320,16 +340,15 @@ class AppState: ObservableObject {
} }
func select(id: Xcode.ID) { func select(id: Xcode.ID) {
if helperInstallState == .notInstalled {
installHelper()
}
guard guard
let installedXcode = Current.files.installedXcodes(Path.root/"Applications").first(where: { $0.version == id }), let installedXcode = Current.files.installedXcodes(Path.root/"Applications").first(where: { $0.version == id }),
selectPublisher == nil selectPublisher == nil
else { return } else { return }
selectPublisher = HelperClient().switchXcodePath(installedXcode.path.string) selectPublisher = installHelperIfNecessary()
.flatMap {
Current.helper.switchXcodePath(installedXcode.path.string)
}
.flatMap { [unowned self] _ in .flatMap { [unowned self] _ in
self.updateSelectedXcodePath() self.updateSelectedXcodePath()
} }

View file

@ -237,7 +237,7 @@ public struct Defaults {
private let helperClient = HelperClient() private let helperClient = HelperClient()
public struct Helper { public struct Helper {
var install: () -> Void = helperClient.install var install: () throws -> Void = helperClient.install
var checkIfLatestHelperIsInstalled: () -> AnyPublisher<Bool, Never> = helperClient.checkIfLatestHelperIsInstalled var checkIfLatestHelperIsInstalled: () -> AnyPublisher<Bool, Never> = helperClient.checkIfLatestHelperIsInstalled
var getVersion: () -> AnyPublisher<String, Error> = helperClient.getVersion var getVersion: () -> AnyPublisher<String, Error> = helperClient.getVersion
var switchXcodePath: (_ absolutePath: String) -> AnyPublisher<Void, Error> = helperClient.switchXcodePath var switchXcodePath: (_ absolutePath: String) -> AnyPublisher<Void, Error> = helperClient.switchXcodePath

View file

@ -307,7 +307,7 @@ final class HelperClient {
// MARK: - Install // MARK: - Install
// From https://github.com/securing/SimpleXPCApp/ // From https://github.com/securing/SimpleXPCApp/
func install() { func install() throws {
Logger.helperClient.info(#function) Logger.helperClient.info(#function)
var authItem = kSMRightBlessPrivilegedHelper.withCString { name in var authItem = kSMRightBlessPrivilegedHelper.withCString { name in
@ -329,6 +329,8 @@ final class HelperClient {
Logger.helperClient.info("\(#function): Finished installation") Logger.helperClient.info("\(#function): Finished installation")
} catch { } catch {
Logger.helperClient.error("\(#function): \(error.localizedDescription)") Logger.helperClient.error("\(#function): \(error.localizedDescription)")
throw error
} }
} }

View file

@ -55,7 +55,7 @@ struct AdvancedPreferencePane: View {
HStack { HStack {
Text("Helper is not installed") Text("Helper is not installed")
Button("Install helper") { Button("Install helper") {
appState.installHelper() appState.installHelperIfNecessary()
} }
} }
} }