Files
i2p.i2p/launchers/macosx/I2PLauncher/subprocesses/Subprocess+CompactAPI.swift
meeh 7615b9236b Adding all new code, removed a lot obsolete code and fixed import paths etc.
Mac OS X launcher:
* UI built on Swift
  * Why?
    * Apple seems to on purpose make it harder to get into Objective-C these days
    * Swift is compiled to native code, but has easiness of Javascript in programming
    * Perfect for the OS X UI, many guides & tutorials as well
* "Backend" in Objective-C++ / C++14
  * Why?
    * Originally written in Objective-C / C++14 with C++17 backports
    * Only for backend because of the time the development takes
    *

Short summary of features:

* Java
  * It can detect java from:
    * JAVA_HOME environment variable
    * "Internet Plug-Ins" Apple stuff
    * By the /usr/libexec/java_home binary helper
  * It can unpack a new version of I2P
    * Unpacks to ~/Library/I2P
    * Can check currently unpacked version in ~/Library/I2P via i2p.jar's "net.i2p.CoreVersion"

  * User Interface (a popover, see https://youtu.be/k8L3lQ5rUq0 for example of this concept)
    * Router control tab view
      * It can start the router
      * It can stop the router
      * It can detect already running router, then avoid fireing up one
      * It can show basic information about the router state & version
    * Log view tab (not yet done)
  * While left-click triggers popover, right-click draws a minimal context menu
2018-09-18 15:36:38 +00:00

119 lines
4.8 KiB
Swift

//
// Subprocess+CompactAPI.swift
// I2PLauncher
//
// Created by Mikal Villa on 17/09/2018.
// Copyright © 2018 The I2P Project. All rights reserved.
//
import Foundation
// MARK: - Compact API
extension Subprocess {
/**
Executes a subprocess and wait for completion, returning the output. If there is an error in creating the task,
it immediately exits the process with status 1
- returns: the output as a String
- note: in case there is any error in executing the process or creating the task, it will halt execution. Use
the constructor and `output` instance method for a more graceful error handling
*/
public static func output(
executablePath: String,
_ arguments: String...,
workingDirectory: String = ".") -> String {
let process = Subprocess.init(executablePath: executablePath, arguments: arguments, workingDirectory: workingDirectory)
guard let result = process.execute(captureOutput: true) else {
Error.die(arguments: "Can't execute \"\(process)\"")
}
if result.status != 0 {
let errorLines = result.errors == "" ? "" : "\n" + result.errors
Error.die(arguments: "Process \"\(process)\" returned status \(result.status)", errorLines)
}
return result.output
}
/**
Executes a subprocess and wait for completion, returning the execution result. If there is an error in creating the task,
it immediately exits the process with status 1
- returns: the execution result
- note: in case there is any error in executing the process or creating the task, it will halt execution. Use
the constructor and `execute` instance method for a more graceful error handling
*/
public static func execute(
executablePath: String,
_ arguments: String...,
workingDirectory: String = ".") -> ExecutionResult {
let process = Subprocess.init(executablePath: executablePath, arguments: arguments, workingDirectory: workingDirectory)
guard let result = process.execute(captureOutput: true) else {
Error.die(arguments: "Can't execute \"\(process)\"")
}
return result
}
/**
Executes a subprocess and wait for completion, returning the output as an array of lines. If there is an error
in creating or executing the task, it immediately exits the process with status 1
- returns: the output as a String
- note: in case there is any error in executing the process or creating the task, it will halt execution. Use
the constructor and `output` instance method for a more graceful error handling
*/
public static func outputLines(
executablePath: String,
_ arguments: String...,
workingDirectory: String = ".") -> [String] {
let process = Subprocess.init(executablePath: executablePath, arguments: arguments, workingDirectory: workingDirectory)
guard let result = process.execute(captureOutput: true) else {
Error.die(arguments: "Can't execute \"\(process)\"")
}
if result.status != 0 {
let errorLines = result.errors == "" ? "" : "\n" + result.errors
Error.die(arguments: "Process \"\(process)\" returned status \(result.status)", errorLines)
}
return result.outputLines
}
/**
Executes a subprocess and wait for completion, returning the exit status. If there is an error in creating the task,
it immediately exits the process with status 1
- returns: the output as a String
- note: in case there is any error in launching the process or creating the task, it will halt execution. Use
the constructor and the `run` instance method for a more graceful error handling
*/
public static func run(
executablePath: String,
_ arguments: String...,
workingDirectory: String = ".") -> Int32 {
let process = Subprocess.init(executablePath: executablePath, arguments: arguments, workingDirectory: workingDirectory)
guard let result = process.run() else {
Error.die(arguments: "Can't execute \"\(process)\"")
}
return result
}
/**
Executes a subprocess and wait for completion. If there is an error in creating the task, or if the tasks
returns an exit status other than 0, it immediately exits the process with status 1
- note: in case there is any error in launching the process or creating the task, or if the task exists with a exit status other than 0, it will halt execution. Use
the constructor and `run` instance method for a more graceful error handling
*/
public static func runOrDie(
executablePath: String,
_ arguments: String...,
workingDirectory: String = ".") {
let process = Subprocess.init(executablePath: executablePath, arguments: arguments, workingDirectory: workingDirectory)
guard let result = process.run() else {
Error.die(arguments: "Can't execute \"\(process)\"")
}
if result != 0 {
Error.die(arguments: "Process \"\(process)\" returned status \(result)")
}
}
}