Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Sources/removemacai/SelfTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
16 changes: 15 additions & 1 deletion Sources/removemacai/Storage.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import AppKit
import Foundation

/// Space RemoveMacAI can give back. Files go to the Trash, so nothing is
Expand Down Expand Up @@ -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] = []
Expand Down Expand Up @@ -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(
Expand Down