Skip to content

Commit

Permalink
Merge pull request #3 from bow-swift/environment
Browse files Browse the repository at this point in the history
Set environment in task executors
  • Loading branch information
truizlop authored Feb 6, 2020
2 parents 2b7e903 + f2afec1 commit f8920ed
Showing 1 changed file with 87 additions and 83 deletions.
170 changes: 87 additions & 83 deletions Source/Swiftline/CommandExecutor.swift
Original file line number Diff line number Diff line change
@@ -1,96 +1,100 @@
//
// CommandExecutor.swift
// CommandExecutor
//
// Created by Omar Abdelhafith on 05/11/2015.
// Copyright © 2015 Omar Abdelhafith. All rights reserved.
//

import Foundation


typealias ExecutorReturnValue = (status: Int, standardOutput: String, standardError: String)

class CommandExecutor {

static var currentTaskExecutor: TaskExecutor = ActualTaskExecutor()

class func execute(_ commandParts: [String]) -> ExecutorReturnValue {
return currentTaskExecutor.execute(commandParts)
}
static var currentTaskExecutor: TaskExecutor = ActualTaskExecutor()

class func execute(_ commandParts: [String]) -> ExecutorReturnValue {
return currentTaskExecutor.execute(commandParts)
}
}


protocol TaskExecutor {
func execute(_ commandParts: [String]) -> ExecutorReturnValue
func execute(_ commandParts: [String]) -> ExecutorReturnValue
}

extension TaskExecutor {
func readPipes(stdoutPipe: Pipe, stderrPipe: Pipe) -> (stdout: String, stderr: String) {
let stdout = readPipe(stdoutPipe).trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
let stderr = readPipe(stderrPipe).trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)

return (stdout, stderr)
}
}


class DryTaskExecutor: TaskExecutor {

func execute(_ commandParts: [String]) -> ExecutorReturnValue {
let command = commandParts.joined(separator: " ")
PromptSettings.print("Executed command '\(command)'")
return (0, "", "")
}
func execute(_ commandParts: [String]) -> ExecutorReturnValue {
let command = commandParts.joined(separator: " ")
PromptSettings.print("Executed command '\(command)'")
return (0, "", "")
}
}


class ActualTaskExecutor: TaskExecutor {

func execute(_ commandParts: [String]) -> ExecutorReturnValue {
let group = DispatchGroup()
group.enter()

let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = commandParts

let stdoutPipe = Pipe()
let stderrPipe = Pipe()

task.terminationHandler = { _ in group.leave() }
task.standardOutput = stdoutPipe
task.standardError = stderrPipe
task.launch()

group.wait()
func execute(_ commandParts: [String]) -> ExecutorReturnValue {
let group = DispatchGroup()
group.enter()

let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = commandParts

let stdoutPipe = Pipe()
let stderrPipe = Pipe()

task.standardOutput = stdoutPipe
task.standardError = stderrPipe
task.terminationHandler = { _ in group.leave() }
task.launch()


group.wait()
let (stdout, stderr) = readPipes(stdoutPipe: stdoutPipe, stderrPipe: stderrPipe)
return (Int(task.terminationStatus), stdout, stderr)
}

let (stdout, stderr) = readPipes(stdoutPipe: stdoutPipe, stderrPipe: stderrPipe)
return (Int(task.terminationStatus), stdout, stderr)
}
static var environment: [UnsafeMutablePointer<CChar>?] {
let env = ActualTaskExecutor().execute(["env"])
guard env.status == 0 else { return [nil] }

let environment = env.standardOutput
.components(separatedBy: "\n")
.map { path in path.trimmingCharacters(in: .whitespaces).trimmingCharacters(in: .newlines) }
.filter { path in !path.isEmpty }

return environment.map { $0.withCString(strdup) } + [nil]
}
}

