From 9597c7deb6ab893db7bbf63c5c29f8c0982c9232 Mon Sep 17 00:00:00 2001 From: Magesh K <47920326+mahee96@users.noreply.github.com> Date: Fri, 13 Dec 2024 16:30:24 +0530 Subject: [PATCH] [error-handling]: Improved Error handling for all OperationTypes in AppManager --- AltStore/Managing Apps/AppManager.swift | 36 +++++-- .../Operations/DownloadAppOperation.swift | 100 +++++++++--------- 2 files changed, 80 insertions(+), 56 deletions(-) diff --git a/AltStore/Managing Apps/AppManager.swift b/AltStore/Managing Apps/AppManager.swift index d36457ae..962a7665 100644 --- a/AltStore/Managing Apps/AppManager.swift +++ b/AltStore/Managing Apps/AppManager.swift @@ -1407,7 +1407,9 @@ private extension AppManager verifyPledgeOperation?.resultHandler = { result in switch result { - case .failure(let error): context.error = error + case .failure(let error): + context.error = error + completionHandler(.failure(error)) case .success: break } } @@ -1421,10 +1423,16 @@ private extension AppManager { let app = try result.get() context.app = app + + if cacheApp + { + try FileManager.default.copyItem(at: app.fileURL, to: InstalledApp.fileURL(for: app), shouldReplace: true) + } } catch { context.error = error + completionHandler(.failure(error)) } } progress.addChild(downloadOperation.progress, withPendingUnitCount: 25) @@ -1508,7 +1516,9 @@ private extension AppManager refreshAnisetteDataOperation.resultHandler = { (result) in switch result { - case .failure(let error): context.error = error + case .failure(let error): + context.error = error + completionHandler(.failure(error)) case .success(let anisetteData): group.context.session?.anisetteData = anisetteData } } @@ -1521,7 +1531,9 @@ private extension AppManager fetchProvisioningProfilesOperation.resultHandler = { (result) in switch result { - case .failure(let error): context.error = error + case .failure(let error): + context.error = error + completionHandler(.failure(error)) case .success(let provisioningProfiles): context.provisioningProfiles = provisioningProfiles print("PROVISIONING PROFILES \(context.provisioningProfiles)") @@ -1659,7 +1671,9 @@ private extension AppManager resignAppOperation.resultHandler = { (result) in switch result { - case .failure(let error): context.error = error + case .failure(let error): + context.error = error + completionHandler(.failure(error)) case .success(let resignedApp): context.resignedApp = resignedApp } } @@ -1672,7 +1686,9 @@ private extension AppManager sendAppOperation.resultHandler = { (result) in switch result { - case .failure(let error): context.error = error + case .failure(let error): + context.error = error + completionHandler(.failure(error)) case .success(_): print("App reported as installed") } } @@ -1757,7 +1773,9 @@ private extension AppManager fetchProvisioningProfilesOperation.resultHandler = { (result) in switch result { - case .failure(let error): context.error = error + case .failure(let error): + context.error = error + completionHandler(.failure(error)) case .success(let provisioningProfiles): context.provisioningProfiles = provisioningProfiles } } @@ -1839,6 +1857,7 @@ private extension AppManager case .failure(let error): restoreContext.error = error appContext.error = error + completionHandler(.failure(error)) } } restoreAppOperation.addDependency(installBackupAppOperation) @@ -1960,7 +1979,9 @@ private extension AppManager backupAppOperation.resultHandler = { (result) in switch result { - case .failure(let error): context.error = error + case .failure(let error): + context.error = error + completionHandler(.failure(error)) case .success: break } } @@ -2016,6 +2037,7 @@ private extension AppManager case .failure(let error): restoreContext.error = error appContext.error = error + completionHandler(.failure(error)) } } backupAppOperation.addDependency(installBackupAppOperation) diff --git a/AltStore/Operations/DownloadAppOperation.swift b/AltStore/Operations/DownloadAppOperation.swift index 1652a781..fbf42678 100644 --- a/AltStore/Operations/DownloadAppOperation.swift +++ b/AltStore/Operations/DownloadAppOperation.swift @@ -126,13 +126,15 @@ final class DownloadAppOperation: ResultOperation override func finish(_ result: Result) { - do - { - try FileManager.default.removeItem(at: self.temporaryDirectory) - } - catch - { - print("Failed to remove DownloadAppOperation temporary directory: \(self.temporaryDirectory).", error) + if(FileManager.default.fileExists(atPath: self.temporaryDirectory.path)){ + do + { + try FileManager.default.removeItem(at: self.temporaryDirectory) + } + catch + { + print("Failed to remove DownloadAppOperation temporary directory: \(self.temporaryDirectory).", error) + } } super.finish(result) @@ -155,54 +157,54 @@ private extension DownloadAppOperation func download(@Managed _ app: AppProtocol) { - guard let sourceURL = self.sourceURL else { return self.finish(.failure(OperationError.appNotFound(name: self.appName))) - - if let appVersion = app as? AppVersion + guard let sourceURL = self.sourceURL else { + return self.finish(.failure(OperationError.appNotFound(name: self.appName))) + } + if let appVersion = app as? AppVersion + { + // All downloads go through this path, and `app` is + // always an AppVersion if downloading from a source, + // so context.appVersion != nil means downloading from source. + self.context.appVersion = appVersion + } + downloadIPA(from: sourceURL) { result in + do { - // All downloads go through this path, and `app` is - // always an AppVersion if downloading from a source, - // so context.appVersion != nil means downloading from source. - self.context.appVersion = appVersion - } - downloadIPA(from: sourceURL!) { result in - do + let application = try result.get() + + if self.context.bundleIdentifier == StoreApp.dolphinAppID, self.context.bundleIdentifier != application.bundleIdentifier { - let application = try result.get() - - if self.context.bundleIdentifier == StoreApp.dolphinAppID, self.context.bundleIdentifier != application.bundleIdentifier + if var infoPlist = NSDictionary(contentsOf: application.bundle.infoPlistURL) as? [String: Any] { - if var infoPlist = NSDictionary(contentsOf: application.bundle.infoPlistURL) as? [String: Any] - { - // Manually update the app's bundle identifier to match the one specified in the source. - // This allows people who previously installed the app to still update and refresh normally. - infoPlist[kCFBundleIdentifierKey as String] = StoreApp.dolphinAppID - (infoPlist as NSDictionary).write(to: application.bundle.infoPlistURL, atomically: true) - } - } - - self.downloadDependencies(for: application) { result in - do - { - _ = try result.get() - - try FileManager.default.copyItem(at: application.fileURL, to: self.destinationURL, shouldReplace: true) - - guard let copiedApplication = ALTApplication(fileURL: self.destinationURL) else { throw OperationError.invalidApp } - self.finish(.success(copiedApplication)) - - self.progress.completedUnitCount += 1 - } - catch - { - self.finish(.failure(error)) - } + // Manually update the app's bundle identifier to match the one specified in the source. + // This allows people who previously installed the app to still update and refresh normally. + infoPlist[kCFBundleIdentifierKey as String] = StoreApp.dolphinAppID + (infoPlist as NSDictionary).write(to: application.bundle.infoPlistURL, atomically: true) } } - catch - { - self.finish(.failure(error)) + + self.downloadDependencies(for: application) { result in + do + { + _ = try result.get() + + try FileManager.default.copyItem(at: application.fileURL, to: self.destinationURL, shouldReplace: true) + + guard let copiedApplication = ALTApplication(fileURL: self.destinationURL) else { throw OperationError.invalidApp } + self.finish(.success(copiedApplication)) + + self.progress.completedUnitCount += 1 + } + catch + { + self.finish(.failure(error)) + } } } + catch + { + self.finish(.failure(error)) + } } func downloadIPA(from sourceURL: URL, completionHandler: @escaping (Result) -> Void) @@ -229,7 +231,7 @@ private extension DownloadAppOperation } defer { - if !sourceURL.isFileURL + if !sourceURL.isFileURL && FileManager.default.fileExists(atPath: fileURL.path) { try? FileManager.default.removeItem(at: fileURL) }