Improve logging of failed commands

This commit is contained in:
Nindi Gill 2023-05-24 17:19:48 +10:00
parent 649ed12358
commit 02a74e59e3
No known key found for this signature in database
GPG key ID: FF9A7FD590D4F4B1
17 changed files with 44 additions and 36 deletions

View file

@ -19,10 +19,10 @@ struct Codesigner {
/// - Throws: A `MistError` if the command failed to execute.
static func sign(_ url: URL, identity: String) async throws {
let arguments: [String] = ["codesign", "--sign", identity, url.path]
let result: (terminationStatus: Int32, standardOutput: String?, standardError: String?) = try ShellExecutor.shared.execute(arguments)
let response: HelperToolCommandResponse = try ShellExecutor.shared.execute(arguments)
guard result.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: result.terminationStatus, string: result.standardError)
guard response.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: response.terminationStatus, output: response.standardOutput, error: response.standardError)
}
}
}

View file

@ -29,7 +29,7 @@ struct DirectoryRemover {
let response: HelperToolCommandResponse = try await client.sendMessage(request, to: XPCRoute.commandRoute)
guard response.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: response.terminationStatus, string: response.standardError)
throw MistError.invalidTerminationStatus(status: response.terminationStatus, output: response.standardOutput, error: response.standardError)
}
}
}

View file

@ -59,10 +59,10 @@ struct DiskImageCreator {
private static func create(_ url: URL, with arguments: [String]) async throws {
try await DirectoryRemover.remove(url)
let result: (terminationStatus: Int32, standardOutput: String?, standardError: String?) = try ShellExecutor.shared.execute(arguments)
let response: HelperToolCommandResponse = try ShellExecutor.shared.execute(arguments)
guard result.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: result.terminationStatus, string: result.standardError)
guard response.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: response.terminationStatus, output: response.standardOutput, error: response.standardError)
}
}
}

View file

@ -26,10 +26,10 @@ struct DiskImageMounter {
}
let arguments: [String] = ["hdiutil", "attach", url.path, "-noverify", "-nobrowse", "-mountpoint", mountPoint.path]
let result: (terminationStatus: Int32, standardOutput: String?, standardError: String?) = try ShellExecutor.shared.execute(arguments)
let response: HelperToolCommandResponse = try ShellExecutor.shared.execute(arguments)
guard result.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: result.terminationStatus, string: result.standardError)
guard response.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: response.terminationStatus, output: response.standardOutput, error: response.standardError)
}
}
}

View file

@ -18,10 +18,10 @@ struct DiskImageUnmounter {
/// - Throws: A `MistError` if the command failed to execute.
static func unmount(_ url: URL) async throws {
let arguments: [String] = ["hdiutil", "detach", url.path, "-force"]
let result: (terminationStatus: Int32, standardOutput: String?, standardError: String?) = try ShellExecutor.shared.execute(arguments)
let response: HelperToolCommandResponse = try ShellExecutor.shared.execute(arguments)
guard result.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: result.terminationStatus, string: result.standardError)
guard response.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: response.terminationStatus, output: response.standardOutput, error: response.standardError)
}
}
}

View file

@ -30,7 +30,7 @@ struct FileAttributesUpdater {
let response: HelperToolCommandResponse = try await client.sendMessage(request, to: XPCRoute.commandRoute)
guard response.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: response.terminationStatus, string: response.standardError)
throw MistError.invalidTerminationStatus(status: response.terminationStatus, output: response.standardOutput, error: response.standardError)
}
}
}

View file

@ -19,10 +19,10 @@ struct ISOConverter {
/// - Throws: An `Error` if the command failed to execute.
static func convert(_ source: URL, destination: URL) async throws {
let arguments: [String] = ["hdiutil", "convert", source.path, "-format", "UDTO", "-o", destination.path]
let result: (terminationStatus: Int32, standardOutput: String?, standardError: String?) = try ShellExecutor.shared.execute(arguments)
let response: HelperToolCommandResponse = try ShellExecutor.shared.execute(arguments)
guard result.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: result.terminationStatus, string: result.standardError)
guard response.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: response.terminationStatus, output: response.standardOutput, error: response.standardError)
}
}
}

View file

@ -25,7 +25,7 @@ struct InstallMediaCreator {
let response: HelperToolCommandResponse = try await client.sendMessage(request, to: XPCRoute.commandRoute)
guard response.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: response.terminationStatus, string: response.standardError)
throw MistError.invalidTerminationStatus(status: response.terminationStatus, output: response.standardOutput, error: response.standardError)
}
}
}

View file

@ -59,7 +59,7 @@ struct InstallerCreator {
let response: HelperToolCommandResponse = try await client.sendMessage(request, to: XPCRoute.commandRoute)
guard response.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: response.terminationStatus, string: response.standardError)
throw MistError.invalidTerminationStatus(status: response.terminationStatus, output: response.standardOutput, error: response.standardError)
}
}
}

View file

