mirror of
https://github.com/mas-cli/mas
synced 2024-11-25 21:10:24 +00:00
Improve error messages
This commit is contained in:
parent
94f3cea428
commit
ce51cea8c6
11 changed files with 95 additions and 67 deletions
|
@ -9,7 +9,7 @@
|
|||
func download(_ adamId: UInt64) -> MASError? {
|
||||
|
||||
guard let account = ISStoreAccount.primaryAccount else {
|
||||
return MASError(code: .notSignedIn)
|
||||
return .notSignedIn
|
||||
}
|
||||
|
||||
let group = DispatchGroup()
|
||||
|
@ -21,7 +21,7 @@ func download(_ adamId: UInt64) -> MASError? {
|
|||
group.enter()
|
||||
purchase.perform { purchase, _, error, response in
|
||||
if let error = error {
|
||||
purchaseError = MASError(code: .purchaseError, sourceError: error as NSError)
|
||||
purchaseError = .purchaseFailed(error: error as NSError?)
|
||||
group.leave()
|
||||
return
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ func download(_ adamId: UInt64) -> MASError? {
|
|||
}
|
||||
else {
|
||||
print("No downloads")
|
||||
purchaseError = MASError(code: .noDownloads)
|
||||
purchaseError = .noDownloads
|
||||
group.leave()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,6 @@ extension ISStoreAccount {
|
|||
return account
|
||||
}
|
||||
|
||||
throw error ?? MASError(code: .signInError)
|
||||
throw error ?? MASError.signInFailed(error: nil)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
// Copyright (c) 2015 Andrew Naylor. All rights reserved.
|
||||
//
|
||||
|
||||
let csi = "\u{001B}["
|
||||
|
||||
@objc class PurchaseDownloadObserver: NSObject, CKDownloadQueueObserver {
|
||||
let purchase: SSPurchase
|
||||
var completionHandler: (() -> ())?
|
||||
|
@ -36,7 +34,7 @@ let csi = "\u{001B}["
|
|||
return
|
||||
}
|
||||
clearLine()
|
||||
print("==> Downloading " + download.metadata.title)
|
||||
printInfo("Downloading \(download.metadata.title)")
|
||||
}
|
||||
|
||||
func downloadQueue(_ queue: CKDownloadQueue, changedWithRemoval download: SSDownload!) {
|
||||
|
@ -47,15 +45,13 @@ let csi = "\u{001B}["
|
|||
|
||||
clearLine()
|
||||
if status.isFailed {
|
||||
print("==> Download Failed")
|
||||
errorHandler?(MASError(code: .downloadFailed, sourceError: status.error as NSError?))
|
||||
errorHandler?(.downloadFailed(error: status.error as NSError?))
|
||||
}
|
||||
else if status.isCancelled {
|
||||
print("==> Download Cancelled")
|
||||
errorHandler?(MASError(code: .cancelled))
|
||||
errorHandler?(.cancelled)
|
||||
}
|
||||
else {
|
||||
print("==> Installed " + download.metadata.title)
|
||||
printInfo("Installed \(download.metadata.title)")
|
||||
completionHandler?()
|
||||
}
|
||||
}
|
||||
|
@ -93,14 +89,6 @@ func progress(_ state: ProgressState) {
|
|||
fflush(stdout)
|
||||
}
|
||||
|
||||
func clearLine() {
|
||||
guard isatty(fileno(stdout)) != 0 else {
|
||||
return
|
||||
}
|
||||
print("\(csi)2K\(csi)0G", terminator: "")
|
||||
fflush(stdout)
|
||||
}
|
||||
|
||||
extension SSDownloadStatus {
|
||||
var progressState: ProgressState? {
|
||||
if let phase = activePhase {
|
||||
|
|
|
@ -17,7 +17,7 @@ struct AccountCommand: CommandProtocol {
|
|||
}
|
||||
else {
|
||||
print("Not signed in")
|
||||
return .failure(MASError(code: .notSignedIn))
|
||||
return .failure(.notSignedIn)
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ struct InstallCommand: CommandProtocol {
|
|||
// Try to download applications with given identifiers and collect results
|
||||
let downloadResults = options.appIds.flatMap { (appId) -> MASError? in
|
||||
if let product = installedApp(appId) , !options.forceInstall {
|
||||
warn("\(product.appName) is already installed")
|
||||
printWarning("\(product.appName) is already installed")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ struct InstallCommand: CommandProtocol {
|
|||
case 1:
|
||||
return .failure(downloadResults[0])
|
||||
default:
|
||||
return .failure(MASError(code: .downloadFailed))
|
||||
return .failure(.downloadFailed(error: nil))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,13 +22,13 @@ struct SearchCommand: CommandProtocol {
|
|||
|
||||
guard let searchURLString = searchURLString(options.appName),
|
||||
let searchJson = URLSession.requestSynchronousJSONWithURLString(searchURLString) as? [String: AnyObject] else {
|
||||
return .failure(MASError(code:.searchError))
|
||||
return .failure(.searchFailed)
|
||||
}
|
||||
|
||||
guard let resultCount = searchJson[ResultKeys.ResultCount] as? Int , resultCount > 0,
|
||||
let results = searchJson[ResultKeys.Results] as? [[String: AnyObject]] else {
|
||||
print("No results found")
|
||||
return .failure(MASError(code:.noSearchResultsFound))
|
||||
return .failure(.noSearchResultsFound)
|
||||
}
|
||||
|
||||
for result in results {
|
||||
|
|
|
@ -14,7 +14,7 @@ struct SignInCommand: CommandProtocol {
|
|||
func run(_ options: Options) -> Result<(), MASError> {
|
||||
|
||||
guard ISStoreAccount.primaryAccount == nil else {
|
||||
return .failure(MASError.init(code: .alreadySignedIn))
|
||||
return .failure(.alreadySignedIn)
|
||||
}
|
||||
|
||||
do {
|
||||
|
@ -29,7 +29,7 @@ struct SignInCommand: CommandProtocol {
|
|||
|
||||
let _ = try ISStoreAccount.signIn(username: options.username, password: password, systemDialog: options.dialog)
|
||||
} catch let error as NSError {
|
||||
return .failure(MASError(code: .signInError, sourceError: error))
|
||||
return .failure(.signInFailed(error: error))
|
||||
}
|
||||
|
||||
return .success(())
|
||||
|
|
|
@ -20,7 +20,7 @@ struct UpgradeCommand: CommandProtocol {
|
|||
updates = appIds.flatMap { updateController?.availableUpdate(withItemIdentifier: $0) }
|
||||
|
||||
guard updates.count > 0 else {
|
||||
warn("Nothing found to upgrade")
|
||||
printWarning("Nothing found to upgrade")
|
||||
return .success(())
|
||||
}
|
||||
} else {
|
||||
|
@ -46,7 +46,7 @@ struct UpgradeCommand: CommandProtocol {
|
|||
case 1:
|
||||
return .failure(updateResults[0])
|
||||
default:
|
||||
return .failure(MASError(code: .downloadFailed))
|
||||
return .failure(.downloadFailed(error: nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,39 +6,58 @@
|
|||
// Copyright (c) 2015 Andrew Naylor. All rights reserved.
|
||||
//
|
||||
|
||||
public let MASErrorDomain: String = "MASErrorDomain"
|
||||
|
||||
private let MASErrorSource: String = "MASErrorSource"
|
||||
|
||||
public enum MASErrorCode: Int {
|
||||
case noError
|
||||
enum MASError: Error, CustomStringConvertible {
|
||||
case notSignedIn
|
||||
case purchaseError
|
||||
case signInFailed(error: NSError?)
|
||||
case alreadySignedIn
|
||||
|
||||
case purchaseFailed(error: NSError?)
|
||||
case downloadFailed(error: NSError?)
|
||||
case noDownloads
|
||||
case cancelled
|
||||
case downloadFailed
|
||||
case signInError
|
||||
case alreadySignedIn
|
||||
case searchError
|
||||
|
||||
case searchFailed
|
||||
case noSearchResultsFound
|
||||
case noUpdatesFound
|
||||
|
||||
var exitCode: Int32 {
|
||||
return Int32(self.rawValue)
|
||||
var description: String {
|
||||
switch self {
|
||||
case .notSignedIn:
|
||||
return "Not signed in"
|
||||
|
||||
case .signInFailed(error: let error):
|
||||
if let error = error {
|
||||
return "Sign in failed: \(error.localizedDescription)"
|
||||
} else {
|
||||
return "Sign in failed"
|
||||
}
|
||||
|
||||
case .alreadySignedIn:
|
||||
return "Already signed in"
|
||||
|
||||
case .purchaseFailed(error: let error):
|
||||
if let error = error {
|
||||
return "Download request failed: \(error.localizedDescription)"
|
||||
} else {
|
||||
return "Download request failed"
|
||||
}
|
||||
case .downloadFailed(error: let error):
|
||||
if let error = error {
|
||||
return "Download failed: \(error.localizedDescription)"
|
||||
} else {
|
||||
return "Download failed"
|
||||
}
|
||||
|
||||
case .noDownloads:
|
||||
return "No downloads began"
|
||||
|
||||
case .cancelled:
|
||||
return "Download cancelled"
|
||||
|
||||
case .searchFailed:
|
||||
return "Search failed"
|
||||
|
||||
case .noSearchResultsFound:
|
||||
return "No results found"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class MASError: Error {
|
||||
let code: MASErrorCode
|
||||
|
||||
let sourceError: NSError?
|
||||
|
||||
init(code: MASErrorCode, sourceError: NSError? = nil) {
|
||||
self.code = code
|
||||
self.sourceError = sourceError
|
||||
}
|
||||
}
|
||||
|
||||
public func == (lhs: MASError, rhs: MASError) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -6,22 +6,46 @@
|
|||
// Copyright © 2016 Andrew Naylor. All rights reserved.
|
||||
//
|
||||
|
||||
func warn(_ message: String) {
|
||||
/// A collection of output formatting helpers
|
||||
|
||||
|
||||
/// Terminal Control Sequence Indicator
|
||||
let csi = "\u{001B}["
|
||||
|
||||
func printInfo(_ message: String) {
|
||||
guard isatty(fileno(stdout)) != 0 else {
|
||||
print("==> \(message)")
|
||||
return
|
||||
}
|
||||
|
||||
// Blue bold arrow, Bold text
|
||||
print("\(csi)1;34m==>\(csi)0m \(csi)1m\(message)\(csi)0m")
|
||||
}
|
||||
|
||||
func printWarning(_ message: String) {
|
||||
guard isatty(fileno(stdout)) != 0 else {
|
||||
print("Warning: \(message)")
|
||||
return
|
||||
}
|
||||
|
||||
// Yellow, underlined "Warning:" prefix
|
||||
print("\(csi)4m\(csi)33mWarning:\(csi)0m \(message)")
|
||||
print("\(csi)4;33mWarning:\(csi)0m \(message)")
|
||||
}
|
||||
|
||||
func error(_ message: String) {
|
||||
func printError(_ message: String) {
|
||||
guard isatty(fileno(stdout)) != 0 else {
|
||||
print("Warning: \(message)")
|
||||
return
|
||||
}
|
||||
|
||||
// Red, underlined "Error:" prefix
|
||||
print("\(csi)4m\(csi)31mError:\(csi)0m \(message)")
|
||||
print("\(csi)4;31mError:\(csi)0m \(message)")
|
||||
}
|
||||
|
||||
func clearLine() {
|
||||
guard isatty(fileno(stdout)) != 0 else {
|
||||
return
|
||||
}
|
||||
print("\(csi)2K\(csi)0G", terminator: "")
|
||||
fflush(stdout)
|
||||
}
|
||||
|
|
|
@ -29,10 +29,7 @@ registry.register(VersionCommand())
|
|||
registry.register(helpCommand)
|
||||
|
||||
registry.main(defaultVerb: helpCommand.verb) { error in
|
||||
if let sourceError = error.sourceError {
|
||||
var stderr = StderrOutputStream()
|
||||
print(sourceError.localizedDescription, to: &stderr)
|
||||
}
|
||||
exit(Int32(error.code.rawValue))
|
||||
printError(String(describing: error))
|
||||
exit(1)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue