diff --git a/Brewfile b/Brewfile index 60ebd6d9..d2604292 100644 --- a/Brewfile +++ b/Brewfile @@ -1,4 +1,4 @@ -brew "actionlint" # 1.7.9 +brew "actionlint" # 1.7.10 brew "gh" # 2.83.2 brew "git" # 2.52.0 brew "ipsw" # 3.1.647 diff --git a/Sources/mas/Commands/Get.swift b/Sources/mas/Commands/Get.swift index fce63737..972d29ac 100644 --- a/Sources/mas/Commands/Get.swift +++ b/Sources/mas/Commands/Get.swift @@ -19,11 +19,11 @@ extension MAS { @OptionGroup private var forceOptionGroup: ForceOptionGroup @OptionGroup - private var requiredAppIDsOptionGroup: RequiredAppIDsOptionGroup + private var catalogAppIDsOptionGroup: CatalogAppIDsOptionGroup func run() async throws { try await AppStore.get.apps( - withAppIDs: requiredAppIDsOptionGroup.appIDs, + withAppIDs: catalogAppIDsOptionGroup.appIDs, force: forceOptionGroup.force, installedApps: try await installedApps, lookupAppFromAppID: lookup(appID:), diff --git a/Sources/mas/Commands/Home.swift b/Sources/mas/Commands/Home.swift index 234c80ef..f23370b3 100644 --- a/Sources/mas/Commands/Home.swift +++ b/Sources/mas/Commands/Home.swift @@ -20,7 +20,7 @@ extension MAS { ) @OptionGroup - private var requiredAppIDsOptionGroup: RequiredAppIDsOptionGroup + private var catalogAppIDsOptionGroup: CatalogAppIDsOptionGroup func run() async { await run(lookupAppFromAppID: lookup(appID:)) @@ -28,7 +28,7 @@ extension MAS { private func run(lookupAppFromAppID: (AppID) async throws -> CatalogApp) async { await run( - catalogApps: await requiredAppIDsOptionGroup.appIDs.lookupCatalogApps(lookupAppFromAppID: lookupAppFromAppID), + catalogApps: await catalogAppIDsOptionGroup.appIDs.lookupCatalogApps(lookupAppFromAppID: lookupAppFromAppID), ) } diff --git a/Sources/mas/Commands/Install.swift b/Sources/mas/Commands/Install.swift index c9c2b6f2..ad8f2e78 100644 --- a/Sources/mas/Commands/Install.swift +++ b/Sources/mas/Commands/Install.swift @@ -18,11 +18,11 @@ extension MAS { @OptionGroup private var forceOptionGroup: ForceOptionGroup @OptionGroup - private var requiredAppIDsOptionGroup: RequiredAppIDsOptionGroup + private var catalogAppIDsOptionGroup: CatalogAppIDsOptionGroup func run() async throws { try await AppStore.install.apps( - withAppIDs: requiredAppIDsOptionGroup.appIDs, + withAppIDs: catalogAppIDsOptionGroup.appIDs, force: forceOptionGroup.force, installedApps: try await installedApps, lookupAppFromAppID: lookup(appID:), diff --git a/Sources/mas/Commands/List.swift b/Sources/mas/Commands/List.swift index 79afb73e..a20990ca 100644 --- a/Sources/mas/Commands/List.swift +++ b/Sources/mas/Commands/List.swift @@ -16,14 +16,14 @@ extension MAS { ) @OptionGroup - private var optionalAppIDsOptionGroup: OptionalAppIDsOptionGroup + private var installedAppIDsOptionGroup: InstalledAppIDsOptionGroup func run() async throws { run(installedApps: try await installedApps) } func run(installedApps: [InstalledApp]) { - let installedApps = installedApps.filter(for: optionalAppIDsOptionGroup.appIDs) + let installedApps = installedApps.filter(for: installedAppIDsOptionGroup.appIDs) guard let maxADAMIDLength = installedApps.map({ String(describing: $0.adamID).count }).max(), let maxNameLength = installedApps.map(\.name.count).max() diff --git a/Sources/mas/Commands/Lookup.swift b/Sources/mas/Commands/Lookup.swift index 6140f3f5..18aa28a2 100644 --- a/Sources/mas/Commands/Lookup.swift +++ b/Sources/mas/Commands/Lookup.swift @@ -21,14 +21,14 @@ extension MAS { ) @OptionGroup - private var requiredAppIDsOptionGroup: RequiredAppIDsOptionGroup + private var catalogAppIDsOptionGroup: CatalogAppIDsOptionGroup func run() async { await run(lookupAppFromAppID: lookup(appID:)) } private func run(lookupAppFromAppID: (AppID) async throws -> CatalogApp) async { - run(catalogApps: await requiredAppIDsOptionGroup.appIDs.lookupCatalogApps(lookupAppFromAppID: lookupAppFromAppID)) + run(catalogApps: await catalogAppIDsOptionGroup.appIDs.lookupCatalogApps(lookupAppFromAppID: lookupAppFromAppID)) } func run(catalogApps: [CatalogApp]) { // swiftformat:disable:this organizeDeclarations diff --git a/Sources/mas/Commands/OptionGroups/RequiredAppIDsOptionGroup.swift b/Sources/mas/Commands/OptionGroups/CatalogAppIDsOptionGroup.swift similarity index 81% rename from Sources/mas/Commands/OptionGroups/RequiredAppIDsOptionGroup.swift rename to Sources/mas/Commands/OptionGroups/CatalogAppIDsOptionGroup.swift index 0b7e38c7..3caff9c6 100644 --- a/Sources/mas/Commands/OptionGroups/RequiredAppIDsOptionGroup.swift +++ b/Sources/mas/Commands/OptionGroups/CatalogAppIDsOptionGroup.swift @@ -1,5 +1,5 @@ // -// RequiredAppIDsOptionGroup.swift +// CatalogAppIDsOptionGroup.swift // mas // // Copyright © 2025 mas-cli. All rights reserved. @@ -7,7 +7,7 @@ internal import ArgumentParser -struct RequiredAppIDsOptionGroup: ParsableArguments { +struct CatalogAppIDsOptionGroup: ParsableArguments { @OptionGroup private var forceBundleIDOptionGroup: ForceBundleIDOptionGroup @Argument(help: ArgumentHelp("App ID", valueName: "app-id")) diff --git a/Sources/mas/Commands/OptionGroups/OptionalAppIDsOptionGroup.swift b/Sources/mas/Commands/OptionGroups/InstalledAppIDsOptionGroup.swift similarity index 81% rename from Sources/mas/Commands/OptionGroups/OptionalAppIDsOptionGroup.swift rename to Sources/mas/Commands/OptionGroups/InstalledAppIDsOptionGroup.swift index fb67f3a3..54c035d3 100644 --- a/Sources/mas/Commands/OptionGroups/OptionalAppIDsOptionGroup.swift +++ b/Sources/mas/Commands/OptionGroups/InstalledAppIDsOptionGroup.swift @@ -1,5 +1,5 @@ // -// OptionalAppIDsOptionGroup.swift +// InstalledAppIDsOptionGroup.swift // mas // // Copyright © 2025 mas-cli. All rights reserved. @@ -7,7 +7,7 @@ internal import ArgumentParser -struct OptionalAppIDsOptionGroup: ParsableArguments { +struct InstalledAppIDsOptionGroup: ParsableArguments { @OptionGroup private var forceBundleIDOptionGroup: ForceBundleIDOptionGroup @Argument(help: ArgumentHelp("App ID", valueName: "app-id")) diff --git a/Sources/mas/Commands/Outdated.swift b/Sources/mas/Commands/Outdated.swift index a0711335..6469101b 100644 --- a/Sources/mas/Commands/Outdated.swift +++ b/Sources/mas/Commands/Outdated.swift @@ -21,7 +21,7 @@ extension MAS { @OptionGroup private var verboseOptionGroup: VerboseOptionGroup @OptionGroup - private var optionalAppIDsOptionGroup: OptionalAppIDsOptionGroup + private var installedAppIDsOptionGroup: InstalledAppIDsOptionGroup func run() async throws { await run(installedApps: try await installedApps.filter(!\.isTestFlight), lookupAppFromAppID: lookup(appID:)) @@ -34,7 +34,7 @@ extension MAS { lookupAppFromAppID: lookupAppFromAppID, accurateOptionGroup: accurateOptionGroup, verboseOptionGroup: verboseOptionGroup, - optionalAppIDsOptionGroup: optionalAppIDsOptionGroup, + installedAppIDsOptionGroup: installedAppIDsOptionGroup, ), ) } diff --git a/Sources/mas/Commands/Seller.swift b/Sources/mas/Commands/Seller.swift index 19ab8d21..67c806d5 100644 --- a/Sources/mas/Commands/Seller.swift +++ b/Sources/mas/Commands/Seller.swift @@ -21,7 +21,7 @@ extension MAS { ) @OptionGroup - private var requiredAppIDsOptionGroup: RequiredAppIDsOptionGroup + private var catalogAppIDsOptionGroup: CatalogAppIDsOptionGroup func run() async { await run(lookupAppFromAppID: lookup(appID:)) @@ -29,7 +29,7 @@ extension MAS { private func run(lookupAppFromAppID: (AppID) async throws -> CatalogApp) async { await run( - catalogApps: await requiredAppIDsOptionGroup.appIDs.lookupCatalogApps(lookupAppFromAppID: lookupAppFromAppID), + catalogApps: await catalogAppIDsOptionGroup.appIDs.lookupCatalogApps(lookupAppFromAppID: lookupAppFromAppID), ) } diff --git a/Sources/mas/Commands/Uninstall.swift b/Sources/mas/Commands/Uninstall.swift index 71b303be..898d24e9 100644 --- a/Sources/mas/Commands/Uninstall.swift +++ b/Sources/mas/Commands/Uninstall.swift @@ -18,17 +18,21 @@ extension MAS { ) /// Flag indicating that uninstall shouldn't be performed. - @Flag(help: "Perform dry run") - private var dryRun = false + @Flag(name: .customLong("dry-run"), help: "Perform dry run") + private var isPerformingDryRun = false + @Flag(name: .customLong("all"), help: "Uninstall all App Store apps") + private var isUninstallingAll = false @OptionGroup - private var requiredAppIDsOptionGroup: RequiredAppIDsOptionGroup + private var installedAppIDsOptionGroup: InstalledAppIDsOptionGroup func run() async throws { try run(installedApps: try await installedApps) } private func run(installedApps: [InstalledApp]) throws { - let uninstallingAppByPath = requiredAppIDsOptionGroup.appIDs // swiftformat:disable indent + let uninstallingAppByPath = ( + isUninstallingAll ? installedApps.map { AppID.adamID($0.adamID) } : installedAppIDsOptionGroup.appIDs, + ) // swiftformat:disable indent .reduce(into: OrderedDictionary()) { uninstallingAppByPath, appID in let uninstallingApps = installedApps.filter { $0.matches(appID) } guard !uninstallingApps.isEmpty else { @@ -43,7 +47,7 @@ extension MAS { guard !uninstallingAppByPath.isEmpty else { // swiftformat:enable indent return } - guard !dryRun else { + guard !isPerformingDryRun else { printer.notice("Dry run. A wet run would uninstall:\n") for appPath in uninstallingAppByPath.keys { printer.info(appPath) diff --git a/Sources/mas/Commands/Update.swift b/Sources/mas/Commands/Update.swift index d8dbf6a4..1ade6cbf 100644 --- a/Sources/mas/Commands/Update.swift +++ b/Sources/mas/Commands/Update.swift @@ -24,7 +24,7 @@ extension MAS { @OptionGroup private var verboseOptionGroup: VerboseOptionGroup @OptionGroup - private var optionalAppIDsOptionGroup: OptionalAppIDsOptionGroup + private var installedAppIDsOptionGroup: InstalledAppIDsOptionGroup func run() async throws { try await run(installedApps: try await installedApps.filter(!\.isTestFlight), lookupAppFromAppID: lookup(appID:)) @@ -34,13 +34,13 @@ extension MAS { async throws { // swiftformat:disable:this indent try await run( outdatedApps: forceOptionGroup.force // swiftformat:disable:next indent - ? installedApps.filter(for: optionalAppIDsOptionGroup.appIDs).map { ($0, "") } + ? installedApps.filter(for: installedAppIDsOptionGroup.appIDs).map { ($0, "") } : await outdatedApps( installedApps: installedApps, lookupAppFromAppID: lookupAppFromAppID, accurateOptionGroup: accurateOptionGroup, verboseOptionGroup: verboseOptionGroup, - optionalAppIDsOptionGroup: optionalAppIDsOptionGroup, + installedAppIDsOptionGroup: installedAppIDsOptionGroup, ), ) } diff --git a/Sources/mas/Models/OutdatedApp.swift b/Sources/mas/Models/OutdatedApp.swift index 4dbfcb44..0baa98c2 100644 --- a/Sources/mas/Models/OutdatedApp.swift +++ b/Sources/mas/Models/OutdatedApp.swift @@ -107,13 +107,13 @@ func outdatedApps( lookupAppFromAppID: (AppID) async throws -> CatalogApp, accurateOptionGroup: AccurateOptionGroup, verboseOptionGroup: VerboseOptionGroup, - optionalAppIDsOptionGroup: OptionalAppIDsOptionGroup, + installedAppIDsOptionGroup: InstalledAppIDsOptionGroup, ) async -> [OutdatedApp] { await accurateOptionGroup.outdatedApps( accurate: { shouldIgnoreUnknownApps in await withTaskGroup { group in let installedApps = await installedApps - .filter(for: optionalAppIDsOptionGroup.appIDs) // swiftformat:disable indent + .filter(for: installedAppIDsOptionGroup.appIDs) // swiftformat:disable indent .filterOutApps( unknownTo: lookupAppFromAppID, if: shouldIgnoreUnknownApps, @@ -147,7 +147,7 @@ func outdatedApps( }, inaccurate: { await installedApps - .filter(for: optionalAppIDsOptionGroup.appIDs) // swiftformat:disable indent + .filter(for: installedAppIDsOptionGroup.appIDs) // swiftformat:disable indent .compactMap { installedApp in do { let catalogApp = try await lookupAppFromAppID(.adamID(installedApp.adamID)) diff --git a/Sources/mas/Utilities/Version+SemVer.swift b/Sources/mas/Utilities/Version+SemVer.swift index f2f52cbb..d72394bd 100644 --- a/Sources/mas/Utilities/Version+SemVer.swift +++ b/Sources/mas/Utilities/Version+SemVer.swift @@ -157,7 +157,7 @@ struct UniversalSemVer: SemVerSyntax { } } -private extension BigInt { +private extension BigUInt { func compare(to that: Self) -> ComparisonResult { self < that ? .orderedAscending : self == that ? .orderedSame : .orderedDescending } @@ -176,8 +176,8 @@ private extension String { range: Range? = nil, locale: Locale? = nil, ) -> ComparisonResult { - let selfInteger = BigInt(self) - let thatInteger = BigInt(that) + let selfInteger = BigUInt(self) + let thatInteger = BigUInt(that) return selfInteger.map { thatInteger.map($0.compare(to:)) ?? .orderedAscending } ?? thatInteger.map { _ in .orderedDescending } // swiftformat:disable:this indent ?? compare(that, options: mask, range: range, locale: locale) // swiftformat:disable:this indent