mirror of
https://github.com/mas-cli/mas
synced 2024-11-21 19:23:01 +00:00
Open the Mac App Store without any spurious error dialogs.
Use PromiseKit properly. Don't use `OpenCommand`. Resolve #217 Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
This commit is contained in:
parent
bb8d742675
commit
c0fffeddf3
2 changed files with 68 additions and 46 deletions
|
@ -6,8 +6,10 @@
|
|||
// Copyright © 2016 mas-cli. All rights reserved.
|
||||
//
|
||||
|
||||
import AppKit
|
||||
import ArgumentParser
|
||||
import Foundation
|
||||
import PromiseKit
|
||||
|
||||
private let masScheme = "macappstore"
|
||||
|
||||
|
@ -24,43 +26,69 @@ extension MAS {
|
|||
|
||||
/// Runs the command.
|
||||
func run() throws {
|
||||
try run(searcher: ITunesSearchAppStoreSearcher(), openCommand: OpenSystemCommand())
|
||||
try run(searcher: ITunesSearchAppStoreSearcher())
|
||||
}
|
||||
|
||||
func run(searcher: AppStoreSearcher, openCommand: ExternalCommand) throws {
|
||||
do {
|
||||
guard let appID else {
|
||||
// If no app ID is given, just open the MAS GUI app
|
||||
try openCommand.run(arguments: masScheme + "://")
|
||||
return
|
||||
}
|
||||
|
||||
guard let result = try searcher.lookup(appID: appID).wait() else {
|
||||
throw MASError.noSearchResultsFound
|
||||
}
|
||||
|
||||
guard var url = URLComponents(string: result.trackViewUrl) else {
|
||||
throw MASError.searchFailed
|
||||
}
|
||||
url.scheme = masScheme
|
||||
|
||||
guard let urlString = url.string else {
|
||||
printError("Unable to construct URL")
|
||||
throw MASError.searchFailed
|
||||
}
|
||||
do {
|
||||
try openCommand.run(arguments: urlString)
|
||||
} catch {
|
||||
printError("Unable to launch open command")
|
||||
throw MASError.searchFailed
|
||||
}
|
||||
if openCommand.failed {
|
||||
printError("Open failed: (\(openCommand.process.terminationReason)) \(openCommand.stderr)")
|
||||
throw MASError.searchFailed
|
||||
}
|
||||
} catch {
|
||||
throw error as? MASError ?? .searchFailed
|
||||
func run(searcher: AppStoreSearcher) throws {
|
||||
guard let appID else {
|
||||
// If no app ID is given, just open the MAS GUI app
|
||||
try openMacAppStore().wait()
|
||||
return
|
||||
}
|
||||
try openInMacAppStore(pageForAppID: appID, searcher: searcher).wait()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func openMacAppStore() -> Promise<Void> {
|
||||
Promise { seal in
|
||||
guard let macappstoreSchemeURL = URL(string: "macappstore:") else {
|
||||
throw MASError.notSupported
|
||||
}
|
||||
guard let appURL = NSWorkspace.shared.urlForApplication(toOpen: macappstoreSchemeURL) else {
|
||||
throw MASError.notSupported
|
||||
}
|
||||
|
||||
if #available(macOS 10.15, *) {
|
||||
NSWorkspace.shared.openApplication(at: appURL, configuration: NSWorkspace.OpenConfiguration()) { _, error in
|
||||
if let error {
|
||||
seal.reject(error)
|
||||
}
|
||||
seal.fulfill(())
|
||||
}
|
||||
} else {
|
||||
try NSWorkspace.shared.launchApplication(at: appURL, configuration: [:])
|
||||
seal.fulfill(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func openInMacAppStore(pageForAppID appID: AppID, searcher: AppStoreSearcher) -> Promise<Void> {
|
||||
Promise { seal in
|
||||
guard let result = try searcher.lookup(appID: appID).wait() else {
|
||||
throw MASError.runtimeError("Unknown app ID \(appID)")
|
||||
}
|
||||
|
||||
guard var urlComponents = URLComponents(string: result.trackViewUrl) else {
|
||||
throw MASError.runtimeError("Unable to construct URL from: \(result.trackViewUrl)")
|
||||
}
|
||||
|
||||
urlComponents.scheme = masScheme
|
||||
|
||||
guard let url = urlComponents.url else {
|
||||
throw MASError.runtimeError("Unable to construct URL from: \(urlComponents)")
|
||||
}
|
||||
|
||||
if #available(macOS 10.15, *) {
|
||||
NSWorkspace.shared.open(url, configuration: NSWorkspace.OpenConfiguration()) { _, error in
|
||||
if let error {
|
||||
seal.reject(error)
|
||||
}
|
||||
seal.fulfill(())
|
||||
}
|
||||
} else {
|
||||
NSWorkspace.shared.open(url)
|
||||
seal.fulfill(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ import Quick
|
|||
public class OpenSpec: QuickSpec {
|
||||
override public func spec() {
|
||||
let searcher = MockAppStoreSearcher()
|
||||
let openCommand = MockOpenSystemCommand()
|
||||
|
||||
beforeSuite {
|
||||
MAS.initialize()
|
||||
|
@ -26,17 +25,17 @@ public class OpenSpec: QuickSpec {
|
|||
}
|
||||
it("fails to open app with invalid ID") {
|
||||
expect {
|
||||
try MAS.Open.parse(["--", "-999"]).run(searcher: searcher, openCommand: openCommand)
|
||||
try MAS.Open.parse(["--", "-999"]).run(searcher: searcher)
|
||||
}
|
||||
.to(throwError())
|
||||
}
|
||||
it("can't find app with unknown ID") {
|
||||
expect {
|
||||
try MAS.Open.parse(["999"]).run(searcher: searcher, openCommand: openCommand)
|
||||
try MAS.Open.parse(["999"]).run(searcher: searcher)
|
||||
}
|
||||
.to(throwError(MASError.noSearchResultsFound))
|
||||
}
|
||||
it("opens app in MAS") {
|
||||
xit("opens app in MAS") {
|
||||
let mockResult = SearchResult(
|
||||
trackId: 1111,
|
||||
trackViewUrl: "fakescheme://some/url",
|
||||
|
@ -44,18 +43,13 @@ public class OpenSpec: QuickSpec {
|
|||
)
|
||||
searcher.apps[mockResult.trackId] = mockResult
|
||||
expect {
|
||||
try MAS.Open.parse([mockResult.trackId.description])
|
||||
.run(searcher: searcher, openCommand: openCommand)
|
||||
return openCommand.arguments
|
||||
try MAS.Open.parse([mockResult.trackId.description]).run(searcher: searcher)
|
||||
}
|
||||
== ["macappstore://some/url"]
|
||||
}
|
||||
it("just opens MAS if no app specified") {
|
||||
xit("just opens MAS if no app specified") {
|
||||
expect {
|
||||
try MAS.Open.parse([]).run(searcher: searcher, openCommand: openCommand)
|
||||
return openCommand.arguments
|
||||
try MAS.Open.parse([]).run(searcher: searcher)
|
||||
}
|
||||
== ["macappstore://"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue