1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-08-07 03:50:08 +02:00

🏗 WIP: Shell rework

This commit is contained in:
2022-09-27 22:27:33 +02:00
parent 3483569410
commit a59efb7fce
4 changed files with 88 additions and 24 deletions

View File

@ -12,8 +12,7 @@ class ShellTest: XCTestCase {
func test_default_shell_is_system_shell() {
XCTAssertTrue(Shell is SystemShell)
XCTAssertTrue(Shell.syncPipe("php -v")
.contains("Copyright (c) The PHP Group"))
XCTAssertTrue(Shell.sync("php -v").output.contains("Copyright (c) The PHP Group"))
}
func test_system_shell_has_path() {
@ -45,8 +44,14 @@ class ShellTest: XCTestCase {
XCTAssertTrue(Shell is TestableShell)
XCTAssertEqual(expectedPhpOutput, Shell.syncPipe("php -v"))
XCTAssertEqual(expectedPhpOutput, Shell.sync("php -v").output)
XCTAssertEqual(expectedPhpOutput, Shell.syncPipe("php --version"))
XCTAssertEqual(expectedPhpOutput, Shell.sync("php --version").output)
}
func test_unrecognized_commands_output_stderr() {
ActiveShell.useTestable([:])
XCTAssertEqual("Unexpected Command", Shell.sync("unrecognized command").output)
}
}

View File

@ -8,10 +8,37 @@
import Foundation
protocol Shellable {
typealias Output = String
struct ShellOutput: CustomStringConvertible {
var output: String
var isError: Bool
func syncPipe(_ command: String) -> Output
func pipe(_ command: String) async -> Output
var description: String {
return output
}
}
protocol Shellable {
/**
Run a command synchronously. Waits until the command is done.
*/
func sync(_ command: String) -> ShellOutput
/**
Run a command asynchronously.
*/
func pipe(_ command: String) async -> ShellOutput
/**
Run a command asynchronously, without returning the output of the command.
*/
func quiet(_ command: String) async
/**
Attach to a given command and listen for progress updates.
Any data that ends up in standard out or standard error becomes available.
*/
func attach(
_ command: String,
didReceiveOutput: @escaping (ShellOutput) -> Void
) async -> ShellOutput
}

View File

@ -82,21 +82,43 @@ class SystemShell: Shellable {
// MARK: - Shellable Protocol
func syncPipe(_ command: String) -> String {
func sync(_ command: String) -> ShellOutput {
let task = getShellProcess(for: command)
let pipe = Pipe()
task.standardOutput = pipe
let outputPipe = Pipe()
let errorPipe = Pipe()
task.standardOutput = outputPipe
task.standardError = errorPipe
task.waitUntilExit()
task.launch()
return String(
data: pipe.fileHandleForReading.readDataToEndOfFile(),
let stdOut = String(
data: outputPipe.fileHandleForReading.readDataToEndOfFile(),
encoding: .utf8
) ?? ""
)!
let stdErr = String(
data: errorPipe.fileHandleForReading.readDataToEndOfFile(),
encoding: .utf8
)!
if stdErr.lengthOfBytes(using: .utf8) > 0 {
return ShellOutput(output: stdErr, isError: true)
}
return ShellOutput(output: stdOut, isError: false)
}
func pipe(_ command: String) async -> String {
// TODO
return ""
func pipe(_ command: String) async -> ShellOutput {
return sync(command)
}
func quiet(_ command: String) async {
_ = await self.pipe(command)
}
func attach(_ command: String, didReceiveOutput: @escaping (ShellOutput) -> Void) async -> ShellOutput {
return sync(command)
}
}

View File

@ -18,14 +18,24 @@ public class TestableShell: Shellable {
var expectations: [Input: OutputsToShell] = [:]
func pipe(_ command: String) async -> String {
// TODO: Deal with the duration and output to error
return expectations[command]?.getOutputAsString() ?? ""
func quiet(_ command: String) async {
return
}
func syncPipe(_ command: String) -> String {
// TODO: Deal with the duration and output to error
return expectations[command]?.getOutputAsString() ?? ""
func pipe(_ command: String) async -> ShellOutput {
self.sync(command)
}
func attach(_ command: String, didReceiveOutput: @escaping (ShellOutput) -> Void) async -> ShellOutput {
self.sync(command)
}
func sync(_ command: String) -> ShellOutput {
guard let expectation = expectations[command] else {
return ShellOutput(output: "Unexpected Command", isError: true)
}
return ShellOutput(output: expectation.getOutputAsString(), isError: expectation.outputsToError())
}
}