diff --git a/mas-cli/AppStore/Downloader.swift b/mas-cli/AppStore/Downloader.swift index 1d48620..1b3e776 100644 --- a/mas-cli/AppStore/Downloader.swift +++ b/mas-cli/AppStore/Downloader.swift @@ -14,17 +14,30 @@ func download(adamId: UInt64) -> MASError? { var purchaseError: MASError? - purchase.perform { purchase, completed, error, response in - if completed { + purchase.perform { purchase, unused, error, response in + if let error = error { + purchaseError = MASError(code: .PurchaseError, sourceError: error) + dispatch_group_leave(group) + return + } + + if let downloads = response.downloads as? [SSDownload] where count(downloads) > 0 { let observer = PurchaseDownloadObserver(purchase: purchase) - observer.onCompletion { + + observer.errorHandler = { error in + purchaseError = error + dispatch_group_leave(group) + } + + observer.completionHandler = { dispatch_group_leave(group) } CKDownloadQueue.sharedDownloadQueue().addObserver(observer) } else { - purchaseError = MASError(code: .PurchaseError, sourceError: error) + println("No downloads") + purchaseError = MASError(code: .NoDownloads) dispatch_group_leave(group) } } diff --git a/mas-cli/AppStore/PurchaseDownloadObserver.swift b/mas-cli/AppStore/PurchaseDownloadObserver.swift index a486be9..946d4d4 100644 --- a/mas-cli/AppStore/PurchaseDownloadObserver.swift +++ b/mas-cli/AppStore/PurchaseDownloadObserver.swift @@ -11,34 +11,44 @@ let csi = "\u{001B}[" @objc class PurchaseDownloadObserver: CKDownloadQueueObserver { let purchase: SSPurchase var completionHandler: (() -> ())? - var started = false + var errorHandler: ((MASError) -> ())? init(purchase: SSPurchase) { self.purchase = purchase } func downloadQueue(queue: CKDownloadQueue, statusChangedForDownload download: SSDownload!) { - if !started { + if download.metadata.itemIdentifier != purchase.itemIdentifier { return } - progress(download.status.progressState) + let status = download.status + if status.failed || status.cancelled { + queue.removeDownloadWithItemIdentifier(download.metadata.itemIdentifier) + } + else { + progress(status.progressState) + } } func downloadQueue(queue: CKDownloadQueue, changedWithAddition download: SSDownload!) { - started = true println("==> Downloading " + download.metadata.title) } func downloadQueue(queue: CKDownloadQueue, changedWithRemoval download: SSDownload!) { - println("") - println("==> Installed " + download.metadata.title) - if let complete = self.completionHandler { - complete() + clearLine() + let status = download.status + if status.failed { + println("==> Download Failed: \(status.error.localizedDescription)") + errorHandler?(MASError(code: .DownloadFailed, sourceError: status.error)) + } + else if status.cancelled { + println("==> Download Cancelled") + errorHandler?(MASError(code: .Cancelled)) + } + else { + println("==> Installed " + download.metadata.title) + completionHandler?() } - } - - func onCompletion(complete: () -> ()) { - self.completionHandler = complete } } @@ -69,10 +79,15 @@ func progress(state: ProgressState) { bar += "-" } } - print("\(csi)2K\(csi)0G\(bar) \(state.percentage) \(state.phase)") + clearLine() + print("\(bar) \(state.percentage) \(state.phase)") fflush(stdout) } +func clearLine() { + print("\(csi)2K\(csi)0G") +} + extension SSDownloadStatus { var progressState: ProgressState { let phase = activePhase?.phaseDescription ?? "Waiting" diff --git a/mas-cli/Error.swift b/mas-cli/Error.swift index ff52e31..f25a6b8 100644 --- a/mas-cli/Error.swift +++ b/mas-cli/Error.swift @@ -14,6 +14,9 @@ public enum MASErrorCode: Int { case NoError case NotSignedIn case PurchaseError + case NoDownloads + case Cancelled + case DownloadFailed var exitCode: Int32 { return Int32(self.rawValue) diff --git a/mas-cli/main.swift b/mas-cli/main.swift index 0b57e4e..5e237bf 100644 --- a/mas-cli/main.swift +++ b/mas-cli/main.swift @@ -17,7 +17,7 @@ registry.register(ListInstalledCommand()) registry.register(ListUpdatesCommand()) registry.register(helpCommand) -registry.main(defaultVerb: helpCommand.verb, errorHandler: { error in - fputs(error.description + "\n", stderr) -}) +registry.main(defaultVerb: helpCommand.verb) { error in + exit(Int32(error.code)) +}