Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Routing][Tooling] Utilize Swift Package Manager tooling #37

Merged
merged 27 commits into from
Feb 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d96a398
[WIP] working through new routing/parsing techniques
namolnad Jan 23, 2019
477ef29
Remove old routing; Remove telemetry; Remove app/version models
namolnad Jan 31, 2019
6a080f8
Wait until exit for Shell; Exit with failure when subtasks does
namolnad Jan 31, 2019
0953268
Add Output helper in Utilities, Simplify/make throwing FileResolver
namolnad Jan 31, 2019
ff7bbdb
Options/Meta/Config members of App. Use Utility.Version
namolnad Jan 31, 2019
da79639
Intro AppRunner and other Command types
namolnad Jan 31, 2019
ecdd91c
Use app.meta, env and tie it all together in main.swift
namolnad Jan 31, 2019
020b747
Remove out of date targets in Package.swift, Fix ssh for pointfree
namolnad Jan 31, 2019
6767bb9
Fix tests; comment out routing tests for the moment
namolnad Jan 31, 2019
e8ac205
Remove directories for old targets
namolnad Jan 31, 2019
7408bc9
Remove extra dependencies in package.swift
namolnad Jan 31, 2019
056ab3d
Remove flags causing linking issues
namolnad Jan 31, 2019
4655fac
Fix and/or disable linting violations
namolnad Jan 31, 2019
1270356
Update Makefile to reflect change in version struct
namolnad Jan 31, 2019
5976438
Redirect output to true. Fix version header behavior
namolnad Jan 31, 2019
b51fcca
Add ability to bind global options from subparser options
namolnad Jan 31, 2019
2db89e9
Fix formatting for Package.swift
namolnad Jan 31, 2019
a82bf64
Reduce to needed dependencies
namolnad Feb 1, 2019
0164ef5
Line spacing
namolnad Feb 1, 2019
fdbe4c3
Intro OutputType; Inject output type for testability
namolnad Feb 1, 2019
89acce0
Add changelogrunner test
namolnad Feb 1, 2019
3be0b28
Add command registry tests
namolnad Feb 1, 2019
a06a546
Add output mock
namolnad Feb 1, 2019
1cff47f
Remove ChangeLogRunner; Add generate command test
namolnad Feb 1, 2019
bb018ef
Correct linting issues
namolnad Feb 1, 2019
5d7ef28
Fix header comment
namolnad Feb 1, 2019
03a3545
Remove unused test class
namolnad Feb 1, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ INSTALL_DIR=$(HOME)/.$(shell echo '$(APP_NAME)' | tr '[:upper:]' '[:lower:]')
BUILD_NUMBER_FILE=./Sources/$(APP_NAME)/App/BuildNumber.swift
VERSION_FILE=./Sources/$(APP_NAME)/App/Version.swift

SWIFT_BUILD_FLAGS=--configuration release -Xswiftc -static-stdlib
SWIFT_BUILD_FLAGS=--configuration release
APP_EXECUTABLE=$(shell swift build $(SWIFT_BUILD_FLAGS) --show-bin-path)/$(APP_NAME)

# ZSH_COMMAND · run single command in `zsh` shell, ignoring most `zsh` startup files.
Expand Down Expand Up @@ -79,7 +79,7 @@ ifdef NEW_VERSION
$(eval MAJOR:=$(word 1,$(VERSION_COMPONENTS)))
$(eval MINOR:=$(word 2,$(VERSION_COMPONENTS)))
$(eval PATCH:=$(word 3,$(VERSION_COMPONENTS)))
@echo "import $(APP_NAME)Core\n\nlet appVersion: Version = .init(major: $(MAJOR), minor: $(MINOR), patch: $(PATCH))" > $(VERSION_FILE)
@echo "import struct Utility.Version\n\nlet appVersion: Version = .init($(MAJOR), $(MINOR), $(PATCH))" > $(VERSION_FILE)
endif

