Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
242 additions
and
203 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,143 +1,22 @@ | ||
import Foundation | ||
import MintKit | ||
import Rainbow | ||
import Foundation | ||
import SwiftShell | ||
import Guaka | ||
|
||
let mint = Mint(path: "/usr/local/lib/mint") | ||
|
||
func catchError(closure: () throws -> Void) { | ||
do { | ||
try closure() | ||
} catch { | ||
if let error = error as? CommandError { | ||
print("🌱 \(error.description)".red) | ||
} else if let error = error as? SwiftShell.CommandError { | ||
switch error { | ||
case .inAccessibleExecutable(let path): main.stderror.print("Couldn't run command \(path)") | ||
case .returnedErrorCode(let command, _): main.stderror.print("\(command.quoted) failed") | ||
} | ||
} else if let error = error as? MintError { | ||
print("🌱 \(error.description)".red) | ||
} else { | ||
print("🌱 \(error.localizedDescription)".red) | ||
} | ||
exit(1) | ||
} | ||
} | ||
|
||
enum CommandError: Error, CustomStringConvertible { | ||
case repoRequired | ||
case invalidRepo(String) | ||
case tooManyArguments | ||
|
||
var description: String { | ||
switch self { | ||
case .repoRequired: | ||
return "Repo required" | ||
case let .invalidRepo(repo): | ||
return "The repo was invalid: \(repo)" | ||
case .tooManyArguments: | ||
return "Too many arguments. Make sure command is surrounded in quotes" | ||
do { | ||
let mint = Mint(path: "/usr/local/lib/mint") | ||
let mintInterface = MintInterace(mint: mint) | ||
try mintInterface.execute(arguments: Array(ProcessInfo.processInfo.arguments.dropFirst())) | ||
} catch { | ||
if let error = error as? SwiftShell.CommandError { | ||
switch error { | ||
case let .inAccessibleExecutable(path): main.stderror.print("Couldn't run command \(path)") | ||
case let .returnedErrorCode(command, _): main.stderror.print("\(command.quoted) failed") | ||
} | ||
} else if error._domain == NSCocoaErrorDomain { | ||
print("🌱 \(error.localizedDescription)".red) | ||
} else { | ||
print("🌱 \(error)".red) | ||
} | ||
exit(1) | ||
} | ||
|
||
func getOptions(flags: Flags, args: [String]) throws -> (repo: String, version: String, command: String, verbose: Bool, global: Bool) { | ||
guard let repoVersion = args.first else { throw CommandError.repoRequired } | ||
let version: String | ||
let command: String | ||
let repoVersionParts = repoVersion.components(separatedBy: "@") | ||
let repo: String | ||
|
||
switch repoVersionParts.count { | ||
case 2: | ||
repo = repoVersionParts[0] | ||
version = repoVersionParts[1] | ||
case 1: | ||
repo = repoVersion | ||
version = "" | ||
default: | ||
throw CommandError.invalidRepo(repoVersion) | ||
} | ||
|
||
switch args.count { | ||
case 2: | ||
command = args[1] | ||
case 1: | ||
command = repo.components(separatedBy: "/").last!.components(separatedBy: ".").first! | ||
default: | ||
throw CommandError.tooManyArguments | ||
} | ||
return (repo: repo, | ||
version: version, | ||
command: command, | ||
verbose: flags.getBool(name: "verbose") ?? false, | ||
global: flags.getBool(name: "global") ?? false) | ||
} | ||
|
||
let versionFlag = Flag(longName: "version", value: false, description: "Prints the version") | ||
let verboseFlag = Flag(longName: "verbose", value: false, description: "Show installation output") | ||
let globalFlag = Flag(longName: "global", value: false, description: "Install executable globally so it's accessible without \"mint run\". This will overwrite any other globally installed versions. An extra $PATH entry will also be added") | ||
|
||
let command = Command(usage: "mint", flags: [versionFlag]) | ||
command.run = { flags, _ in | ||
if let hasVersion = flags.getBool(name: "version"), hasVersion { | ||
print(Mint.version) | ||
return | ||
} | ||
print(command.helpMessage) | ||
} | ||
|
||
let commandHelp = """ | ||
This command takes allows you to specify a repo, a version and an executable command to run. | ||
- Repo is either in shorthand for a github repo \"githubName/repo\", or a fully qualified .git path. | ||
- An optional version can be specified by appending @version to the repo, otherwise the newest tag or master will be used. | ||
- The second argument qualifies the command name, otherwise this will be assumed to the be the end of the repo name. | ||
""" | ||
|
||
let runCommand = Command(usage: "run package(@version) (command)", shortMessage: "Run a package", longMessage: "This will run a package. If it isn't installed if will do so first.\n\(commandHelp) The command can include any arguments and flags but the whole command must then be surrounded in quotes.", flags: [verboseFlag], example: "mint run realm/SwiftLint@0.22.0") { flags, args in | ||
catchError { | ||
let options = try getOptions(flags: flags, args: args) | ||
try mint.run(repo: options.repo, version: options.version, command: options.command, verbose: options.verbose) | ||
} | ||
} | ||
|
||
let installCommand = Command(usage: "install package(@version) (command)", shortMessage: "Install a package", longMessage: "This will install a package. If it's already installed no action will be taken.\n\(commandHelp)", flags: [verboseFlag, globalFlag], example: "mint install realm/SwiftLint@0.22.0") { flags, args in | ||
catchError { | ||
let options = try getOptions(flags: flags, args: args) | ||
try mint.install(repo: options.repo, version: options.version, command: options.command, force: false, verbose: options.verbose, global: options.global) | ||
} | ||
} | ||
|
||
let updateCommand = Command(usage: "update package(@version) (command)", shortMessage: "Update a package", longMessage: "This will update a package even if it's already installed.\n\(commandHelp)", flags: [verboseFlag, globalFlag], example: "mint install realm/SwiftLint@0.22.0") { flags, args in | ||
catchError { | ||
let options = try getOptions(flags: flags, args: args) | ||
try mint.install(repo: options.repo, version: options.version, command: options.command, force: true, verbose: options.verbose, global: options.global) | ||
} | ||
} | ||
|
||
let uninstallCommand = Command(usage: "uninstall (package)", shortMessage: "Uninstall a package", longMessage: "This will uninstall a package by name. See all installed packages with \"mint list\")", example: "mint uninstall SwiftLint") { flags, args in | ||
catchError { | ||
let options = try getOptions(flags: flags, args: args) | ||
try mint.uninstall(name: options.repo) | ||
} | ||
} | ||
|
||
let listCommand = Command(usage: "list", shortMessage: "List packages", longMessage: "This lists all the currently installed packages", example: "mint list") { _, _ in | ||
catchError { | ||
try mint.listPackages() | ||
} | ||
} | ||
|
||
let bootstrapCommand = Command(usage: "bootstrap") { _, _ in | ||
} | ||
|
||
command.add(subCommand: runCommand) | ||
command.add(subCommand: installCommand) | ||
command.add(subCommand: updateCommand) | ||
command.add(subCommand: uninstallCommand) | ||
command.add(subCommand: listCommand) | ||
|
||
command.execute() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import Foundation | ||
import Utility | ||
|
||
class InstallCommand: _InstallCommand { | ||
|
||
init(mint: Mint, parser: ArgumentParser) { | ||
super.init(mint: mint, parser: parser, name: "install", description: "Installs a package. If the version is already installed no action will be taken") | ||
} | ||
|
||
override func execute(parsedArguments: ArgumentParser.Result, repo: String, version: String, verbose: Bool, executable: String?, global: Bool) throws { | ||
try mint.install(repo: repo, version: version, command: executable, force: false, verbose: verbose, global: global) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import Foundation | ||
import Utility | ||
|
||
class ListCommand: MintCommand { | ||
|
||
init(mint: Mint, parser: ArgumentParser) { | ||
super.init(mint: mint, parser: parser, name: "list", description: "Lists all the currently installed packages") | ||
} | ||
|
||
override func execute(parsedArguments: ArgumentParser.Result) throws { | ||
try mint.listPackages() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import Foundation | ||
import Utility | ||
|
||
class MintCommand { | ||
|
||
let mint: Mint | ||
let subparser: ArgumentParser | ||
|
||
init(mint: Mint, parser: ArgumentParser, name: String, description: String) { | ||
self.mint = mint | ||
subparser = parser.add(subparser: name, overview: description) | ||
} | ||
|
||
func execute(parsedArguments: ArgumentParser.Result) throws { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import Basic | ||
import Foundation | ||
import Utility | ||
|
||
public class MintInterace { | ||
|
||
let mint: Mint | ||
|
||
public init(mint: Mint) { | ||
self.mint = mint | ||
} | ||
|
||
public func execute(arguments: [String]) throws { | ||
let parser = ArgumentParser(commandName: "mint", usage: "mint [subcommand]", overview: "run and install Swift PM executables") | ||
let versionArgument = parser.add(option: "--version", shortName: "-v", kind: Bool.self, usage: "Prints the current version of Mint") | ||
|
||
let commands: [String: MintCommand] = [ | ||
"run": RunCommand(mint: mint, parser: parser), | ||
"install": InstallCommand(mint: mint, parser: parser), | ||
"update": UpdateCommand(mint: mint, parser: parser), | ||
"uninstall": UninstallCommand(mint: mint, parser: parser), | ||
"list": ListCommand(mint: mint, parser: parser), | ||
] | ||
|
||
let parsedArguments = try parser.parse(arguments) | ||
|
||
if let printVersion = parsedArguments.get(versionArgument), printVersion == true { | ||
print(Mint.version) | ||
return | ||
} | ||
|
||
if let subParser = parsedArguments.subparser(parser), | ||
let command = commands[subParser] { | ||
try command.execute(parsedArguments: parsedArguments) | ||
} else { | ||
parser.printUsage(on: stdoutStream) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import Foundation | ||
import Utility | ||
|
||
class PackageCommand: MintCommand { | ||
|
||
var verboseArgument: OptionArgument<Bool>! | ||
var packageArgument: PositionalArgument<String>! | ||
|
||
override init(mint: Mint, parser: ArgumentParser, name: String, description: String) { | ||
super.init(mint: mint, parser: parser, name: name, description: description) | ||
|
||
let packageHelp = """ | ||
The identifier for the Swift Package to use. It can be a shorthand for a github repo \"githubName/repo\", or a fully qualified .git path. | ||
An optional version can be specified by appending @version to the repo, otherwise the newest tag will be used (or master if no tags are found) | ||
""" | ||
packageArgument = subparser.add(positional: "package", kind: String.self, optional: false, usage: packageHelp) | ||
verboseArgument = subparser.add(option: "--verbose", kind: Bool.self, usage: "Show installation output") | ||
} | ||
|
||
override func execute(parsedArguments: ArgumentParser.Result) throws { | ||
let verbose = parsedArguments.get(verboseArgument) ?? false | ||
let package = parsedArguments.get(packageArgument)! | ||
|
||
let version: String | ||
let packageParts = package.components(separatedBy: "@") | ||
let repo: String | ||
|
||
if packageParts.count > 1 { | ||
repo = packageParts[0] | ||
version = packageParts[1] | ||
} else { | ||
repo = package | ||
version = "" | ||
} | ||
|
||
try execute(parsedArguments: parsedArguments, repo: repo, version: version, verbose: verbose) | ||
} | ||
|
||
func execute(parsedArguments: ArgumentParser.Result, repo: String, version: String, verbose: Bool) throws { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import Foundation | ||
import Utility | ||
|
||
class RunCommand: PackageCommand { | ||
|
||
var commandArgument: PositionalArgument<[String]>! | ||
|
||
init(mint: Mint, parser: ArgumentParser) { | ||
super.init(mint: mint, parser: parser, name: "run", description: "Installs and then runs a package") | ||
commandArgument = subparser.add(positional: "command", kind: [String].self, optional: true, strategy: .remaining, usage: "The command to run. This will default to the package name") | ||
} | ||
|
||
override func execute(parsedArguments: ArgumentParser.Result, repo: String, version: String, verbose: Bool) throws { | ||
let arguments = parsedArguments.get(commandArgument) | ||
try mint.run(repo: repo, version: version, verbose: verbose, arguments: arguments) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import Foundation | ||
import Utility | ||
|
||
class UninstallCommand: MintCommand { | ||
|
||
var packageArgument: PositionalArgument<String>! | ||
|
||
init(mint: Mint, parser: ArgumentParser) { | ||
super.init(mint: mint, parser: parser, name: "uninstall", description: "Uninstalls a package by name.\nUse mint list to see all installed packages") | ||
packageArgument = subparser.add(positional: "name", kind: String.self, optional: false, usage: "The name of the package to uninstall") | ||
} | ||
|
||
override func execute(parsedArguments: ArgumentParser.Result) throws { | ||
let package = parsedArguments.get(packageArgument)! | ||
try mint.uninstall(name: package) | ||
} | ||
} |
Oops, something went wrong.