Switch to using CocoaSeeds for imports

This commit is contained in:
Andrew Naylor 2015-08-21 22:24:03 +08:00
parent 634df01958
commit d9a5baa7e6
18 changed files with 114 additions and 1275 deletions

2
.gitignore vendored
View file

@ -69,4 +69,4 @@ Network Trash Folder
Temporary Items
.apdisk
Seeds/

View file

@ -1,33 +0,0 @@
// Copyright (c) 2014 Rob Rix. All rights reserved.
/// Wraps a type `T` in a reference type.
///
/// Typically this is used to work around limitations of value types (for example, the lack of codegen for recursive value types and type-parameterized enums with >1 case). It is also useful for sharing a single (presumably large) value without copying it.
public final class Box<T>: BoxType, Printable {
/// Initializes a `Box` with the given value.
public init(_ value: T) {
self.value = value
}
/// Constructs a `Box` with the given `value`.
public class func unit(value: T) -> Box<T> {
return Box(value)
}
/// The (immutable) value wrapped by the receiver.
public let value: T
/// Constructs a new Box by transforming `value` by `f`.
public func map<U>(@noescape f: T -> U) -> Box<U> {
return Box<U>(f(value))
}
// MARK: Printable
public var description: String {
return toString(value)
}
}

View file

@ -1,46 +0,0 @@
// Copyright (c) 2014 Rob Rix. All rights reserved.
// MARK: BoxType
/// The type conformed to by all boxes.
public protocol BoxType {
/// The type of the wrapped value.
typealias Value
/// Initializes an intance of the type with a value.
init(_ value: Value)
/// The wrapped value.
var value: Value { get }
}
/// The type conformed to by mutable boxes.
public protocol MutableBoxType: BoxType {
/// The (mutable) wrapped value.
var value: Value { get set }
}
// MARK: Equality
/// Equality of `BoxType`s of `Equatable` types.
///
/// We cannot declare that e.g. `Box<T: Equatable>` conforms to `Equatable`, so this is a relatively ad hoc definition.
public func == <B: BoxType where B.Value: Equatable> (lhs: B, rhs: B) -> Bool {
return lhs.value == rhs.value
}
/// Inequality of `BoxType`s of `Equatable` types.
///
/// We cannot declare that e.g. `Box<T: Equatable>` conforms to `Equatable`, so this is a relatively ad hoc definition.
public func != <B: BoxType where B.Value: Equatable> (lhs: B, rhs: B) -> Bool {
return lhs.value != rhs.value
}
// MARK: Map
/// Maps the value of a box into a new box.
public func map<B: BoxType, C: BoxType>(v: B, @noescape f: B.Value -> C.Value) -> C {
return C(f(v.value))
}

View file

@ -1,27 +0,0 @@
// Copyright (c) 2014 Rob Rix. All rights reserved.
/// Wraps a type `T` in a mutable reference type.
///
/// While this, like `Box<T>` could be used to work around limitations of value types, it is much more useful for sharing a single mutable value such that mutations are shared.
///
/// As with all mutable state, this should be used carefully, for example as an optimization, rather than a default design choice. Most of the time, `Box<T>` will suffice where any `BoxType` is needed.
public final class MutableBox<T>: MutableBoxType, Printable {
/// Initializes a `MutableBox` with the given value.
public init(_ value: T) {
self.value = value
}
/// The (mutable) value wrapped by the receiver.
public var value: T
/// Constructs a new MutableBox by transforming `value` by `f`.
public func map<U>(@noescape f: T -> U) -> MutableBox<U> {
return MutableBox<U>(f(value))
}
// MARK: Printable
public var description: String {
return toString(value)
}
}

View file

@ -1,189 +0,0 @@
//
// ArgumentParser.swift
// Commandant
//
// Created by Justin Spahr-Summers on 2014-11-21.
// Copyright (c) 2014 Carthage. All rights reserved.
//
import Foundation
/// Represents an argument passed on the command line.
private enum RawArgument: Equatable {
/// A key corresponding to an option (e.g., `verbose` for `--verbose`).
case Key(String)
/// A value, either associated with an option or passed as a positional
/// argument.
case Value(String)
/// One or more flag arguments (e.g 'r' and 'f' for `-rf`)
case Flag(Set<Character>)
}
private func ==(lhs: RawArgument, rhs: RawArgument) -> Bool {
switch (lhs, rhs) {
case let (.Key(left), .Key(right)):
return left == right
case let (.Value(left), .Value(right)):
return left == right
case let (.Flag(left), .Flag(right)):
return left == right
default:
return false
}
}
extension RawArgument: Printable {
private var description: String {
switch self {
case let .Key(key):
return "--\(key)"
case let .Value(value):
return "\"\(value)\""
case let .Flag(flags):
return "-\(String(flags))"
}
}
}
/// Destructively parses a list of command-line arguments.
public final class ArgumentParser {
/// The remaining arguments to be extracted, in their raw form.
private var rawArguments: [RawArgument] = []
/// Initializes the generator from a simple list of command-line arguments.
public init(_ arguments: [String]) {
// The first instance of `--` terminates the option list.
let params = split(arguments, maxSplit: 1, allowEmptySlices: true) { $0 == "--" }
// Parse out the keyed and flag options.
let options = params.first!
rawArguments.extend(options.map { arg in
if arg.hasPrefix("-") {
// Do we have `--{key}` or `-{flags}`.
var opt = dropFirst(arg)
return opt.hasPrefix("-") ? .Key(dropFirst(opt)) : .Flag(Set(opt))
} else {
return .Value(arg)
}
})
// Remaining arguments are all positional parameters.
if params.count == 2 {
let positional = params.last!
rawArguments.extend(positional.map { .Value($0) })
}
}
/// Returns whether the given key was enabled or disabled, or nil if it
/// was not given at all.
///
/// If the key is found, it is then removed from the list of arguments
/// remaining to be parsed.
internal func consumeBooleanKey(key: String) -> Bool? {
let oldArguments = rawArguments
rawArguments.removeAll()
var result: Bool?
for arg in oldArguments {
if arg == .Key(key) {
result = true
} else if arg == .Key("no-\(key)") {
result = false
} else {
rawArguments.append(arg)
}
}
return result
}
/// Returns the value associated with the given flag, or nil if the flag was
/// not specified. If the key is presented, but no value was given, an error
/// is returned.
///
/// If a value is found, the key and the value are both removed from the
/// list of arguments remaining to be parsed.
internal func consumeValueForKey(key: String) -> Result<String?, CommandantError<NoError>> {
let oldArguments = rawArguments
rawArguments.removeAll()
var foundValue: String?
argumentLoop: for var index = 0; index < oldArguments.count; index++ {
let arg = oldArguments[index]
if arg == .Key(key) {
if ++index < oldArguments.count {
switch oldArguments[index] {
case let .Value(value):
foundValue = value
continue argumentLoop
default:
break
}
}
return .failure(missingArgumentError("--\(key)"))
} else {
rawArguments.append(arg)
}
}
return .success(foundValue)
}
/// Returns the next positional argument that hasn't yet been returned, or
/// nil if there are no more positional arguments.
internal func consumePositionalArgument() -> String? {
for var index = 0; index < rawArguments.count; index++ {
switch rawArguments[index] {
case let .Value(value):
rawArguments.removeAtIndex(index)
return value
default:
break
}
}
return nil
}
/// Returns whether the given key was specified and removes it from the
/// list of arguments remaining.
internal func consumeKey(key: String) -> Bool {
let oldArguments = rawArguments
rawArguments = oldArguments.filter { $0 != .Key(key) }
return rawArguments.count < oldArguments.count
}
/// Returns whether the given flag was specified and removes it from the
/// list of arguments remaining.
internal func consumeBooleanFlag(flag: Character) -> Bool {
for (index, arg) in enumerate(rawArguments) {
switch arg {
case var .Flag(flags) where flags.contains(flag):
flags.remove(flag)
if flags.isEmpty {
rawArguments.removeAtIndex(index)
} else {
rawArguments[index] = .Flag(flags)
}
return true
default:
break
}
}
return false
}
}

