Skip to content

Commit

Permalink
Merge pull request #10 from qutheory/compiled
Browse files Browse the repository at this point in the history
self commands, including compile
  • Loading branch information
tanner0101 committed May 27, 2016
2 parents 3c171dc + ab160b3 commit 5316bb1
Show file tree
Hide file tree
Showing 2 changed files with 202 additions and 89 deletions.
27 changes: 20 additions & 7 deletions .travis.yml
Expand Up @@ -8,12 +8,25 @@ osx_image: xcode7.3
install:
- eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/02090c7ede5a637b76e6df1710e83cd0bbe7dcdf/swiftenv-install.sh)"
script:
- sudo cp vapor /usr/local/bin/vapor # install
- ./vapor self-update # self-update, will overwrite `./vapor` (do not relocate)
- vapor help # help
- vapor new test-project # new
- chmod +x vapor.swift
- ./vapor.swift self install # install
- vapor self compile # compile

# docker
- rm Dockerfile # docker init won't run if file exists
- vapor docker init

# heroku
# - vapor heroku init

# basic
- vapor help # help
- vapor new test-project # new
- cd test-project
- vapor clean # clean
- vapor build # build
- vapor run & # run
- vapor clean # clean
- vapor build # build
- vapor run & # run

# test update
- vapor self update # will update to older version

264 changes: 182 additions & 82 deletions vapor → vapor.swift
Expand Up @@ -258,6 +258,10 @@ extension String {

return newString
}

func colored(with color: ANSIColor) -> String {
return color.rawValue + self + ANSIColor.reset.rawValue
}
}

