rwbutler/IPAUploader

View on GitHub
Services/Task/Implementation/DefaultTaskService.swift

Summary

Maintainability
A
0 mins
Test Coverage
//
//  DefaultTaskService.swift
//  ipa-uploader
//
//  Created by Ross Butler on 11/19/18.
//

import Foundation

struct DefaultTaskService: TaskService {
    private let queue = DispatchQueue(label: "timeout", qos: .background)
    
    /// Returns a Process configured using settings from the Task model object.
    private func process(from task: Task) -> Process {
        let process = Process()
        if let arguments = task.arguments {
            process.arguments = arguments
        }
        if let workingDirectoryURL = task.workingDirectoryURL {
            process.currentDirectoryURL = workingDirectoryURL
        }
        process.executableURL = task.processURL
        return process
    }
    
    /// Executes the specified task and return the output, if any
    func run(task: Task) throws -> String {
        let dispatchGroup = DispatchGroup()
        let pipe = Pipe()
        let pipeReader = pipe.fileHandleForReading
        let process = self.process(from: task)
        process.standardOutput = pipe
        process.standardError = pipe
        process.terminationHandler = { (process) in
            dispatchGroup.leave()
        }
        dispatchGroup.enter()
        if let timeout = task.timeoutInSeconds {
            startTimeoutTimer(timeoutInSeconds: timeout, process: process)
        }
        try process.run()
        dispatchGroup.wait()
        let processData = pipeReader.readDataToEndOfFile()
        let processOutput = String(data: processData, encoding: .utf8) ?? ""
        pipeReader.closeFile()
        return processOutput
    }
    
    private func startTimeoutTimer(timeoutInSeconds: Double, process: Process) {
        let deadline = DispatchTime.now() + timeoutInSeconds
        queue.asyncAfter(deadline: deadline, execute: {
            process.terminate()
        })
    }
    
}