View file

@ -1,137 +0,0 @@
//
// Command.swift
// Commandant
//
// Created by Justin Spahr-Summers on 2014-10-10.
// Copyright (c) 2014 Carthage. All rights reserved.
//
import Foundation
/// Represents a subcommand that can be executed with its own set of arguments.
public protocol CommandType {
typealias ClientError
/// The action that users should specify to use this subcommand (e.g.,
/// `help`).
var verb: String { get }
/// A human-readable, high-level description of what this command is used
/// for.
var function: String { get }
/// Runs this subcommand in the given mode.
func run(mode: CommandMode) -> Result<(), CommandantError<ClientError>>
}
/// A type-erased CommandType.
public struct CommandOf<ClientError>: CommandType {
public let verb: String
public let function: String
private let runClosure: CommandMode -> Result<(), CommandantError<ClientError>>
/// Creates a command that wraps another.
public init<C: CommandType where C.ClientError == ClientError>(_ command: C) {
verb = command.verb
function = command.function
runClosure = { mode in command.run(mode) }
}
public func run(mode: CommandMode) -> Result<(), CommandantError<ClientError>> {
return runClosure(mode)
}
}
/// Describes the "mode" in which a command should run.
public enum CommandMode {
/// Options should be parsed from the given command-line arguments.
case Arguments(ArgumentParser)
/// Each option should record its usage information in an error, for
/// presentation to the user.
case Usage
}
/// Maintains the list of commands available to run.
public final class CommandRegistry<ClientError> {
private var commandsByVerb: [String: CommandOf<ClientError>] = [:]
/// All available commands.
public var commands: [CommandOf<ClientError>] {
return sorted(commandsByVerb.values) { return $0.verb < $1.verb }
}
public init() {}
/// Registers the given command, making it available to run.
///
/// If another command was already registered with the same `verb`, it will
/// be overwritten.
public func register<C: CommandType where C.ClientError == ClientError>(command: C) {
commandsByVerb[command.verb] = CommandOf(command)
}
/// Runs the command corresponding to the given verb, passing it the given
/// arguments.
///
/// Returns the results of the execution, or nil if no such command exists.
public func runCommand(verb: String, arguments: [String]) -> Result<(), CommandantError<ClientError>>? {
return self[verb]?.run(.Arguments(ArgumentParser(arguments)))
}
/// Returns the command matching the given verb, or nil if no such command
/// is registered.
public subscript(verb: String) -> CommandOf<ClientError>? {
return commandsByVerb[verb]
}
}
extension CommandRegistry {
/// Hands off execution to the CommandRegistry, by parsing Process.arguments
/// and then running whichever command has been identified in the argument
/// list.
///
/// If the chosen command executes successfully, the process will exit with
/// a successful exit code.
///
/// If the chosen command fails, the provided error handler will be invoked,
/// then the process will exit with a failure exit code.
///
/// If a matching command could not be found or a usage error occurred,
/// a helpful error message will be written to `stderr`, then the process
/// will exit with a failure error code.
@noreturn public func main(#defaultVerb: String, errorHandler: ClientError -> ()) {
var arguments = Process.arguments
assert(arguments.count >= 1)
// Extract the executable name.
let executableName = arguments.first!
arguments.removeAtIndex(0)
let verb = arguments.first ?? defaultVerb
if arguments.count > 0 {
// Remove the command name.
arguments.removeAtIndex(0)
}
switch runCommand(verb, arguments: arguments) {
case .Some(.Success):
exit(EXIT_SUCCESS)
case let .Some(.Failure(error)):
switch error.value {
case let .UsageError(description):
fputs(description + "\n", stderr)
case let .CommandError(error):
errorHandler(error.value)
}
exit(EXIT_FAILURE)
case .None:
fputs("Unrecognized command: '\(verb)'. See `\(executableName) help`.\n", stderr)
exit(EXIT_FAILURE)
}
}
}

View file

@ -1,17 +0,0 @@
//
// Commandant.h
// Commandant
//
// Created by Justin Spahr-Summers on 2014-11-21.
// Copyright (c) 2014 Carthage. All rights reserved.
//
#import <Foundation/Foundation.h>
//! Project version number for Commandant.
FOUNDATION_EXPORT double CommandantVersionNumber;
//! Project version string for Commandant.
FOUNDATION_EXPORT const unsigned char CommandantVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <Commandant/PublicHeader.h>

View file

@ -1,114 +0,0 @@
//
// Errors.swift
// Commandant
//
// Created by Justin Spahr-Summers on 2014-10-24.
// Copyright (c) 2014 Carthage. All rights reserved.
//
import Foundation
/// Possible errors that can originate from Commandant.
///
/// `ClientError` should be the type of error (if any) that can occur when
/// running commands.
public enum CommandantError<ClientError> {
/// An option was used incorrectly.
case UsageError(description: String)
/// An error occurred while running a command.
case CommandError(Box<ClientError>)
}
extension CommandantError: Printable {
public var description: String {
switch self {
case let .UsageError(description):
return description
case let .CommandError(error):
return toString(error)
}
}
}
/// Used to represent that a ClientError will never occur.
internal enum NoError {}
/// Constructs an `InvalidArgument` error that indicates a missing value for
/// the argument by the given name.
internal func missingArgumentError<ClientError>(argumentName: String) -> CommandantError<ClientError> {
let description = "Missing argument for \(argumentName)"
return .UsageError(description: description)
}
/// Constructs an error by combining the example of key (and value, if applicable)
/// with the usage description.
internal func informativeUsageError<ClientError>(keyValueExample: String, usage: String) -> CommandantError<ClientError> {
let lines = usage.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet())
return .UsageError(description: reduce(lines, keyValueExample) { previous, value in
return previous + "\n\t" + value
})
}
/// Constructs an error that describes how to use the option, with the given
/// example of key (and value, if applicable) usage.
internal func informativeUsageError<T, ClientError>(keyValueExample: String, option: Option<T>) -> CommandantError<ClientError> {
if option.defaultValue != nil {
return informativeUsageError("[\(keyValueExample)]", option.usage)
} else {
return informativeUsageError(keyValueExample, option.usage)
}
}
/// Constructs an error that describes how to use the option.
internal func informativeUsageError<T: ArgumentType, ClientError>(option: Option<T>) -> CommandantError<ClientError> {
var example = ""
if let key = option.key {
example += "--\(key) "
}
var valueExample = ""
if let defaultValue = option.defaultValue {
valueExample = "\(defaultValue)"
}
if valueExample.isEmpty {
example += "(\(T.name))"
} else {
example += valueExample
}
return informativeUsageError(example, option)
}
/// Constructs an error that describes how to use the given boolean option.
internal func informativeUsageError<ClientError>(option: Option<Bool>) -> CommandantError<ClientError> {
precondition(option.key != nil)
let key = option.key!
if let defaultValue = option.defaultValue {
return informativeUsageError((defaultValue ? "--no-\(key)" : "--\(key)"), option)
} else {
return informativeUsageError("--(no-)\(key)", option)
}
}
/// Combines the text of the two errors, if they're both `UsageError`s.
/// Otherwise, uses whichever one is not (biased toward the left).
internal func combineUsageErrors<ClientError>(lhs: CommandantError<ClientError>, rhs: CommandantError<ClientError>) -> CommandantError<ClientError> {
switch (lhs, rhs) {
case let (.UsageError(left), .UsageError(right)):
let combinedDescription = "\(left)\n\n\(right)"
return .UsageError(description: combinedDescription)
case (.UsageError, _):
return rhs
case (_, .UsageError), (_, _):
return lhs
}
}

View file

@ -1,78 +0,0 @@
//
// HelpCommand.swift
// Commandant
//
// Created by Justin Spahr-Summers on 2014-10-10.
// Copyright (c) 2014 Carthage. All rights reserved.
//
import Foundation
/// A basic implementation of a `help` command, using information available in a
/// `CommandRegistry`.
///
/// If you want to use this command, initialize it with the registry, then add
/// it to that same registry:
///
/// let commands: CommandRegistry<MyErrorType> =
/// let helpCommand = HelpCommand(registry: commands)
/// commands.register(helpCommand)
public struct HelpCommand<ClientError>: CommandType {
public let verb = "help"
public let function = "Display general or command-specific help"
private let registry: CommandRegistry<ClientError>
/// Initializes the command to provide help from the given registry of
/// commands.
public init(registry: CommandRegistry<ClientError>) {
self.registry = registry
}
public func run(mode: CommandMode) -> Result<(), CommandantError<ClientError>> {
return HelpOptions<ClientError>.evaluate(mode)
.flatMap { options in
if let verb = options.verb {
if let command = self.registry[verb] {
println(command.function)
println()
return command.run(.Usage)
} else {
fputs("Unrecognized command: '\(verb)'\n", stderr)
}
}
println("Available commands:\n")
let maxVerbLength = maxElement(self.registry.commands.map { count($0.verb) })
for command in self.registry.commands {
let padding = Repeat<Character>(count: maxVerbLength - count(command.verb), repeatedValue: " ")
var formattedVerb = command.verb
formattedVerb.extend(padding)
println(" \(formattedVerb) \(command.function)")
}
return .success(())
}
}
}
private struct HelpOptions<ClientError>: OptionsType {
let verb: String?
init(verb: String?) {
self.verb = verb
}
static func create(verb: String) -> HelpOptions {
return self(verb: (verb == "" ? nil : verb))
}
static func evaluate(m: CommandMode) -> Result<HelpOptions, CommandantError<ClientError>> {
return create
<*> m <| Option(defaultValue: "", usage: "the command to display help for")
}
}

View file

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>org.carthage.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.6.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2014 Carthage. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View file

@ -1,246 +0,0 @@
//
// Option.swift
// Commandant
//
// Created by Justin Spahr-Summers on 2014-11-21.
// Copyright (c) 2014 Carthage. All rights reserved.
//
import Foundation
/// Represents a record of options for a command, which can be parsed from
/// a list of command-line arguments.
///
/// This is most helpful when used in conjunction with the `Option` and `Switch`
/// types, and `<*>` and `<|` combinators.
///
/// Example:
///
/// struct LogOptions: OptionsType {
/// let verbosity: Int
/// let outputFilename: String
/// let logName: String
///
/// static func create(verbosity: Int)(outputFilename: String)(logName: String) -> LogOptions {
/// return LogOptions(verbosity: verbosity, outputFilename: outputFilename, logName: logName)
/// }
///
/// static func evaluate(m: CommandMode) -> Result<LogOptions> {
/// return create
/// <*> m <| Option(key: "verbose", defaultValue: 0, usage: "the verbosity level with which to read the logs")
/// <*> m <| Option(key: "outputFilename", defaultValue: "", usage: "a file to print output to, instead of stdout")
/// <*> m <| Switch(flag: "d", key: "delete", defaultValue: false, usage: "delete the logs when finished")
/// <*> m <| Option(usage: "the log to read")
/// }
/// }
public protocol OptionsType {
typealias ClientError
/// Evaluates this set of options in the given mode.
///
/// Returns the parsed options or a `UsageError`.
static func evaluate(m: CommandMode) -> Result<Self, CommandantError<ClientError>>
}
/// Describes an option that can be provided on the command line.
public struct Option<T> {
/// The key that controls this option. For example, a key of `verbose` would
/// be used for a `--verbose` option.
///
/// If this is nil, this option will not have a corresponding flag, and must
/// be specified as a plain value at the end of the argument list.
///
/// This must be non-nil for a boolean option.
public let key: String?
/// The default value for this option. This is the value that will be used
/// if the option is never explicitly specified on the command line.
///
/// If this is nil, this option is always required.
public let defaultValue: T?
/// A human-readable string describing the purpose of this option. This will
/// be shown in help messages.
///
/// For boolean operations, this should describe the effect of _not_ using
/// the default value (i.e., what will happen if you disable/enable the flag
/// differently from the default).
public let usage: String
public init(key: String? = nil, defaultValue: T? = nil, usage: String) {
self.key = key
self.defaultValue = defaultValue
self.usage = usage
}
/// Constructs an `InvalidArgument` error that describes how the option was
/// used incorrectly. `value` should be the invalid value given by the user.
private func invalidUsageError<ClientError>(value: String) -> CommandantError<ClientError> {
let description = "Invalid value for '\(self)': \(value)"
return .UsageError(description: description)
}
}
extension Option: Printable {
public var description: String {
if let key = key {
return "--\(key)"
} else {
return usage
}
}
}
/// Represents a value that can be converted from a command-line argument.
public protocol ArgumentType {
/// A human-readable name for this type.
static var name: String { get }
/// Attempts to parse a value from the given command-line argument.
static func fromString(string: String) -> Self?
}
extension Int: ArgumentType {
public static let name = "integer"
public static func fromString(string: String) -> Int? {
return string.toInt()
}
}
extension String: ArgumentType {
public static let name = "string"
public static func fromString(string: String) -> String? {
return string
}
}
// Inspired by the Argo library:
// https://github.com/thoughtbot/Argo
/*
Copyright (c) 2014 thoughtbot, inc.
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
infix operator <*> {
associativity left
}
infix operator <| {
associativity left
precedence 150
}
/// Applies `f` to the value in the given result.
///
/// In the context of command-line option parsing, this is used to chain
/// together the parsing of multiple arguments. See OptionsType for an example.
public func <*> <T, U, ClientError>(f: T -> U, value: Result<T, CommandantError<ClientError>>) -> Result<U, CommandantError<ClientError>> {
return value.map(f)
}
/// Applies the function in `f` to the value in the given result.
///
/// In the context of command-line option parsing, this is used to chain
/// together the parsing of multiple arguments. See OptionsType for an example.
public func <*> <T, U, ClientError>(f: Result<(T -> U), CommandantError<ClientError>>, value: Result<T, CommandantError<ClientError>>) -> Result<U, CommandantError<ClientError>> {
switch (f, value) {
case let (.Failure(left), .Failure(right)):
return .failure(combineUsageErrors(left.value, right.value))
case let (.Failure(left), .Success):
return .failure(left.value)
case let (.Success, .Failure(right)):
return .failure(right.value)
case let (.Success(f), .Success(value)):
let newValue = f.value(value.value)
return .success(newValue)
}
}
/// Evaluates the given option in the given mode.
///
/// If parsing command line arguments, and no value was specified on the command
/// line, the option's `defaultValue` is used.
public func <| <T: ArgumentType, ClientError>(mode: CommandMode, option: Option<T>) -> Result<T, CommandantError<ClientError>> {
switch mode {
case let .Arguments(arguments):
var stringValue: String?
if let key = option.key {
switch arguments.consumeValueForKey(key) {
case let .Success(value):
stringValue = value.value
case let .Failure(error):
switch error.value {
case let .UsageError(description):
return .failure(.UsageError(description: description))
case .CommandError:
fatalError("CommandError should be impossible when parameterized over NoError")
}
}
} else {
stringValue = arguments.consumePositionalArgument()
}
if let stringValue = stringValue {
if let value = T.fromString(stringValue) {
return .success(value)
}
return .failure(option.invalidUsageError(stringValue))
} else if let defaultValue = option.defaultValue {
return .success(defaultValue)
} else {
return .failure(missingArgumentError(option.description))
}
case .Usage:
return .failure(informativeUsageError(option))
}
}
/// Evaluates the given boolean option in the given mode.
///
/// If parsing command line arguments, and no value was specified on the command
/// line, the option's `defaultValue` is used.
public func <| <ClientError>(mode: CommandMode, option: Option<Bool>) -> Result<Bool, CommandantError<ClientError>> {
precondition(option.key != nil)
switch mode {
case let .Arguments(arguments):
if let value = arguments.consumeBooleanKey(option.key!) {
return .success(value)
} else if let defaultValue = option.defaultValue {
return .success(defaultValue)
} else {
return .failure(missingArgumentError(option.description))
}
case .Usage:
return .failure(informativeUsageError(option))
}
}

View file

@ -1,62 +0,0 @@
//
// Switch.swift
// Commandant
//
// Created by Neil Pankey on 3/31/15.
// Copyright (c) 2015 Carthage. All rights reserved.
//
/// Describes a parameterless command line flag that defaults to false and can only
/// be switched on. Canonical examples include `--force` and `--recurse`.
///
/// For a boolean toggle that can be enabled and disabled use `Option<Bool>`.
public struct Switch {
/// The key that enables this switch. For example, a key of `verbose` would be
/// used for a `--verbose` option.
public let key: String
/// Optional single letter flag that enables this switch. For example, `-v` would
/// be used as a shorthand for `--verbose`.
///
/// Multiple flags can be grouped together as a single argument and will split
/// when parsing (e.g. `rm -rf` treats 'r' and 'f' as inidividual flags).
public let flag: Character?
/// A human-readable string describing the purpose of this option. This will
/// be shown in help messages.
public let usage: String
public init(flag: Character? = nil, key: String, usage: String) {
self.flag = flag
self.key = key
self.usage = usage
}
}
extension Switch: Printable {
public var description: String {
var options = "--\(key)"
if let flag = self.flag {
options += "|-\(flag)"
}
return options
}
}
/// Evaluates the given boolean switch in the given mode.
///
/// If parsing command line arguments, and no value was specified on the command
/// line, the option's `defaultValue` is used.
public func <| <ClientError> (mode: CommandMode, option: Switch) -> Result<Bool, CommandantError<ClientError>> {
switch mode {
case let .Arguments(arguments):
var enabled = arguments.consumeKey(option.key)
if let flag = option.flag {
enabled = arguments.consumeBooleanFlag(flag)
}
return .success(enabled)
case .Usage:
return .failure(informativeUsageError(option.description, option.usage))
}
}

4
Gemfile Normal file
View file

@ -0,0 +1,4 @@
# A sample Gemfile
source "https://rubygems.org"
gem "cocoaseeds", "~>0.2"

34
Gemfile.lock Normal file
View file

@ -0,0 +1,34 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (4.2.3)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
claide (0.9.1)
cocoaseeds (0.2.0)
colorize (~> 0.7)
xcodeproj (~> 0.24)
colored (1.2)
colorize (0.7.7)
i18n (0.7.0)
json (1.8.3)
minitest (5.8.0)
thread_safe (0.3.5)
tzinfo (1.2.2)
thread_safe (~> 0.1)
xcodeproj (0.26.3)
activesupport (>= 3)
claide (~> 0.9.1)
colored (~> 1.2)
PLATFORMS
ruby
DEPENDENCIES
cocoaseeds (~> 0.2)
BUNDLED WITH
1.10.6

View file

@ -1,7 +0,0 @@
// Copyright (c) 2015 Rob Rix. All rights reserved.
/// Project version number for Result.
extern double ResultVersionNumber;
/// Project version string for Result.
extern const unsigned char ResultVersionString[];

View file

@ -1,218 +0,0 @@
// Copyright (c) 2015 Rob Rix. All rights reserved.
/// An enum representing either a failure with an explanatory error, or a success with a result value.
public enum Result<T, Error>: Printable, DebugPrintable {
case Success(Box<T>)
case Failure(Box<Error>)
// MARK: Constructors
/// Constructs a success wrapping a `value`.
public init(value: T) {
self = .Success(Box(value))
}
/// Constructs a failure wrapping an `error`.
public init(error: Error) {
self = .Failure(Box(error))
}
/// Constructs a result from an Optional, failing with `Error` if `nil`
public init(_ value: T?, @autoclosure failWith: () -> Error) {
self = value.map { .success($0) } ?? .failure(failWith())
}
/// Constructs a success wrapping a `value`.
public static func success(value: T) -> Result {
return Result(value: value)
}
/// Constructs a failure wrapping an `error`.
public static func failure(error: Error) -> Result {
return Result(error: error)
}
// MARK: Deconstruction
/// Returns the value from `Success` Results, `nil` otherwise.
public var value: T? {
return analysis(ifSuccess: { $0 }, ifFailure: { _ in nil })
}
/// Returns the error from `Failure` Results, `nil` otherwise.
public var error: Error? {
return analysis(ifSuccess: { _ in nil }, ifFailure: { $0 })
}
/// Case analysis for Result.
///
/// Returns the value produced by applying `ifFailure` to `Failure` Results, or `ifSuccess` to `Success` Results.
public func analysis<Result>(@noescape #ifSuccess: T -> Result, @noescape ifFailure: Error -> Result) -> Result {
switch self {
case let .Success(value):
return ifSuccess(value.value)
case let .Failure(value):
return ifFailure(value.value)
}
}
// MARK: Higher-order functions
/// Returns a new Result by mapping `Success`es values using `transform`, or re-wrapping `Failure`s errors.
public func map<U>(@noescape transform: T -> U) -> Result<U, Error> {
return flatMap { .success(transform($0)) }
}
/// Returns the result of applying `transform` to `Success`es values, or re-wrapping `Failure`s errors.
public func flatMap<U>(@noescape transform: T -> Result<U, Error>) -> Result<U, Error> {
return analysis(
ifSuccess: transform,
ifFailure: Result<U, Error>.failure)
}
/// Returns `self.value` if this result is a .Success, or the given value otherwise. Equivalent with `??`
public func recover(@autoclosure value: () -> T) -> T {
return self.value ?? value()
}
/// Returns this result if it is a .Success, or the given result otherwise. Equivalent with `??`
public func recoverWith(@autoclosure result: () -> Result<T,Error>) -> Result<T,Error> {
return analysis(
ifSuccess: { _ in self },
ifFailure: { _ in result() })
}
// MARK: Errors
/// The domain for errors constructed by Result.
public static var errorDomain: String { return "com.antitypical.Result" }
/// The userInfo key for source functions in errors constructed by Result.
public static var functionKey: String { return "\(errorDomain).function" }
/// The userInfo key for source file paths in errors constructed by Result.
public static var fileKey: String { return "\(errorDomain).file" }
/// The userInfo key for source file line numbers in errors constructed by Result.
public static var lineKey: String { return "\(errorDomain).line" }
/// Constructs an error.
public static func error(message: String? = nil, function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__) -> NSError {
var userInfo: [String: AnyObject] = [
functionKey: function,
fileKey: file,
lineKey: line,
]
if let message = message {
userInfo[NSLocalizedDescriptionKey] = message
}
return NSError(domain: errorDomain, code: 0, userInfo: userInfo)
}
// MARK: Printable
public var description: String {
return analysis(
ifSuccess: { ".Success(\($0))" },
ifFailure: { ".Failure(\($0))" })
}
// MARK: DebugPrintable
public var debugDescription: String {
return description
}
}
/// Returns `true` if `left` and `right` are both `Success`es and their values are equal, or if `left` and `right` are both `Failure`s and their errors are equal.
public func == <T: Equatable, Error: Equatable> (left: Result<T, Error>, right: Result<T, Error>) -> Bool {
if let left = left.value, right = right.value {
return left == right
} else if let left = left.error, right = right.error {
return left == right
}
return false
}
/// Returns `true` if `left` and `right` represent different cases, or if they represent the same case but different values.
public func != <T: Equatable, Error: Equatable> (left: Result<T, Error>, right: Result<T, Error>) -> Bool {
return !(left == right)
}
/// Returns the value of `left` if it is a `Success`, or `right` otherwise. Short-circuits.
public func ?? <T, Error> (left: Result<T, Error>, @autoclosure right: () -> T) -> T {
return left.recover(right())
}
/// Returns `left` if it is a `Success`es, or `right` otherwise. Short-circuits.
public func ?? <T, Error> (left: Result<T, Error>, @autoclosure right: () -> Result<T, Error>) -> Result<T, Error> {
return left.recoverWith(right())
}
// MARK: - Cocoa API conveniences
/// Constructs a Result with the result of calling `try` with an error pointer.
///
/// This is convenient for wrapping Cocoa API which returns an object or `nil` + an error, by reference. e.g.:
///
/// Result.try { NSData(contentsOfURL: URL, options: .DataReadingMapped, error: $0) }
public func try<T>(function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__, try: NSErrorPointer -> T?) -> Result<T, NSError> {
var error: NSError?
return try(&error).map(Result.success) ?? Result.failure(error ?? Result<T, NSError>.error(function: function, file: file, line: line))
}
/// Constructs a Result with the result of calling `try` with an error pointer.
///
/// This is convenient for wrapping Cocoa API which returns a `Bool` + an error, by reference. e.g.:
///
/// Result.try { NSFileManager.defaultManager().removeItemAtURL(URL, error: $0) }
public func try(function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__, try: NSErrorPointer -> Bool) -> Result<(), NSError> {
var error: NSError?
return try(&error) ?
.success(())
: .failure(error ?? Result<(), NSError>.error(function: function, file: file, line: line))
}
// MARK: - Operators
infix operator >>- {
// Left-associativity so that chaining works like youd expect, and for consistency with Haskell, Runes, swiftz, etc.
associativity left
// Higher precedence than function application, but lower than function composition.
precedence 100
}
infix operator &&& {
/// Same associativity as &&.
associativity left
/// Same precedence as &&.
precedence 120
}
/// Returns the result of applying `transform` to `Success`es values, or re-wrapping `Failure`s errors.
///
/// This is a synonym for `flatMap`.
public func >>- <T, U, Error> (result: Result<T, Error>, @noescape transform: T -> Result<U, Error>) -> Result<U, Error> {
return result.flatMap(transform)
}
/// Returns a Result with a tuple of `left` and `right` values if both are `Success`es, or re-wrapping the error of the earlier `Failure`.
public func &&& <T, U, Error> (left: Result<T, Error>, @autoclosure right: () -> Result<U, Error>) -> Result<(T, U), Error> {
return left.flatMap { left in right().map { right in (left, right) } }
}
import Foundation

3
Seedfile Normal file
View file

@ -0,0 +1,3 @@
github "Carthage/Commandant", "0.6.1", :files => "Commandant/*.swift"
github "antitypical/Result", "0.4.3", :files => "Result/*.swift"
github "robrix/Box", "1.2.1", :files => "Box/{Box,BoxType,MutableBox}.swift"

View file

@ -7,6 +7,15 @@
objects = {
/* Begin PBXBuildFile section */
1CC607DA6B900AA3FEC3F6D8 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9257C5FABA335E5F060CB7F7 /* Result.swift */; };
21EC092422A3EDFE33B153B8 /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1005EEE43D06F809260BEA /* Command.swift */; };
5918483F96256CDAC88FF450 /* HelpCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7F27132AB0C6BC7BA7078EF /* HelpCommand.swift */; };
66110A826B78DD6BAEC50E70 /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7B1825DB425D0D3D345597 /* Box.swift */; };
6C2E8E6E36A6598C7DA5BAB5 /* ArgumentParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52882737E43AACD9AAEF5D9D /* ArgumentParser.swift */; };
7858BCFB4D5A4251DE998CE4 /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54F23BBFDBCD3D4CAF67DE68 /* Switch.swift */; };
92828DCD99CED47F54242776 /* Option.swift in Sources */ = {isa = PBXBuildFile; fileRef = AECDEA314BB1F1599638884C /* Option.swift */; };
B80C5DDD38A8F7EB6F320697 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E553CF8A2DE31278400C3A /* Errors.swift */; };
DE39BCA91D1BC3D876711677 /* MutableBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8007A86176C1DC9462A80FA /* MutableBox.swift */; };
ED031A7C1B5127C00097692E /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED031A7B1B5127C00097692E /* main.swift */; };
ED0F237F1B87522400AE40CD /* Install.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F237E1B87522400AE40CD /* Install.swift */; };
ED0F23831B87533A00AE40CD /* ListInstalled.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F23821B87533A00AE40CD /* ListInstalled.swift */; };
@ -15,18 +24,9 @@
ED0F23891B87543D00AE40CD /* DownloadQueueObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F23881B87543D00AE40CD /* DownloadQueueObserver.swift */; };
ED0F238B1B87569C00AE40CD /* Downloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F238A1B87569C00AE40CD /* Downloader.swift */; };
ED0F238D1B8756E600AE40CD /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F238C1B8756E600AE40CD /* Error.swift */; };
ED128ECA1B6C2A0B00C4050A /* ArgumentParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EC11B6C2A0B00C4050A /* ArgumentParser.swift */; };
ED128ECB1B6C2A0B00C4050A /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EC21B6C2A0B00C4050A /* Command.swift */; };
ED128ECC1B6C2A0B00C4050A /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EC41B6C2A0B00C4050A /* Errors.swift */; };
ED128ECD1B6C2A0B00C4050A /* HelpCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EC51B6C2A0B00C4050A /* HelpCommand.swift */; };
ED128ECE1B6C2A0B00C4050A /* Option.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EC71B6C2A0B00C4050A /* Option.swift */; };
ED128ECF1B6C2A0B00C4050A /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EC81B6C2A0B00C4050A /* Switch.swift */; };
ED128ED31B6C2AA200C4050A /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128ED21B6C2AA200C4050A /* Result.swift */; };
ED128EDC1B6C2B4400C4050A /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128ED91B6C2B4400C4050A /* Box.swift */; };
ED128EDD1B6C2B4400C4050A /* BoxType.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EDA1B6C2B4400C4050A /* BoxType.swift */; };
ED128EDE1B6C2B4400C4050A /* MutableBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EDB1B6C2B4400C4050A /* MutableBox.swift */; };
EDEAA0C01B51CE6200F2FC3F /* StoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDEAA0BF1B51CE6200F2FC3F /* StoreFoundation.framework */; };
EDEAA17D1B5C579100F2FC3F /* CommerceKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDEAA17C1B5C579100F2FC3F /* CommerceKit.framework */; };
F5F01044EC3065C6EBAB95D7 /* BoxType.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0E87CFA5E6371893D5B1807 /* BoxType.swift */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -42,6 +42,14 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
52882737E43AACD9AAEF5D9D /* ArgumentParser.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ArgumentParser.swift; path = Seeds/Commandant/Commandant/ArgumentParser.swift; sourceTree = "<group>"; };
54F23BBFDBCD3D4CAF67DE68 /* Switch.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Switch.swift; path = Seeds/Commandant/Commandant/Switch.swift; sourceTree = "<group>"; };
9257C5FABA335E5F060CB7F7 /* Result.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Result.swift; path = Seeds/Result/Result/Result.swift; sourceTree = "<group>"; };
AECDEA314BB1F1599638884C /* Option.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Option.swift; path = Seeds/Commandant/Commandant/Option.swift; sourceTree = "<group>"; };
B7F27132AB0C6BC7BA7078EF /* HelpCommand.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HelpCommand.swift; path = Seeds/Commandant/Commandant/HelpCommand.swift; sourceTree = "<group>"; };
B8007A86176C1DC9462A80FA /* MutableBox.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MutableBox.swift; path = Seeds/Box/Box/MutableBox.swift; sourceTree = "<group>"; };
C4E553CF8A2DE31278400C3A /* Errors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Errors.swift; path = Seeds/Commandant/Commandant/Errors.swift; sourceTree = "<group>"; };
DD1005EEE43D06F809260BEA /* Command.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Command.swift; path = Seeds/Commandant/Commandant/Command.swift; sourceTree = "<group>"; };
ED031A781B5127C00097692E /* mas-cli */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "mas-cli"; sourceTree = BUILT_PRODUCTS_DIR; };
ED031A7B1B5127C00097692E /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
ED0F237E1B87522400AE40CD /* Install.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Install.swift; sourceTree = "<group>"; };
@ -51,20 +59,6 @@
ED0F23881B87543D00AE40CD /* DownloadQueueObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownloadQueueObserver.swift; sourceTree = "<group>"; };
ED0F238A1B87569C00AE40CD /* Downloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Downloader.swift; sourceTree = "<group>"; };
ED0F238C1B8756E600AE40CD /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; };
ED128EC11B6C2A0B00C4050A /* ArgumentParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArgumentParser.swift; sourceTree = "<group>"; };
ED128EC21B6C2A0B00C4050A /* Command.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = "<group>"; };
ED128EC31B6C2A0B00C4050A /* Commandant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Commandant.h; sourceTree = "<group>"; };
ED128EC41B6C2A0B00C4050A /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = "<group>"; };
ED128EC51B6C2A0B00C4050A /* HelpCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HelpCommand.swift; sourceTree = "<group>"; };
ED128EC61B6C2A0B00C4050A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
ED128EC71B6C2A0B00C4050A /* Option.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Option.swift; sourceTree = "<group>"; };
ED128EC81B6C2A0B00C4050A /* Switch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Switch.swift; sourceTree = "<group>"; };
ED128ED11B6C2A8B00C4050A /* Result.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Result.h; sourceTree = "<group>"; };
ED128ED21B6C2AA200C4050A /* Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = "<group>"; };
ED128ED81B6C2B4400C4050A /* Box.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Box.h; sourceTree = "<group>"; };
ED128ED91B6C2B4400C4050A /* Box.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Box.swift; sourceTree = "<group>"; };
ED128EDA1B6C2B4400C4050A /* BoxType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxType.swift; sourceTree = "<group>"; };
ED128EDB1B6C2B4400C4050A /* MutableBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MutableBox.swift; sourceTree = "<group>"; };
EDEAA0BF1B51CE6200F2FC3F /* StoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreFoundation.framework; path = /System/Library/PrivateFrameworks/StoreFoundation.framework; sourceTree = "<absolute>"; };
EDEAA0C31B51CEE400F2FC3F /* CDStructures.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CDStructures.h; sourceTree = "<group>"; };
EDEAA0C41B51CEE400F2FC3F /* CKBook.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKBook.h; sourceTree = "<group>"; };
@ -250,6 +244,8 @@
EDEAA17A1B5C576D00F2FC3F /* SSRestoreContentItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSRestoreContentItem.h; sourceTree = "<group>"; };
EDEAA17B1B5C576D00F2FC3F /* SSURLRequestProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSURLRequestProperties.h; sourceTree = "<group>"; };
EDEAA17C1B5C579100F2FC3F /* CommerceKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CommerceKit.framework; path = /System/Library/PrivateFrameworks/CommerceKit.framework; sourceTree = "<absolute>"; };
F0E87CFA5E6371893D5B1807 /* BoxType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BoxType.swift; path = Seeds/Box/Box/BoxType.swift; sourceTree = "<group>"; };
FC7B1825DB425D0D3D345597 /* Box.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Box.swift; path = Seeds/Box/Box/Box.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -265,16 +261,55 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0739FA024AB80925B32D64D1 /* Seeds */ = {
isa = PBXGroup;
children = (
0DBDF2D12EBF050099F36BEE /* Box */,
A49C8EB621015CD588C621FD /* Commandant */,
6569B225928F21A4A639BB22 /* Result */,
);
name = Seeds;
sourceTree = "<group>";
};
0DBDF2D12EBF050099F36BEE /* Box */ = {
isa = PBXGroup;
children = (
FC7B1825DB425D0D3D345597 /* Box.swift */,
F0E87CFA5E6371893D5B1807 /* BoxType.swift */,
B8007A86176C1DC9462A80FA /* MutableBox.swift */,
);
name = Box;
sourceTree = "<group>";
};
6569B225928F21A4A639BB22 /* Result */ = {
isa = PBXGroup;
children = (
9257C5FABA335E5F060CB7F7 /* Result.swift */,
);
name = Result;
sourceTree = "<group>";
};
A49C8EB621015CD588C621FD /* Commandant */ = {
isa = PBXGroup;
children = (
52882737E43AACD9AAEF5D9D /* ArgumentParser.swift */,
DD1005EEE43D06F809260BEA /* Command.swift */,
C4E553CF8A2DE31278400C3A /* Errors.swift */,
B7F27132AB0C6BC7BA7078EF /* HelpCommand.swift */,
AECDEA314BB1F1599638884C /* Option.swift */,
54F23BBFDBCD3D4CAF67DE68 /* Switch.swift */,
);
name = Commandant;
sourceTree = "<group>";
};
ED031A6F1B5127C00097692E = {
isa = PBXGroup;
children = (
ED128ED61B6C2AF200C4050A /* Box */,
ED128EC91B6C2A0B00C4050A /* Commandant */,
EDFC76381B642A2E00D0DBD7 /* Frameworks */,
EDEAA0C11B51CEBD00F2FC3F /* Headers */,
ED031A7A1B5127C00097692E /* mas-cli */,
ED031A791B5127C00097692E /* Products */,
ED128ED01B6C2A7300C4050A /* Result */,
0739FA024AB80925B32D64D1 /* Seeds */,
);
sourceTree = "<group>";
};
@ -311,41 +346,6 @@
path = "mas-cli/Commands";
sourceTree = SOURCE_ROOT;
};
ED128EC91B6C2A0B00C4050A /* Commandant */ = {
isa = PBXGroup;
children = (
ED128EC11B6C2A0B00C4050A /* ArgumentParser.swift */,
ED128EC21B6C2A0B00C4050A /* Command.swift */,
ED128EC31B6C2A0B00C4050A /* Commandant.h */,
ED128EC41B6C2A0B00C4050A /* Errors.swift */,
ED128EC51B6C2A0B00C4050A /* HelpCommand.swift */,
ED128EC61B6C2A0B00C4050A /* Info.plist */,
ED128EC71B6C2A0B00C4050A /* Option.swift */,
ED128EC81B6C2A0B00C4050A /* Switch.swift */,
);
path = Commandant;
sourceTree = "<group>";
};
ED128ED01B6C2A7300C4050A /* Result */ = {
isa = PBXGroup;
children = (
ED128ED11B6C2A8B00C4050A /* Result.h */,
ED128ED21B6C2AA200C4050A /* Result.swift */,
);
path = Result;
sourceTree = "<group>";
};
ED128ED61B6C2AF200C4050A /* Box */ = {
isa = PBXGroup;
children = (
ED128ED81B6C2B4400C4050A /* Box.h */,
ED128ED91B6C2B4400C4050A /* Box.swift */,
ED128EDA1B6C2B4400C4050A /* BoxType.swift */,
ED128EDB1B6C2B4400C4050A /* MutableBox.swift */,
);
path = Box;
sourceTree = "<group>";
};
EDEAA0C11B51CEBD00F2FC3F /* Headers */ = {
isa = PBXGroup;
children = (
@ -621,23 +621,23 @@
buildActionMask = 2147483647;
files = (
ED0F23871B87537200AE40CD /* Account.swift in Sources */,
ED128ECA1B6C2A0B00C4050A /* ArgumentParser.swift in Sources */,
ED128EDC1B6C2B4400C4050A /* Box.swift in Sources */,
ED128EDD1B6C2B4400C4050A /* BoxType.swift in Sources */,
ED128ECB1B6C2A0B00C4050A /* Command.swift in Sources */,
6C2E8E6E36A6598C7DA5BAB5 /* ArgumentParser.swift in Sources */,
66110A826B78DD6BAEC50E70 /* Box.swift in Sources */,
F5F01044EC3065C6EBAB95D7 /* BoxType.swift in Sources */,
21EC092422A3EDFE33B153B8 /* Command.swift in Sources */,
ED0F238B1B87569C00AE40CD /* Downloader.swift in Sources */,
ED0F23891B87543D00AE40CD /* DownloadQueueObserver.swift in Sources */,
ED0F238D1B8756E600AE40CD /* Error.swift in Sources */,
ED128ECC1B6C2A0B00C4050A /* Errors.swift in Sources */,
ED128ECD1B6C2A0B00C4050A /* HelpCommand.swift in Sources */,
B80C5DDD38A8F7EB6F320697 /* Errors.swift in Sources */,
5918483F96256CDAC88FF450 /* HelpCommand.swift in Sources */,
ED0F237F1B87522400AE40CD /* Install.swift in Sources */,
ED0F23831B87533A00AE40CD /* ListInstalled.swift in Sources */,
ED0F23851B87536A00AE40CD /* ListUpdates.swift in Sources */,
ED031A7C1B5127C00097692E /* main.swift in Sources */,
ED128EDE1B6C2B4400C4050A /* MutableBox.swift in Sources */,
ED128ECE1B6C2A0B00C4050A /* Option.swift in Sources */,
ED128ED31B6C2AA200C4050A /* Result.swift in Sources */,
ED128ECF1B6C2A0B00C4050A /* Switch.swift in Sources */,
DE39BCA91D1BC3D876711677 /* MutableBox.swift in Sources */,
92828DCD99CED47F54242776 /* Option.swift in Sources */,
1CC607DA6B900AA3FEC3F6D8 /* Result.swift in Sources */,
7858BCFB4D5A4251DE998CE4 /* Switch.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};