@ -47,10 +47,10 @@ struct PackageCreator {
private static func create(_ url: URL, with arguments: [String]) async throws {
try await DirectoryRemover.remove(url)
let result: (terminationStatus: Int32, standardOutput: String?, standardError: String?) = try ShellExecutor.shared.execute(arguments)
let response: HelperToolCommandResponse = try ShellExecutor.shared.execute(arguments)
guard result.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: result.terminationStatus, string: result.standardError)
guard response.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: response.terminationStatus, output: response.standardOutput, error: response.standardError)
}
}
}

View file

@ -23,9 +23,9 @@ struct PrivilegedHelperTool {
do {
// launchctl service is loaded
let arguments: [String] = ["launchctl", "print", "system/\(String.helperIdentifier)"]
let result: (terminationStatus: Int32, standardOutput: String?, standardError: String?) = try ShellExecutor().execute(arguments)
let response: HelperToolCommandResponse = try ShellExecutor().execute(arguments)
guard result.terminationStatus == 0 else {
guard response.terminationStatus == 0 else {
return false
}

View file

@ -19,7 +19,7 @@ struct ProcessKiller {
let response: HelperToolCommandResponse = try await client.sendMessage(request, to: XPCRoute.commandRoute)
guard response.terminationStatus == 0 else {
throw MistError.invalidTerminationStatus(status: response.terminationStatus, string: response.standardError)
throw MistError.invalidTerminationStatus(status: response.terminationStatus, output: response.standardOutput, error: response.standardError)
}
}
}

View file

@ -16,7 +16,7 @@ enum MistError: Error, Equatable {
case invalidDownloadResumeData
case invalidFileSize(invalid: UInt64, valid: UInt64)
case invalidShasum(invalid: String, valid: String)
case invalidTerminationStatus(status: Int32, string: String?)
case invalidTerminationStatus(status: Int32, output: String?, error: String?)
case invalidURL(_ url: String)
case maximumRetriesReached
case missingFileAttributes
@ -42,12 +42,20 @@ enum MistError: Error, Equatable {
return "Invalid File Size: '\(invalid)', should be: '\(valid)'"
case .invalidShasum(let invalid, let valid):
return "Invalid Shasum: '\(invalid)', should be: '\(valid)'"
case .invalidTerminationStatus(let status, let string):
if let string: String = string {
return "Invalid Termination Status '\(status)': \(string)"
} else {
return "Invalid Termination Status: \(status)"
case .invalidTerminationStatus(let status, let output, let error):
var string: String = "Invalid Termination Status: \(status)"
if let output: String = output,
!output.isEmpty {
string += "\n\n\(output)"
}
if let error: String = error,
!error.isEmpty {
string += "\n\n\(error)"
}
return string
case .invalidURL(let url):
return "Invalid URL: '\(url)'"
case .maximumRetriesReached:

View file

@ -166,7 +166,7 @@ struct DownloadView: View {
switch error {
case .userCancelled:
return true
case .invalidTerminationStatus(let status, _):
case .invalidTerminationStatus(let status, _, _):
// SIGTERM triggered via Privileged Helper Tool due to user cancellation
guard status == 15 else {

View file

@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>BuildHash</key>
<string>a9b37eeef3f02041cf0206471219c999c03928fa8d1f3c83475e74e8fec8e196</string>
<string>185811c82f555c98602ef205e6722bf512e5f4c4e882eb4c719aafc45d467f53</string>
<key>CFBundleIdentifier</key>
<string>com.ninxsoft.mist.helper</string>
<key>CFBundleInfoDictionaryVersion</key>

View file

@ -61,7 +61,7 @@ struct HelperToolCommandRunner {
ShellExecutor.shared.terminate()
return HelperToolCommandResponse(terminationStatus: 0, standardOutput: nil, standardError: nil)
default:
let response: (terminationStatus: Int32, standardOutput: String?, standardError: String?) = try ShellExecutor.shared.execute(request.arguments, environment: request.environment)
let response: HelperToolCommandResponse = try ShellExecutor.shared.execute(request.arguments, environment: request.environment)
return HelperToolCommandResponse(terminationStatus: response.terminationStatus, standardOutput: response.standardOutput, standardError: response.standardError)
}
}

View file

@ -27,7 +27,7 @@ class ShellExecutor: NSObject {
_ arguments: [String],
environment variables: [String: String] = [:],
currentDirectoryPath: String? = nil
) throws -> (terminationStatus: Int32, standardOutput: String?, standardError: String?) {
) throws -> HelperToolCommandResponse {
let outputPipe: Pipe = Pipe()
let errorPipe: Pipe = Pipe()
process = Process()
@ -56,7 +56,7 @@ class ShellExecutor: NSObject {
let errorData: Data = errorPipe.fileHandleForReading.readDataToEndOfFile()
let standardError: String? = String(data: errorData, encoding: .utf8)
let terminationStatus: Int32 = process.terminationStatus
return (terminationStatus: terminationStatus, standardOutput: standardOutput, standardError: (standardError ?? "").isEmpty ? nil : standardError)
return HelperToolCommandResponse(terminationStatus: terminationStatus, standardOutput: standardOutput, standardError: standardError)
}
func terminate() {