mirror of
https://github.com/mas-cli/mas
synced 2024-11-22 03:23:08 +00:00
Begin to refactor the download process
This commit is contained in:
parent
83291f2fc6
commit
41ceab2c3a
7 changed files with 93 additions and 32 deletions
|
@ -21,10 +21,11 @@
|
|||
ED0F23831B87533A00AE40CD /* ListInstalled.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F23821B87533A00AE40CD /* ListInstalled.swift */; };
|
||||
ED0F23851B87536A00AE40CD /* ListUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F23841B87536A00AE40CD /* ListUpdates.swift */; };
|
||||
ED0F23871B87537200AE40CD /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F23861B87537200AE40CD /* Account.swift */; };
|
||||
ED0F23891B87543D00AE40CD /* DownloadQueueObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F23881B87543D00AE40CD /* DownloadQueueObserver.swift */; };
|
||||
ED0F23891B87543D00AE40CD /* PurchaseDownloadObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F23881B87543D00AE40CD /* PurchaseDownloadObserver.swift */; };
|
||||
ED0F238B1B87569C00AE40CD /* Downloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F238A1B87569C00AE40CD /* Downloader.swift */; };
|
||||
ED0F238D1B8756E600AE40CD /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F238C1B8756E600AE40CD /* Error.swift */; };
|
||||
ED0F23901B87A56F00AE40CD /* ISStoreAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F238F1B87A56F00AE40CD /* ISStoreAccount.swift */; };
|
||||
EDA3BE521B8B84AF00C18D70 /* SSPurchase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA3BE511B8B84AF00C18D70 /* SSPurchase.swift */; };
|
||||
EDEAA0C01B51CE6200F2FC3F /* StoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDEAA0BF1B51CE6200F2FC3F /* StoreFoundation.framework */; };
|
||||
EDEAA17D1B5C579100F2FC3F /* CommerceKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDEAA17C1B5C579100F2FC3F /* CommerceKit.framework */; };
|
||||
F5F01044EC3065C6EBAB95D7 /* BoxType.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0E87CFA5E6371893D5B1807 /* BoxType.swift */; };
|
||||
|
@ -57,10 +58,11 @@
|
|||
ED0F23821B87533A00AE40CD /* ListInstalled.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListInstalled.swift; sourceTree = "<group>"; };
|
||||
ED0F23841B87536A00AE40CD /* ListUpdates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListUpdates.swift; sourceTree = "<group>"; };
|
||||
ED0F23861B87537200AE40CD /* Account.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = "<group>"; };
|
||||
ED0F23881B87543D00AE40CD /* DownloadQueueObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownloadQueueObserver.swift; sourceTree = "<group>"; };
|
||||
ED0F23881B87543D00AE40CD /* PurchaseDownloadObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PurchaseDownloadObserver.swift; sourceTree = "<group>"; };
|
||||
ED0F238A1B87569C00AE40CD /* Downloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Downloader.swift; sourceTree = "<group>"; };
|
||||
ED0F238C1B8756E600AE40CD /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; };
|
||||
ED0F238F1B87A56F00AE40CD /* ISStoreAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ISStoreAccount.swift; sourceTree = "<group>"; };
|
||||
EDA3BE511B8B84AF00C18D70 /* SSPurchase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SSPurchase.swift; sourceTree = "<group>"; };
|
||||
EDEAA0BF1B51CE6200F2FC3F /* StoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreFoundation.framework; path = /System/Library/PrivateFrameworks/StoreFoundation.framework; sourceTree = "<absolute>"; };
|
||||
EDEAA0C31B51CEE400F2FC3F /* CDStructures.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CDStructures.h; sourceTree = "<group>"; };
|
||||
EDEAA0C41B51CEE400F2FC3F /* CKBook.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKBook.h; sourceTree = "<group>"; };
|
||||
|
@ -351,8 +353,9 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
ED0F238A1B87569C00AE40CD /* Downloader.swift */,
|
||||
ED0F23881B87543D00AE40CD /* DownloadQueueObserver.swift */,
|
||||
ED0F238F1B87A56F00AE40CD /* ISStoreAccount.swift */,
|
||||
ED0F23881B87543D00AE40CD /* PurchaseDownloadObserver.swift */,
|
||||
EDA3BE511B8B84AF00C18D70 /* SSPurchase.swift */,
|
||||
);
|
||||
path = AppStore;
|
||||
sourceTree = "<group>";
|
||||
|
@ -637,7 +640,6 @@
|
|||
F5F01044EC3065C6EBAB95D7 /* BoxType.swift in Sources */,
|
||||
21EC092422A3EDFE33B153B8 /* Command.swift in Sources */,
|
||||
ED0F238B1B87569C00AE40CD /* Downloader.swift in Sources */,
|
||||
ED0F23891B87543D00AE40CD /* DownloadQueueObserver.swift in Sources */,
|
||||
ED0F238D1B8756E600AE40CD /* Error.swift in Sources */,
|
||||
B80C5DDD38A8F7EB6F320697 /* Errors.swift in Sources */,
|
||||
5918483F96256CDAC88FF450 /* HelpCommand.swift in Sources */,
|
||||
|
@ -648,7 +650,9 @@
|
|||
ED031A7C1B5127C00097692E /* main.swift in Sources */,
|
||||
DE39BCA91D1BC3D876711677 /* MutableBox.swift in Sources */,
|
||||
92828DCD99CED47F54242776 /* Option.swift in Sources */,
|
||||
ED0F23891B87543D00AE40CD /* PurchaseDownloadObserver.swift in Sources */,
|
||||
1CC607DA6B900AA3FEC3F6D8 /* Result.swift in Sources */,
|
||||
EDA3BE521B8B84AF00C18D70 /* SSPurchase.swift in Sources */,
|
||||
7858BCFB4D5A4251DE998CE4 /* Switch.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
|
@ -6,25 +6,34 @@
|
|||
// Copyright (c) 2015 Andrew Naylor. All rights reserved.
|
||||
//
|
||||
|
||||
typealias DownloadCompletion = (purchase: SSPurchase!, completed: Bool, error: NSError?, response: SSPurchaseResponse!) -> ()
|
||||
func download(adamId: UInt64) -> MASError? {
|
||||
|
||||
func download(adamId: UInt64, completion:DownloadCompletion) {
|
||||
let buyParameters = "productType=C&price=0&salableAdamId=\(adamId)&pricingParameters=STDRDL"
|
||||
let purchase = SSPurchase()
|
||||
purchase.buyParameters = buyParameters
|
||||
purchase.itemIdentifier = adamId
|
||||
purchase.accountIdentifier = primaryAccount().dsID
|
||||
purchase.appleID = primaryAccount().identifier
|
||||
|
||||
let downloadMetadata = SSDownloadMetadata()
|
||||
downloadMetadata.kind = "software"
|
||||
downloadMetadata.itemIdentifier = adamId
|
||||
|
||||
purchase.downloadMetadata = downloadMetadata
|
||||
|
||||
let purchaseController = CKPurchaseController.sharedPurchaseController()
|
||||
purchaseController.performPurchase(purchase, withOptions: 0, completionHandler: completion)
|
||||
while true {
|
||||
NSRunLoop.mainRunLoop().runMode(NSDefaultRunLoopMode, beforeDate: NSDate(timeIntervalSinceNow: 10))
|
||||
if let account = ISStoreAccount.primaryAccount {
|
||||
let group = dispatch_group_create()
|
||||
let purchase = SSPurchase(adamId: adamId, account: account)
|
||||
|
||||
var purchaseError: MASError?
|
||||
|
||||
purchase.perform { purchase, completed, error, response in
|
||||
if completed {
|
||||
let observer = PurchaseDownloadObserver(purchase: purchase)
|
||||
observer.onCompletion {
|
||||
dispatch_group_leave(group)
|
||||
}
|
||||
|
||||
CKDownloadQueue.sharedDownloadQueue().addObserver(observer)
|
||||
}
|
||||
else {
|
||||
purchaseError = MASError(code: .PurchaseError, sourceError: error)
|
||||
dispatch_group_leave(group)
|
||||
}
|
||||
}
|
||||
|
||||
dispatch_group_enter(group)
|
||||
dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
|
||||
return purchaseError
|
||||
}
|
||||
}
|
||||
else {
|
||||
return MASError(code: .NotSignedIn)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// DownloadQueueObserver.swift
|
||||
// PurchaseDownloadObserver.swift
|
||||
// mas-cli
|
||||
//
|
||||
// Created by Andrew Naylor on 21/08/2015.
|
||||
|
@ -8,9 +8,15 @@
|
|||
|
||||
let csi = "\u{001B}["
|
||||
|
||||
@objc class DownloadQueueObserver: CKDownloadQueueObserver {
|
||||
@objc class PurchaseDownloadObserver: CKDownloadQueueObserver {
|
||||
let purchase: SSPurchase
|
||||
var completionHandler: (() -> ())?
|
||||
var started = false
|
||||
|
||||
init(purchase: SSPurchase) {
|
||||
self.purchase = purchase
|
||||
}
|
||||
|
||||
func downloadQueue(queue: CKDownloadQueue, statusChangedForDownload download: SSDownload!) {
|
||||
if !started {
|
||||
return
|
||||
|
@ -26,7 +32,13 @@ let csi = "\u{001B}["
|
|||
func downloadQueue(queue: CKDownloadQueue, changedWithRemoval download: SSDownload!) {
|
||||
println("")
|
||||
println("==> Installed " + download.metadata.title)
|
||||
exit(EXIT_SUCCESS)
|
||||
if let complete = self.completionHandler {
|
||||
complete()
|
||||
}
|
||||
}
|
||||
|
||||
func onCompletion(complete: () -> ()) {
|
||||
self.completionHandler = complete
|
||||
}
|
||||
}
|
||||
|
29
mas-cli/AppStore/SSPurchase.swift
Normal file
29
mas-cli/AppStore/SSPurchase.swift
Normal file
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// SSPurchase.swift
|
||||
// mas-cli
|
||||
//
|
||||
// Created by Andrew Naylor on 25/08/2015.
|
||||
// Copyright (c) 2015 Andrew Naylor. All rights reserved.
|
||||
//
|
||||
|
||||
typealias SSPurchaseCompletion = (purchase: SSPurchase!, completed: Bool, error: NSError?, response: SSPurchaseResponse!) -> ()
|
||||
|
||||
extension SSPurchase {
|
||||
convenience init(adamId: UInt64, account: ISStoreAccount) {
|
||||
self.init()
|
||||
self.buyParameters = "productType=C&price=0&salableAdamId=\(adamId)&pricingParameters=STDRDL"
|
||||
self.itemIdentifier = adamId
|
||||
self.accountIdentifier = account.dsID
|
||||
self.appleID = account.identifier
|
||||
|
||||
let downloadMetadata = SSDownloadMetadata()
|
||||
downloadMetadata.kind = "software"
|
||||
downloadMetadata.itemIdentifier = adamId
|
||||
|
||||
self.downloadMetadata = downloadMetadata
|
||||
}
|
||||
|
||||
func perform(completion: SSPurchaseCompletion) {
|
||||
CKPurchaseController.sharedPurchaseController().performPurchase(self, withOptions: 0, completionHandler: completion)
|
||||
}
|
||||
}
|
|
@ -11,10 +11,18 @@ struct InstallCommand: CommandType {
|
|||
let function = "Install from the Mac App Store"
|
||||
|
||||
func run(mode: CommandMode) -> Result<(), CommandantError<MASError>> {
|
||||
return InstallOptions.evaluate(mode).map { options in
|
||||
download(options.appId) { (purchase, completed, error, response) in
|
||||
|
||||
let optionsResult = InstallOptions.evaluate(mode)
|
||||
|
||||
switch optionsResult {
|
||||
case let .Failure(error):
|
||||
return .Failure(error)
|
||||
|
||||
case let .Success(options):
|
||||
if let error = download(options.value.appId) {
|
||||
return .failure(CommandantError.CommandError(Box(error)))
|
||||
}
|
||||
|
||||
return .success(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ private let MASErrorSource: String = "MASErrorSource"
|
|||
public enum MASErrorCode: Int {
|
||||
case NoError
|
||||
case NotSignedIn
|
||||
case PurchaseError
|
||||
|
||||
var exitCode: Int32 {
|
||||
return Int32(self.rawValue)
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
var downloadQueue = CKDownloadQueue.sharedDownloadQueue()
|
||||
downloadQueue.addObserver(DownloadQueueObserver())
|
||||
|
||||
let registry = CommandRegistry<MASError>()
|
||||
let helpCommand = HelpCommand(registry: registry)
|
||||
|
|
Loading…
Reference in a new issue