@@ -101,6 +101,9 @@ enum DiagnosticsStore {
101101 let bundle = Bundle . main
102102 let shortVersion = bundle. object ( forInfoDictionaryKey: " CFBundleShortVersionString " ) as? String ?? " unknown "
103103 let buildVersion = bundle. object ( forInfoDictionaryKey: " CFBundleVersion " ) as? String ?? " unknown "
104+ let bundleIdentifier = bundle. bundleIdentifier ?? " unknown "
105+ let bundlePath = bundle. bundleURL. path
106+ let codeSignature = currentCodeSignatureSummary ( )
104107
105108 let deviceLines = snapshot. devices. map { device in
106109 let mode = device. remapMode ?? " none "
@@ -111,6 +114,9 @@ enum DiagnosticsStore {
111114 " MacKeyMap Diagnostics " ,
112115 " Generated: \( iso8601Timestamp ( ) ) " ,
113116 " Version: \( shortVersion) ( \( buildVersion) ) " ,
117+ " Bundle identifier: \( bundleIdentifier) " ,
118+ " Bundle path: \( bundlePath) " ,
119+ " Code signature: \( codeSignature) " ,
114120 " Engine status: \( snapshot. engineStatus) " ,
115121 " Remapping enabled: \( config. enabled) " ,
116122 " Launch at login: \( config. launchAtLogin) " ,
@@ -166,4 +172,53 @@ enum DiagnosticsStore {
166172 formatter. dateFormat = " yyyyMMdd-HHmmss "
167173 return formatter. string ( from: Date ( ) )
168174 }
175+
176+ private static func currentCodeSignatureSummary( ) -> String {
177+ let process = Process ( )
178+ let outputPipe = Pipe ( )
179+ process. executableURL = URL ( fileURLWithPath: " /usr/bin/codesign " )
180+ process. arguments = [ " -dv " , " --verbose=4 " , Bundle . main. bundleURL. path]
181+ process. standardError = outputPipe
182+ process. standardOutput = Pipe ( )
183+
184+ do {
185+ try process. run ( )
186+ process. waitUntilExit ( )
187+ } catch {
188+ return " unavailable ( \( error. localizedDescription) ) "
189+ }
190+
191+ guard process. terminationStatus == 0 else {
192+ return " codesign exited with status \( process. terminationStatus) "
193+ }
194+
195+ let data = outputPipe. fileHandleForReading. readDataToEndOfFile ( )
196+ guard let output = String ( data: data, encoding: . utf8) else {
197+ return " unavailable "
198+ }
199+
200+ let authority = output
201+ . components ( separatedBy: . newlines)
202+ . first ( where: { $0. hasPrefix ( " Authority= " ) } )
203+ . map { String ( $0. dropFirst ( " Authority= " . count) ) }
204+ let teamIdentifier = output
205+ . components ( separatedBy: . newlines)
206+ . first ( where: { $0. hasPrefix ( " TeamIdentifier= " ) } )
207+ . map { String ( $0. dropFirst ( " TeamIdentifier= " . count) ) }
208+ let signature = output
209+ . components ( separatedBy: . newlines)
210+ . first ( where: { $0. hasPrefix ( " Signature= " ) } )
211+ . map { String ( $0. dropFirst ( " Signature= " . count) ) }
212+
213+ return [ signature, authority, teamIdentifier]
214+ . compactMap { $0 }
215+ . joined ( separator: " | " )
216+ . ifEmpty ( " unavailable " )
217+ }
218+ }
219+
220+ private extension String {
221+ func ifEmpty( _ fallback: String ) -> String {
222+ isEmpty ? fallback : self
223+ }
169224}
0 commit comments