Refactor AppLibrary.installedApp(…) as AppLibrary.installedApps(…)

because multiple installed apps can have the same app ID or app name.

Partial #313

Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
This commit is contained in:
Ross Goldberg 2024-10-23 12:51:59 -04:00
parent 4e0a471d81
commit 222646159d
No known key found for this signature in database
6 changed files with 30 additions and 26 deletions

View file

@ -29,8 +29,8 @@ extension Mas {
func run(appLibrary: AppLibrary) throws {
// Try to download applications with given identifiers and collect results
let appIDs = appIDs.filter { appID in
if let product = appLibrary.installedApp(withAppID: appID), !force {
printWarning("\(product.appName) is already installed")
if let appName = appLibrary.installedApps(withAppID: appID).first?.appName, !force {
printWarning("\(appName) is already installed")
return false
}

View file

@ -58,8 +58,8 @@ extension Mas {
/// - Throws: Any error that occurs while attempting to install the app.
private func install(appID: AppID, appLibrary: AppLibrary) throws {
// Try to download applications with given identifiers and collect results
if let product = appLibrary.installedApp(withAppID: appID), !force {
printWarning("\(product.appName) is already installed")
if let appName = appLibrary.installedApps(withAppID: appID).first?.appName, !force {
printWarning("\(appName) is already installed")
} else {
do {
try downloadAll([appID]).wait()

View file

@ -26,8 +26,8 @@ extension Mas {
func run(appLibrary: AppLibrary) throws {
// Try to download applications with given identifiers and collect results
let appIDs = appIDs.filter { appID in
if let product = appLibrary.installedApp(withAppID: appID) {
printWarning("\(product.appName) has already been purchased.")
if let appName = appLibrary.installedApps(withAppID: appID).first?.appName {
printWarning("\(appName) has already been purchased.")
return false
}

View file

@ -7,8 +7,7 @@
//
import ArgumentParser
import CommerceKit
import StoreFoundation
import Foundation
extension Mas {
/// Command which uninstalls apps managed by the Mac App Store.
@ -29,16 +28,21 @@ extension Mas {
}
func run(appLibrary: AppLibrary) throws {
guard let product = appLibrary.installedApp(withAppID: appID) else {
let installedApps = appLibrary.installedApps(withAppID: appID)
guard !installedApps.isEmpty else {
throw MASError.notInstalled
}
if dryRun {
printInfo("\(product.appName) \(product.bundlePath)")
for installedApp in installedApps {
printInfo("\(installedApp.appName) \(installedApp.bundlePath)")
}
printInfo("(not removed, dry run)")
} else {
do {
try appLibrary.uninstallApp(app: product)
for installedApp in installedApps {
try appLibrary.uninstallApp(app: installedApp)
}
} catch {
throw MASError.uninstallFailed
}

View file

@ -58,14 +58,14 @@ extension Mas {
let apps =
appIDs.isEmpty
? appLibrary.installedApps
: appIDs.compactMap { appID in
: appIDs.flatMap { appID in
if let appID = AppID(appID) {
// argument is an AppID, lookup app by id using argument
return appLibrary.installedApp(withAppID: appID)
// argument is an AppID, lookup apps by id using argument
return appLibrary.installedApps(withAppID: appID)
}
// argument is not an AppID, lookup app by name using argument
return appLibrary.installedApp(named: appID)
// argument is not an AppID, lookup apps by name using argument
return appLibrary.installedApps(named: appID)
}
let promises = apps.map { installedApp in

View file

@ -22,20 +22,20 @@ protocol AppLibrary {
/// Common logic
extension AppLibrary {
/// Finds an app for appID.
/// Finds all installed instances of apps whose app ID is `appID`.
///
/// - Parameter appID: app ID for app.
/// - Returns: SoftwareProduct of app if found; nil otherwise.
func installedApp(withAppID appID: AppID) -> SoftwareProduct? {
/// - Parameter appID: app ID for app(s).
/// - Returns: [SoftwareProduct] of matching apps.
func installedApps(withAppID appID: AppID) -> [SoftwareProduct] {
let appID = NSNumber(value: appID)
return installedApps.first { $0.itemIdentifier == appID }
return installedApps.filter { $0.itemIdentifier == appID }
}
/// Finds an app by name.
/// Finds all installed instances of apps whose name is `appName`.
///
/// - Parameter appName: Full title of an app.
/// - Returns: Software Product of app if found; nil otherwise.
func installedApp(named appName: String) -> SoftwareProduct? {
installedApps.first { $0.appName == appName }
/// - Parameter appName: Full name of app(s).
/// - Returns: [SoftwareProduct] of matching apps.
func installedApps(named appName: String) -> [SoftwareProduct] {
installedApps.filter { $0.appName == appName }
}
}