diff --git a/Sources/removemacai/SelfTest.swift b/Sources/removemacai/SelfTest.swift index e260482..d284653 100644 --- a/Sources/removemacai/SelfTest.swift +++ b/Sources/removemacai/SelfTest.swift @@ -217,6 +217,9 @@ func selfTest() -> Bool { program: "/Library/PrivilegedHelperTools/dev.orbstack.OrbStack.privhelper", system: true) check(script.owner == "sync.sh" && helper.owner == "OrbStack", "background items are named after what they run") + check(Storage.soundLibraryUsers(["com.apple.finder": "Finder", "com.example.missing": "Missing"]) == ["Finder"], + "apps that share the sound library are found by bundle identifier") + print(failed == 0 ? Term.green("all checks passed") : Term.red("\(failed) failed")) return failed == 0 } diff --git a/Sources/removemacai/Storage.swift b/Sources/removemacai/Storage.swift index 59aa3fe..a327216 100644 --- a/Sources/removemacai/Storage.swift +++ b/Sources/removemacai/Storage.swift @@ -1,3 +1,4 @@ +import AppKit import Foundation /// Space RemoveMacAI can give back. Files go to the Trash, so nothing is @@ -38,6 +39,16 @@ enum Storage { ("pages", "Pages", []), ] + /// Apps that share GarageBand's sound library, by bundle identifier. + static let soundLibraryApps = ["com.apple.logic10": "Logic Pro", "com.apple.mainstage3": "MainStage"] + + /// The sound library apps installed anywhere Launch Services knows of, + /// including an external disk. + static func soundLibraryUsers(_ apps: [String: String] = soundLibraryApps) -> [String] { + apps.filter { !NSWorkspace.shared.urlsForApplications(withBundleIdentifier: $0.key).isEmpty } + .map(\.value).sorted() + } + /// Finds what can go and how big it is. Slow on big caches; call it off the main thread. static func scan() -> [StorageItem] { var items: [StorageItem] = [] @@ -90,13 +101,16 @@ enum Storage { caveat: "Quit your apps first. Apple's own caches are left alone.", paths: children(home + "/Library/Caches").filter { !($0 as NSString).lastPathComponent.hasPrefix("com.apple.") })) + let sharing = soundLibraryUsers() for app in appleApps { let path = "/Applications/\(app.app).app" guard FileManager.default.fileExists(atPath: path) else { continue } + let keepExtra = !app.extra.isEmpty && !sharing.isEmpty items.append(files( id: app.id, title: app.app, detail: "One of Apple's optional apps. It reinstalls free from the App Store.", - paths: [path] + app.extra.filter { FileManager.default.fileExists(atPath: $0) })) + caveat: keepExtra ? "Its sound library stays, because \(sharing.joined(separator: " and ")) uses it too." : nil, + paths: [path] + (keepExtra ? [] : app.extra.filter { FileManager.default.fileExists(atPath: $0) }))) } var snapshots = StorageItem(