class InteractiveTaskExecutor: TaskExecutor {

func execute(_ commandParts: [String]) -> ExecutorReturnValue {

let argv: [UnsafeMutablePointer<CChar>?] = commandParts.map{ $0.withCString(strdup) }
defer { for case let arg? in argv { free(arg) } }

var childFDActions: posix_spawn_file_actions_t? = nil
let outputPipe: [Int32] = [-1, -1]

posix_spawn_file_actions_init(&childFDActions)
posix_spawn_file_actions_adddup2(&childFDActions, outputPipe[1], 1)
posix_spawn_file_actions_adddup2(&childFDActions, outputPipe[1], 2)
posix_spawn_file_actions_addclose(&childFDActions, outputPipe[0])
posix_spawn_file_actions_addclose(&childFDActions, outputPipe[1])

var pid: pid_t = 0
let result = posix_spawn(&pid, argv[0], &childFDActions, nil, argv + [nil], nil)
class InteractiveTaskExecutor: TaskExecutor {

return (Int(result), "", "")
}
func execute(_ commandParts: [String]) -> ExecutorReturnValue {
let argv: [UnsafeMutablePointer<CChar>?] = commandParts.map { $0.withCString(strdup) }
defer { for case let arg? in argv { free(arg) } }

var childFDActions: posix_spawn_file_actions_t? = nil
let outputPipe: [Int32] = [-1, -1]

posix_spawn_file_actions_init(&childFDActions)
posix_spawn_file_actions_adddup2(&childFDActions, outputPipe[1], 1)
posix_spawn_file_actions_adddup2(&childFDActions, outputPipe[1], 2)
posix_spawn_file_actions_addclose(&childFDActions, outputPipe[0])
posix_spawn_file_actions_addclose(&childFDActions, outputPipe[1])

var pid: pid_t = 0
let result = posix_spawn(&pid, argv[0], &childFDActions, nil, argv + [nil], ActualTaskExecutor.environment)

return (Int(result), "", "")
}
}


class LogTaskExecutor: TaskExecutor {
let logPath: String

Expand All @@ -99,7 +103,7 @@ class LogTaskExecutor: TaskExecutor {
}

func execute(_ commandParts: [String]) -> ExecutorReturnValue {
let argv: [UnsafeMutablePointer<CChar>?] = commandParts.map{ $0.withCString(strdup) }
let argv: [UnsafeMutablePointer<CChar>?] = commandParts.map { $0.withCString(strdup) }
var pid: pid_t = 0
var childFDActions: posix_spawn_file_actions_t? = nil
let outputPipe: Int32 = 69
Expand All @@ -117,8 +121,8 @@ class LogTaskExecutor: TaskExecutor {
posix_spawn_file_actions_addopen(&childFDActions, outerrPipe, stderrLogPath, O_CREAT | O_TRUNC | O_WRONLY, ~0)
posix_spawn_file_actions_adddup2(&childFDActions, outputPipe, 1)
posix_spawn_file_actions_adddup2(&childFDActions, outerrPipe, 2)
var result = posix_spawn(&pid, argv[0], &childFDActions, nil, argv + [nil], nil)

var result = posix_spawn(&pid, argv[0], &childFDActions, nil, argv + [nil], ActualTaskExecutor.environment)
guard result == 0 else { return (Int(result), "", "") }
waitpid(pid, &result, 0)

Expand Down Expand Up @@ -150,24 +154,24 @@ class LogTaskExecutor: TaskExecutor {
}
}


class DummyTaskExecutor: TaskExecutor {

var commandsExecuted: [String] = []
let statusCodeToReturn: Int

let errorToReturn: String
let outputToReturn: String

init(status: Int, output: String, error: String) {
statusCodeToReturn = status
outputToReturn = output
errorToReturn = error
}

func execute(_ commandParts: [String]) -> ExecutorReturnValue {
let command = commandParts.joined(separator: " ")
commandsExecuted.append(command)
var commandsExecuted: [String] = []
let statusCodeToReturn: Int

return (statusCodeToReturn, outputToReturn, errorToReturn)
}
let errorToReturn: String
let outputToReturn: String

init(status: Int, output: String, error: String) {
statusCodeToReturn = status
outputToReturn = output
errorToReturn = error
}

func execute(_ commandParts: [String]) -> ExecutorReturnValue {
let command = commandParts.joined(separator: " ")
commandsExecuted.append(command)

return (statusCodeToReturn, outputToReturn, errorToReturn)
}
}

0 comments on commit f8920ed

Please sign in to comment.