%:
Expand Down
9 changes: 9 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
{
"object": {
"pins": [
{
"package": "SwiftPM",
"repositoryURL": "git@github.com:apple/swift-package-manager.git",
"state": {
"branch": null,
"revision": "235aacc514cb81a6881364b0fedcb3dd083228f3",
"version": "0.3.0"
}
},
{
"package": "SnapshotTesting",
"repositoryURL": "https://github.com/pointfreeco/swift-snapshot-testing",
Expand Down
11 changes: 3 additions & 8 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,19 @@ let package = Package(
.library(name: "DiffFormatterApp", targets: ["DiffFormatterApp"])
],
dependencies: [
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.1.0")
.package(url: "git@github.com:pointfreeco/swift-snapshot-testing", from: "1.1.0"),
.package(url: "git@github.com:apple/swift-package-manager.git", from: "0.3.0")
],
targets: [
.target(
name: "DiffFormatter",
dependencies: ["DiffFormatterApp"]),
.target(
name: "DiffFormatterApp",
dependencies: ["DiffFormatterCore", "DiffFormatterRouting", "DiffFormatterTelemetry", "DiffFormatterUtilities"]),
dependencies: ["DiffFormatterCore", "Utility"]),
.target(
name: "DiffFormatterCore",
dependencies: ["DiffFormatterUtilities"]),
.target(
name: "DiffFormatterRouting",
dependencies: ["DiffFormatterCore", "DiffFormatterUtilities"]),
.target(
name: "DiffFormatterTelemetry",
dependencies: []),
.target(
name: "DiffFormatterUtilities",
dependencies: []),
Expand Down
4 changes: 2 additions & 2 deletions Sources/DiffFormatter/App/Version.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import DiffFormatterCore
import struct Utility.Version

let appVersion: Version = .init(major: 0, minor: 0, patch: 17)
let appVersion: Version = .init(0, 0, 17)
19 changes: 16 additions & 3 deletions Sources/DiffFormatter/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,24 @@
//

import DiffFormatterApp
import DiffFormatterCore
import DiffFormatterUtilities
import Foundation

App(
let processInfo: ProcessInfo = .processInfo

let meta: App.Meta = .init(
buildNumber: appBuildNumber,
name: appName,
version: appVersion
).run(processInfo: ProcessInfo.processInfo)
)

let runner = AppRunner(
environment: processInfo.environment,
meta: meta
)

do {
try runner.run(arguments: processInfo.arguments)
} catch {
Output.instance.print("\(error)", kind: .error)
}
75 changes: 47 additions & 28 deletions Sources/DiffFormatterApp/App.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,53 @@
// Copyright © 2019 DHL. All rights reserved.
//

import DiffFormatterCore
import DiffFormatterRouting
import DiffFormatterTelemetry
import Foundation

extension App {
public func run(processInfo: ProcessInfo) {
let args: [String] = Array(processInfo
.arguments
.dropFirst() // Remove app name/command
)

let scheme = ArgumentScheme(arguments: args)

let configurator = Configurator(processInfo: processInfo, argScheme: scheme)

let router = ArgumentRouter(
app: self,
configuration: configurator.configuration,
handlers: [
ArgumentRouter.usageHandler,
ArgumentRouter.versionHandler,
ArgumentRouter.diffHandler
]
)

if case .notHandled = router.route(argScheme: scheme) {
log.error("Unable to handle included arguments")
import struct Utility.Version
import struct DiffFormatterCore.Configuration
import DiffFormatterUtilities

typealias Version = Utility.Version

public struct App {
public struct Meta {
public typealias Version = Utility.Version

let buildNumber: Int
let name: String
let version: Version

public init(buildNumber: Int, name: String, version: Version) {
self.buildNumber = buildNumber
self.name = name
self.version = version
}
}
public struct Options {
var projectDir: String?
var shouldPrintVersion: Bool
var verbose: Bool
}

public let configuration: Configuration
public let meta: Meta
public let options: Options
private let output: OutputType

init(configuration: Configuration, meta: Meta, options: Options, output: OutputType = Output.instance) {
self.configuration = configuration
self.meta = meta
self.options = options
self.output = output
}

func print(_ value: String, kind: Output.Kind = .default) {
output.print(value, kind: kind, verbose: options.verbose)
}
}

extension App.Options {
static let blank: App.Options = .init(
projectDir: nil,
shouldPrintVersion: false,
verbose: false
)
}
51 changes: 51 additions & 0 deletions Sources/DiffFormatterApp/AppRunner.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// AppRunner.swift
// DiffFormatterApp
//
// Created by Dan Loman on 1/29/19.
//

public class AppRunner {
private let environment: Environment

private let meta: App.Meta

private let registry: CommandRegistry

public init(environment: Environment, meta: App.Meta) {
self.environment = environment
self.meta = meta
self.registry = .init(meta: meta)

registry.register {
GenerateCommand(meta: meta, parser: $0).bindingGlobalOptions(to: $1)
}
}

public func run(arguments: [String]) throws {
let args = Array(arguments.dropFirst())

let (command, options, result) = try registry.parse(arguments: args)

let config = Configurator(
options: options,
meta: meta,
environment: environment
).configuration

let app: App = .init(configuration: config, meta: meta, options: options)

if let command = command {
try registry.runCommand(
named: command,
with: result,
app: app,
env: environment
)
} else if options.shouldPrintVersion {
app.print("\(app.meta.name) \(app.meta.version) (\(app.meta.buildNumber))")
} else {
registry.printUsage()
}
}
}
18 changes: 18 additions & 0 deletions Sources/DiffFormatterApp/Command-Routing/Command.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// Command.swift
// DiffFormatterApp
//
// Created by Dan Loman on 1/29/19.
//

import Utility

public typealias ParsingResult = ArgumentParser.Result
public typealias Environment = [String: String]

protocol Command {
var name: String { get }

func run(with result: ParsingResult, app: App, env: Environment) throws
func bindingGlobalOptions(to binder: ArgumentBinder<App.Options>) -> Self
}
69 changes: 69 additions & 0 deletions Sources/DiffFormatterApp/Command-Routing/CommandRegistry.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//
// CommandRegistry.swift
// DiffFormatterApp
//
// Created by Dan Loman on 1/29/19.
//

import Foundation
import Utility
import var Basic.stdoutStream

final class CommandRegistry {
typealias Binder = ArgumentBinder<App.Options>

private let binder: Binder = .init()

private var commands: [Command] = []

private let parser: ArgumentParser

init(meta: App.Meta) {
// swiftlint:disable line_length
self.parser = .init(
usage: "generate <version1> <version2> [--option]...",
overview: "\(meta.name) is a flexible tool for generating well-formatted changelogs between application versions",
seeAlso: "Visit https://github.com/namolnad/\(meta.name) for more information"
)
// swiftlint:enable line_length

bindOptions(to: binder, using: parser, meta: meta)
}

// swiftlint:disable large_tuple
func parse(arguments: [String]) throws -> (String?, App.Options, ParsingResult) {
let result = try parser.parse(arguments)

var options: App.Options = .blank

try binder.fill(parseResult: result, into: &options)

return (result.subparser(parser), options, result)
}
// swiftlint:enable large_tuple

func printUsage() {
parser.printUsage(on: stdoutStream)
}

func register(command: (ArgumentParser, Binder) -> Command) {
self.commands.append(command(parser, binder))
}

func runCommand(named name: String, with result: ParsingResult, app: App, env: Environment) throws {
guard let command = commands.first(where: { $0.name == name }) else {
return
}

return try command.run(with: result, app: app, env: env)
}

private func bindOptions(to binder: Binder, using parser: ArgumentParser, meta: App.Meta) {
binder.bind(option: parser.add(
option: "--version",
shortName: "-V",
kind: Bool.self,
usage: "Displays current \(meta.name) version and build number"
)) { $0.shouldPrintVersion = $1 }
}
}
Loading