Skip to content

Commit 9721e5d

Browse files
committed
Index in Spotlight folders that should contain App Store apps but that aren't indexed as such in Spotlight.
Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
1 parent 38f1bc9 commit 9721e5d

3 files changed

Lines changed: 73 additions & 17 deletions

File tree

.swiftlint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ file_length:
4848
ignore_comment_only_lines: true
4949
warning: 500
5050
file_name:
51-
excluded: [Group.swift, Process.swift, User.swift]
51+
excluded: [Group.swift, InstalledApp+Spotlight.swift, Process.swift, User.swift]
5252
file_types_order:
5353
order:
5454
- main_type

Sources/mas/Controllers/InstalledApp+Spotlight.swift

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,32 @@ private import Atomics
99
private import Foundation
1010
private import ObjectiveC
1111

12+
private extension URL {
13+
var installedAppURLs: [URL] {
14+
FileManager.default // swiftformat:disable indent
15+
.enumerator(at: self, includingPropertiesForKeys: [.isDirectoryKey], options: [.skipsHiddenFiles])
16+
.map { enumerator in
17+
enumerator.compactMap { item in
18+
guard
19+
let url = item as? URL,
20+
(try? url.resourceValues(forKeys: [.isDirectoryKey]).isDirectory) == true,
21+
url.lastPathComponent == "Contents"
22+
else {
23+
return nil as URL?
24+
}
25+
26+
enumerator.skipDescendants()
27+
return
28+
(try? url.appending(path: "_MASReceipt/receipt", directoryHint: .notDirectory).checkResourceIsReachable())
29+
== true
30+
? url.deletingLastPathComponent()
31+
: nil
32+
}
33+
}
34+
?? []
35+
} // swiftformat:enable indent
36+
}
37+
1238
var installedApps: [InstalledApp] {
1339
get async throws {
1440
try await mas.installedApps(matching: "kMDItemAppStoreAdamID LIKE '*'")
@@ -53,22 +79,52 @@ func installedApps(matching metadataQuery: String) async throws -> [InstalledApp
5379

5480
query.stop()
5581

56-
continuation.resume(
57-
returning: query.results
58-
.compactMap { result in // swiftformat:disable indent
59-
(result as? NSMetadataItem).map { item in
60-
InstalledApp(
61-
adamID: item.value(forAttribute: "kMDItemAppStoreAdamID") as? ADAMID ?? 0,
62-
bundleID: item.value(forAttribute: NSMetadataItemCFBundleIdentifierKey) as? String ?? "",
63-
name: (item.value(forAttribute: "_kMDItemDisplayNameWithExtensions") as? String ?? "")
64-
.removingSuffix(".app"),
65-
path: item.value(forAttribute: NSMetadataItemPathKey) as? String ?? "",
66-
version: item.value(forAttribute: NSMetadataItemVersionKey) as? String ?? "",
67-
)
82+
let installedApps = query.results
83+
.compactMap { result in // swiftformat:disable indent
84+
(result as? NSMetadataItem).map { item in
85+
InstalledApp(
86+
adamID: item.value(forAttribute: "kMDItemAppStoreAdamID") as? ADAMID ?? 0,
87+
bundleID: item.value(forAttribute: NSMetadataItemCFBundleIdentifierKey) as? String ?? "",
88+
name: (item.value(forAttribute: "_kMDItemDisplayNameWithExtensions") as? String ?? "")
89+
.removingSuffix(".app"),
90+
path: item.value(forAttribute: NSMetadataItemPathKey) as? String ?? "",
91+
version: item.value(forAttribute: NSMetadataItemVersionKey) as? String ?? "",
92+
)
93+
}
94+
}
95+
.sorted(using: KeyPathComparator(\.name, comparator: .localizedStandard)) // swiftformat:enable indent
96+
97+
if !["1", "true", "yes"].contains(ProcessInfo.processInfo.environment["MAS_NO_AUTO_INDEX"]?.lowercased()) {
98+
let installedAppPathSet = Set(installedApps.map(\.path))
99+
for installedAppURL in applicationsFolderURLs.flatMap(\.installedAppURLs)
100+
where !installedAppPathSet.contains(installedAppURL.filePath) { // swiftformat:disable:this indent
101+
MAS.printer.warning(
102+
"Found a likely App Store app that is not indexed in Spotlight in ",
103+
installedAppURL.filePath,
104+
"""
105+
106+
107+
Indexing now, which will not complete until sometime after mas exits
108+
109+
Disable auto-indexing via: export MAS_NO_AUTO_INDEX=1
110+
""",
111+
separator: "",
112+
)
113+
Task {
114+
do {
115+
_ = try await run(
116+
"/usr/bin/mdimport",
117+
installedAppURL.filePath,
118+
errorMessage: "Failed to index the Spotlight data for \(installedAppURL.filePath)",
119+
)
120+
} catch {
121+
MAS.printer.error(error: error)
122+
}
68123
}
69124
}
70-
.sorted(using: KeyPathComparator(\.name, comparator: .localizedStandard)), // swiftformat:enable indent
71-
)
125+
}
126+
127+
continuation.resume(returning: installedApps)
72128
}
73129

74130
query.start()

Sources/mas/Utilities/Sudo.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ func sudo(_ executableName: String, args: some Sequence<String>) throws {
1717
try sudo([executablePath] + args)
1818
}
1919

20-
private func sudo(_ args: some Sequence<String>) throws {
21-
let cArgs = unsafe (["sudo"] + args).map { unsafe strdup($0) } // swiftformat:disable:this spaceAroundParens
20+
private func sudo(_ args: some Sequence<String>) throws { // swiftformat:disable:next spaceAroundParens
21+
let cArgs = unsafe (["sudo", "MAS_NO_AUTO_INDEX=1"] + args).map { unsafe strdup($0) }
2222
defer {
2323
for unsafe cArg in unsafe cArgs {
2424
unsafe free(cArg)

0 commit comments

Comments
 (0)