mirror of
https://github.com/mas-cli/mas
synced 2024-11-25 21:10:24 +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 */; };
|
ED0F23831B87533A00AE40CD /* ListInstalled.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F23821B87533A00AE40CD /* ListInstalled.swift */; };
|
||||||
ED0F23851B87536A00AE40CD /* ListUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F23841B87536A00AE40CD /* ListUpdates.swift */; };
|
ED0F23851B87536A00AE40CD /* ListUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F23841B87536A00AE40CD /* ListUpdates.swift */; };
|
||||||
ED0F23871B87537200AE40CD /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F23861B87537200AE40CD /* Account.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 */; };
|
ED0F238B1B87569C00AE40CD /* Downloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F238A1B87569C00AE40CD /* Downloader.swift */; };
|
||||||
ED0F238D1B8756E600AE40CD /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F238C1B8756E600AE40CD /* Error.swift */; };
|
ED0F238D1B8756E600AE40CD /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F238C1B8756E600AE40CD /* Error.swift */; };
|
||||||
ED0F23901B87A56F00AE40CD /* ISStoreAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F238F1B87A56F00AE40CD /* ISStoreAccount.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 */; };
|
EDEAA0C01B51CE6200F2FC3F /* StoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDEAA0BF1B51CE6200F2FC3F /* StoreFoundation.framework */; };
|
||||||
EDEAA17D1B5C579100F2FC3F /* CommerceKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDEAA17C1B5C579100F2FC3F /* CommerceKit.framework */; };
|
EDEAA17D1B5C579100F2FC3F /* CommerceKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDEAA17C1B5C579100F2FC3F /* CommerceKit.framework */; };
|
||||||
F5F01044EC3065C6EBAB95D7 /* BoxType.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0E87CFA5E6371893D5B1807 /* BoxType.swift */; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
EDEAA0C41B51CEE400F2FC3F /* CKBook.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKBook.h; sourceTree = "<group>"; };
|
||||||
|
@ -351,8 +353,9 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
ED0F238A1B87569C00AE40CD /* Downloader.swift */,
|
ED0F238A1B87569C00AE40CD /* Downloader.swift */,
|
||||||
ED0F23881B87543D00AE40CD /* DownloadQueueObserver.swift */,
|
|
||||||
ED0F238F1B87A56F00AE40CD /* ISStoreAccount.swift */,
|
ED0F238F1B87A56F00AE40CD /* ISStoreAccount.swift */,
|
||||||
|
ED0F23881B87543D00AE40CD /* PurchaseDownloadObserver.swift */,
|
||||||
|
EDA3BE511B8B84AF00C18D70 /* SSPurchase.swift */,
|
||||||
);
|
);
|
||||||
path = AppStore;
|
path = AppStore;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -637,7 +640,6 @@
|
||||||
F5F01044EC3065C6EBAB95D7 /* BoxType.swift in Sources */,
|
F5F01044EC3065C6EBAB95D7 /* BoxType.swift in Sources */,
|
||||||
21EC092422A3EDFE33B153B8 /* Command.swift in Sources */,
|
21EC092422A3EDFE33B153B8 /* Command.swift in Sources */,
|
||||||
ED0F238B1B87569C00AE40CD /* Downloader.swift in Sources */,
|
ED0F238B1B87569C00AE40CD /* Downloader.swift in Sources */,
|
||||||
ED0F23891B87543D00AE40CD /* DownloadQueueObserver.swift in Sources */,
|
|
||||||
ED0F238D1B8756E600AE40CD /* Error.swift in Sources */,
|
ED0F238D1B8756E600AE40CD /* Error.swift in Sources */,
|
||||||
B80C5DDD38A8F7EB6F320697 /* Errors.swift in Sources */,
|
B80C5DDD38A8F7EB6F320697 /* Errors.swift in Sources */,
|
||||||
5918483F96256CDAC88FF450 /* HelpCommand.swift in Sources */,
|
5918483F96256CDAC88FF450 /* HelpCommand.swift in Sources */,
|
||||||
|
@ -648,7 +650,9 @@
|
||||||
ED031A7C1B5127C00097692E /* main.swift in Sources */,
|
ED031A7C1B5127C00097692E /* main.swift in Sources */,
|
||||||
DE39BCA91D1BC3D876711677 /* MutableBox.swift in Sources */,
|
DE39BCA91D1BC3D876711677 /* MutableBox.swift in Sources */,
|
||||||
92828DCD99CED47F54242776 /* Option.swift in Sources */,
|
92828DCD99CED47F54242776 /* Option.swift in Sources */,
|
||||||
|
ED0F23891B87543D00AE40CD /* PurchaseDownloadObserver.swift in Sources */,
|
||||||
1CC607DA6B900AA3FEC3F6D8 /* Result.swift in Sources */,
|
1CC607DA6B900AA3FEC3F6D8 /* Result.swift in Sources */,
|
||||||
|
EDA3BE521B8B84AF00C18D70 /* SSPurchase.swift in Sources */,
|
||||||
7858BCFB4D5A4251DE998CE4 /* Switch.swift in Sources */,
|
7858BCFB4D5A4251DE998CE4 /* Switch.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|
|
@ -6,25 +6,34 @@
|
||||||
// Copyright (c) 2015 Andrew Naylor. All rights reserved.
|
// 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) {
|
if let account = ISStoreAccount.primaryAccount {
|
||||||
let buyParameters = "productType=C&price=0&salableAdamId=\(adamId)&pricingParameters=STDRDL"
|
let group = dispatch_group_create()
|
||||||
let purchase = SSPurchase()
|
let purchase = SSPurchase(adamId: adamId, account: account)
|
||||||
purchase.buyParameters = buyParameters
|
|
||||||
purchase.itemIdentifier = adamId
|
|
||||||
purchase.accountIdentifier = primaryAccount().dsID
|
|
||||||
purchase.appleID = primaryAccount().identifier
|
|
||||||
|
|
||||||
let downloadMetadata = SSDownloadMetadata()
|
var purchaseError: MASError?
|
||||||
downloadMetadata.kind = "software"
|
|
||||||
downloadMetadata.itemIdentifier = adamId
|
|
||||||
|
|
||||||
purchase.downloadMetadata = downloadMetadata
|
purchase.perform { purchase, completed, error, response in
|
||||||
|
if completed {
|
||||||
|
let observer = PurchaseDownloadObserver(purchase: purchase)
|
||||||
|
observer.onCompletion {
|
||||||
|
dispatch_group_leave(group)
|
||||||
|
}
|
||||||
|
|
||||||
let purchaseController = CKPurchaseController.sharedPurchaseController()
|
CKDownloadQueue.sharedDownloadQueue().addObserver(observer)
|
||||||
purchaseController.performPurchase(purchase, withOptions: 0, completionHandler: completion)
|
}
|
||||||
while true {
|
else {
|
||||||
NSRunLoop.mainRunLoop().runMode(NSDefaultRunLoopMode, beforeDate: NSDate(timeIntervalSinceNow: 10))
|
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
|
// mas-cli
|
||||||
//
|
//
|
||||||
// Created by Andrew Naylor on 21/08/2015.
|
// Created by Andrew Naylor on 21/08/2015.
|
||||||
|
@ -8,9 +8,15 @@
|
||||||
|
|
||||||
let csi = "\u{001B}["
|
let csi = "\u{001B}["
|
||||||
|
|
||||||
@objc class DownloadQueueObserver: CKDownloadQueueObserver {
|
@objc class PurchaseDownloadObserver: CKDownloadQueueObserver {
|
||||||
|
let purchase: SSPurchase
|
||||||
|
var completionHandler: (() -> ())?
|
||||||
var started = false
|
var started = false
|
||||||
|
|
||||||
|
init(purchase: SSPurchase) {
|
||||||
|
self.purchase = purchase
|
||||||
|
}
|
||||||
|
|
||||||
func downloadQueue(queue: CKDownloadQueue, statusChangedForDownload download: SSDownload!) {
|
func downloadQueue(queue: CKDownloadQueue, statusChangedForDownload download: SSDownload!) {
|
||||||
if !started {
|
if !started {
|
||||||
return
|
return
|
||||||
|
@ -26,7 +32,13 @@ let csi = "\u{001B}["
|
||||||
func downloadQueue(queue: CKDownloadQueue, changedWithRemoval download: SSDownload!) {
|
func downloadQueue(queue: CKDownloadQueue, changedWithRemoval download: SSDownload!) {
|
||||||
println("")
|
println("")
|
||||||
println("==> Installed " + download.metadata.title)
|
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"
|
let function = "Install from the Mac App Store"
|
||||||
|
|
||||||
func run(mode: CommandMode) -> Result<(), CommandantError<MASError>> {
|
func run(mode: CommandMode) -> Result<(), CommandantError<MASError>> {
|
||||||
return InstallOptions.evaluate(mode).map { options in
|
let optionsResult = InstallOptions.evaluate(mode)
|
||||||
download(options.appId) { (purchase, completed, error, response) in
|
|
||||||
|
|
||||||
|
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 {
|
public enum MASErrorCode: Int {
|
||||||
case NoError
|
case NoError
|
||||||
case NotSignedIn
|
case NotSignedIn
|
||||||
|
case PurchaseError
|
||||||
|
|
||||||
var exitCode: Int32 {
|
var exitCode: Int32 {
|
||||||
return Int32(self.rawValue)
|
return Int32(self.rawValue)
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
var downloadQueue = CKDownloadQueue.sharedDownloadQueue()
|
|
||||||
downloadQueue.addObserver(DownloadQueueObserver())
|
|
||||||
|
|
||||||
let registry = CommandRegistry<MASError>()
|
let registry = CommandRegistry<MASError>()
|
||||||
let helpCommand = HelpCommand(registry: registry)
|
let helpCommand = HelpCommand(registry: registry)
|
||||||
|
|
Loading…
Reference in a new issue