extension Sequence where Iterator.Element == String {
Expand Down Expand Up @@ -345,33 +349,40 @@ extension Command {
}

extension Command {
static var description: String {
let coloredId = ANSIColor.magenta.rawValue + id + ANSIColor.reset.rawValue
static var description: String {
// Sub Commands
let subCommandRows: [String] = subCommands.map { subCommand in
var output = " \(subCommand.id.colored(with: .blue)):"

if subCommand.help.count > 0 {
output += "\n"
output += subCommand.help.map { row in
return " \(row)"
}.joined(separator: "\n")
output += "\n"
}

guard help.count > 0 else {
return " \(coloredId):\n"
}
return output
}
let subCommandOutput = "\n" + subCommandRows.joined(separator: "\n")

// Sven: The following is not very readable but I stuck with the theme of how the
// description is built. It would be easier if we would just use:
// let subCmdHelpSection = "\n" + subCommands.map { $0.description }.joined(separator: "\n")
// This does work but the indentation is on the same level as the main commands, which looks bad
let subCmdHelpFragments: [String] = subCommands.map { subCommand in
let coloredSubId = ANSIColor.yellow.rawValue + subCommand.id + ANSIColor.reset.rawValue
// Command
var output = " \(id.colored(with: .magenta)):"

return "\n \(coloredSubId):\n"
+ subCommand.help
.map { " \($0)" }
.joined(separator: "\n")
}
let subCmdHelpSection = "\n" + subCmdHelpFragments.joined(separator: "\n")
if help.count > 0 {
output += "\n"

return " \(coloredId):\n"
+ help
.map { " \($0)"}
.joined(separator: "\n")
+ subCmdHelpSection
}
output += help.map { row in
return " \(row)"
}.joined(separator: "\n")

output += "\n"
}

output += subCommandOutput

return output
}
}

extension Command {
Expand Down Expand Up @@ -597,49 +608,152 @@ extension New {
commands.append(New)
// MARK: SelfUpdate
// MARK: Self
struct SelfUpdate: Command {
static let id = "self-update"
extension SelfCommands {
struct Install: Command {
static let id = "install"
static func execute(with args: [String], in directory: String) {
let name = "vapor-cli.tmp"
let quiet = args.contains("--verbose") ? "" : "-s"
static func execute(with args: [String], in directory: String) {
do {
try run("mv \(directory) /usr/local/bin/vapor")
print("Vapor CLI installed.")
} catch {
print("Trying with 'sudo'.")
do {
try run("sudo mv \(directory) /usr/local/bin/vapor")
print("Vapor CLI installed.")
} catch {
fail("Could not move Vapor CLI to install location.")
}
}
}
do {
print("Downloading...")
try run("curl -L \(quiet) cli.qutheory.io -o \(name)")
} catch {
fail("Could not download Vapor CLI.")
static var help: [String] {
return [
"Moves the CLI into the bin so",
"that it is available in the PATH"
]
}
}
}
extension SelfCommands {
struct Update: Command {
static let id = "update"
static func execute(with args: [String], in directory: String) {
let name = "vapor-cli.tmp"
let quiet = args.contains("--verbose") ? "" : "-s"
do {
try run("chmod +x \(name)")
try run("mv \(name) \(directory)")
} catch {
print("Could not move Vapor CLI to install location.")
print("Trying with 'sudo'.")
do {
try run("sudo mv \(name) \(directory)")
print("Downloading...")
try run("curl -L \(quiet) cli.qutheory.io -o \(name)")
} catch {
fail("Could not move Vapor CLI to install location, giving up.")
fail("Could not download Vapor CLI.")
}
do {
try run("chmod +x \(name)")
try run("mv \(name) \(directory)")
print("Vapor CLI updated.")
} catch {
print("Trying with 'sudo'.")
do {
try run("sudo mv \(name) \(directory)")
print("Vapor CLI updated.")
} catch {
fail("Could not move Vapor CLI to install location.")
}
}
}
print("Vapor CLI updated.")
static var help: [String] {
return [
"Downloads the latest version of",
"the Vapor command line interface."
]
}
}
}
extension SelfUpdate {
static var help: [String] {
return [
"Downloads the latest version of",
"the Vapor command line interface."
extension SelfCommands {
struct Compile: Command {
static let id = "compile"
static func execute(with args: [String], in directory: String) {
let source = "vapor-cli.swift"
do {
try run("cp \(directory) \(source)")
} catch {
fail("Could not copy source.")
}
print("Compiling...")
let name = "vapor-cli.tmp"
let compile = "swiftc \(source) -o \(name)"
#if os(OSX)
let cmd = "env SDKROOT=$(xcrun -show-sdk-path -sdk macosx) \(compile)"
#else
let cmd = compile
#endif
do {
try run(cmd)
} catch {
fail("Could not compile.")
}
do {
try run("chmod +x \(name)")
try run("mv \(name) \(directory)")
} catch {
print("Could not move Vapor CLI to install location.")
print("Trying with 'sudo'.")
do {
try run("sudo mv \(name) \(directory)")
} catch {
fail("Could not move Vapor CLI to install location, giving up.")
}
}
do {
try run("rm \(source)")
} catch {
}
print("Vapor CLI compiled.")
}
static var help: [String] {
return [
"Compiles and caches the CLI",
"to improve performance."
]
}
}
}
struct SelfCommands: Command {
static let id = "self"
static var subCommands: [Command.Type] = [
SelfCommands.Update.self,
SelfCommands.Compile.self,
SelfCommands.Install.self
]
}
static func execute(with args: [String], in directory: String) {
executeSubCommand(with: args, in: directory)
}
}
commands.append(SelfUpdate)
commands.append(SelfCommands)
// MARK: Xcode
Expand Down Expand Up @@ -691,48 +805,30 @@ commands.append(Xcode)

// MARK: Heroku

protocol Subcommand: Command {}

struct Heroku: Command {
static let id = "heroku"

static var dependencies = ["git", "heroku"]

static var subcommands: [Subcommand.Type] = []

static var supportedCommands: String {
return subcommands.map { $0.id } .joined(separator: "|")
}

static func subcommand(forId id: String) -> Subcommand.Type? {
return subcommands
.lazy
.filter { $0.id == id }
.first
}
static var subCommands: [Command.Type] = [
Heroku.Init.self,
]

static func execute(with args: [String], in directory: String) {
var iterator = args.makeIterator()
guard let subcommand = iterator.next().flatMap(subcommand(forId:)) else {
fail("heroku subcommand not found. supported: \(supportedCommands)")
}

let passthroughArgs = Array(iterator)
subcommand.execute(with: passthroughArgs, in: directory)
executeSubCommand(with: args, in: directory)
}
}

extension Heroku {
static var help: [String] {
return [
"Configures a new heroku project"
]
}
}

extension Heroku {
struct Init: Subcommand {
struct Init: Command {
static let id = "init"

static var help: [String] {
return [
"Configures a new heroku project"
]
}

static func execute(with args: [String], in directory: String) {
guard args.isEmpty else { fail("heroku init takes no args") }

Expand Down Expand Up @@ -824,15 +920,19 @@ extension Heroku {
}
}

Heroku.subcommands.append(Heroku.Init.self)
commands.append(Heroku)

// MARK: Docker

struct Docker: Command {
static let id = "docker"

static var subCommands: [Command.Type] = [Docker.Init.self, Docker.Build.self, Docker.Run.self, Docker.Enter.self]
static var subCommands: [Command.Type] = [
Docker.Init.self,
Docker.Build.self,
Docker.Run.self,
Docker.Enter.self
]

static func execute(with args: [String], in directory: String) {
executeSubCommand(with: args, in: directory)
Expand Down

0 comments on commit 5316bb1

Please sign in to comment.