Skip to content

Commit

Permalink
Support shelling out to a series of commands, optionally at a given path
Browse files Browse the repository at this point in the history
This addition to ShellOut makes it easier to run a series of commands, without
having to manually string them together using ‘&&’. It also enables you to
easily run a shell command at a given path, without having to ‘cd’ to it first.
  • Loading branch information
JohnSundell committed Apr 11, 2017
1 parent 07f32cd commit 8675701
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 3 deletions.
26 changes: 23 additions & 3 deletions Sources/ShellOut.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,39 @@ import Foundation
*
* - parameter command: The command to run
* - parameter arguments: The arguments to pass to the command
* - parameter path: The path to execute the commands at (defaults to current folder)
*
* - returns: The output of running the command
* - throws: `ShellOutError` in case the command couldn't be performed, or it returned an error
*
* Use this function to "shell out" in a Swift script or command line tool
* For example: `shellOut(to: "mkdir", arguments: ["NewFolder"])`
* For example: `shellOut(to: "mkdir", arguments: ["NewFolder"], at: "~/CurrentFolder")`
*/
@discardableResult public func shellOut(to command: String, arguments: [String] = []) throws -> String {
@discardableResult public func shellOut(to command: String,
arguments: [String] = [],
at path: String = ".") throws -> String {
let process = Process()
let command = "\(command) \(arguments.joined(separator: " "))"
let command = "cd \"\(path)\" && \(command) \(arguments.joined(separator: " "))"
return try process.launchBash(with: command)
}

/**
* Run a series of shell commands using Bash
*
* - parameter commands: The commands to run
* - parameter path: The path to execute the commands at (defaults to current folder)
*
* - returns: The output of running the command
* - throws: `ShellOutError` in case the command couldn't be performed, or it returned an error
*
* Use this function to "shell out" in a Swift script or command line tool
* For example: `shellOut(to: ["mkdir NewFolder", "cd NewFolder"], at: "~/CurrentFolder")`
*/
@discardableResult public func shellOut(to commands: [String], at path: String = ".") throws -> String {
let command = commands.joined(separator: " && ")
return try shellOut(to: command, at: path)
}

// Error type thrown by the `shellOut()` function, in case the given command failed
public struct ShellOutError: Swift.Error {
/// The error message that was returned through `STDERR`
Expand Down
29 changes: 29 additions & 0 deletions Tests/ShellOutTests/ShellOutTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,35 @@ class ShellOutTests: XCTestCase {
XCTAssertEqual(echo, "Hello world")
}

func testSingleCommandAtPath() throws {
try shellOut(to: "echo \"Hello\" > \(NSTemporaryDirectory())ShellOutTests-SingleCommand.txt")

let textFileContent = try shellOut(to: "cat ShellOutTests-SingleCommand.txt",
at: NSTemporaryDirectory())

XCTAssertEqual(textFileContent, "Hello")
}

func testSeriesOfCommands() throws {
let echo = try shellOut(to: ["echo \"Hello\"", "echo \"world\""])
XCTAssertEqual(echo, "Hello\nworld")
}

func testSeriesOfCommandsAtPath() throws {
try shellOut(to: [
"cd \(NSTemporaryDirectory())",
"mkdir -p ShellOutTests",
"echo \"Hello again\" > ShellOutTests/MultipleCommands.txt"
])

let textFileContent = try shellOut(to: [
"cd ShellOutTests",
"cat MultipleCommands.txt"
], at: NSTemporaryDirectory())

XCTAssertEqual(textFileContent, "Hello again")
}

func testThrowingError() {
do {
try shellOut(to: "cd", arguments: ["notADirectory"])
Expand Down

0 comments on commit 8675701

Please sign in to comment.