mirror of
https://github.com/mas-cli/mas
synced 2024-11-26 05:20:18 +00:00
♻️ Refactor AppLibrary to use TrashCommand
This commit is contained in:
parent
3630df5750
commit
ae8d8f5f46
3 changed files with 23 additions and 53 deletions
|
@ -13,8 +13,8 @@ public protocol ExternalCommand {
|
||||||
|
|
||||||
var process: Process { get }
|
var process: Process { get }
|
||||||
|
|
||||||
var stdout: String? { get }
|
var stdout: String { get }
|
||||||
var stderr: String? { get }
|
var stderr: String { get }
|
||||||
var stdoutPipe: Pipe { get }
|
var stdoutPipe: Pipe { get }
|
||||||
var stderrPipe: Pipe { get }
|
var stderrPipe: Pipe { get }
|
||||||
|
|
||||||
|
@ -23,19 +23,19 @@ public protocol ExternalCommand {
|
||||||
var failed: Bool { get }
|
var failed: Bool { get }
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
mutating func run() throws
|
func run() throws
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Common implementation
|
/// Common implementation
|
||||||
extension ExternalCommand {
|
extension ExternalCommand {
|
||||||
public var stdout: String? { get {
|
public var stdout: String { get {
|
||||||
let data = stdoutPipe.fileHandleForReading.readDataToEndOfFile()
|
let data = stdoutPipe.fileHandleForReading.readDataToEndOfFile()
|
||||||
return String(data: data, encoding: .utf8)
|
return String(data: data, encoding: .utf8) ?? ""
|
||||||
}}
|
}}
|
||||||
|
|
||||||
public var stderr: String? { get {
|
public var stderr: String { get {
|
||||||
let data = stderrPipe.fileHandleForReading.readDataToEndOfFile()
|
let data = stderrPipe.fileHandleForReading.readDataToEndOfFile()
|
||||||
return String(data: data, encoding: .utf8)
|
return String(data: data, encoding: .utf8) ?? ""
|
||||||
}}
|
}}
|
||||||
|
|
||||||
public var exitCode: Int? { get {
|
public var exitCode: Int? { get {
|
||||||
|
@ -51,7 +51,7 @@ extension ExternalCommand {
|
||||||
}}
|
}}
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
public mutating func run() throws {
|
public func run() throws {
|
||||||
process.standardOutput = stdoutPipe
|
process.standardOutput = stdoutPipe
|
||||||
process.standardError = stderrPipe
|
process.standardError = stderrPipe
|
||||||
process.arguments = arguments
|
process.arguments = arguments
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
// Copyright © 2019 mas-cli. All rights reserved.
|
// Copyright © 2019 mas-cli. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
/// CLI command
|
/// Wrapper for the external trash command. Relies on the "trash" command
|
||||||
|
/// from Homebrew. Trash requires el_capitan or higher for core bottles:
|
||||||
|
/// https://github.com/Homebrew/homebrew-core/blob/master/Formula/trash.rb
|
||||||
public struct TrashCommand: ExternalCommand {
|
public struct TrashCommand: ExternalCommand {
|
||||||
public var binaryPath: String
|
public var binaryPath: String
|
||||||
public var arguments: [String]
|
public var arguments: [String]
|
||||||
|
|
|
@ -22,8 +22,9 @@ public class MasAppLibrary: AppLibrary {
|
||||||
return products
|
return products
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private let trashCommand: ExternalCommand
|
private var trashCommand: ExternalCommand
|
||||||
|
|
||||||
|
/// Designated initializer
|
||||||
public init(trashCommand: ExternalCommand = TrashCommand()) {
|
public init(trashCommand: ExternalCommand = TrashCommand()) {
|
||||||
self.trashCommand = trashCommand
|
self.trashCommand = trashCommand
|
||||||
}
|
}
|
||||||
|
@ -41,50 +42,17 @@ public class MasAppLibrary: AppLibrary {
|
||||||
/// - Parameter app: App to be removed.
|
/// - Parameter app: App to be removed.
|
||||||
/// - Throws: Error if there is a problem.
|
/// - Throws: Error if there is a problem.
|
||||||
public func uninstallApp(app: SoftwareProduct) throws {
|
public func uninstallApp(app: SoftwareProduct) throws {
|
||||||
let status = trash(path: app.bundlePath)
|
trashCommand.arguments = [app.bundlePath]
|
||||||
if !status {
|
do {
|
||||||
|
try trashCommand.run()
|
||||||
|
} catch {
|
||||||
|
printError("Unable to launch trash command")
|
||||||
|
throw MASError.uninstallFailed
|
||||||
|
}
|
||||||
|
if trashCommand.failed {
|
||||||
|
let reason = trashCommand.process.terminationReason
|
||||||
|
printError("Uninstall failed: (\(reason)) \(trashCommand.stderr)")
|
||||||
throw MASError.uninstallFailed
|
throw MASError.uninstallFailed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs the trash command in another process. Relies on the "trash" command
|
|
||||||
/// from Homebrew. Trash requires el_capitan or higher for core bottles:
|
|
||||||
/// https://github.com/Homebrew/homebrew-core/blob/master/Formula/trash.rb
|
|
||||||
///
|
|
||||||
/// - Parameter path: Absolute path to the application bundle to uninstall.
|
|
||||||
/// - Returns: true on success; fail on error
|
|
||||||
func trash(path: String) -> Bool {
|
|
||||||
let binaryPath = "/usr/local/bin/trash"
|
|
||||||
let process = Process()
|
|
||||||
let stdout = Pipe()
|
|
||||||
let stderr = Pipe()
|
|
||||||
|
|
||||||
process.standardOutput = stdout
|
|
||||||
process.standardError = stderr
|
|
||||||
process.arguments = [path]
|
|
||||||
|
|
||||||
if #available(OSX 10.13, *) {
|
|
||||||
process.executableURL = URL(fileURLWithPath: binaryPath)
|
|
||||||
do {
|
|
||||||
try process.run()
|
|
||||||
} catch {
|
|
||||||
printError("Unable to launch trash command")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
process.launchPath = binaryPath
|
|
||||||
process.launch()
|
|
||||||
}
|
|
||||||
|
|
||||||
process.waitUntilExit()
|
|
||||||
|
|
||||||
if process.terminationStatus == 0 {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
let reason = process.terminationReason
|
|
||||||
let output = stderr.fileHandleForReading.readDataToEndOfFile()
|
|
||||||
printError("Uninstall failed: \(reason)\n\(String(data: output, encoding: .utf8)!)")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue