From b29ab0d0e7f02a34758989d343deb758e07b6d74 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Sat, 3 Mar 2018 13:15:44 -0600 Subject: [PATCH 01/66] Added awsome badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 2cc6cc5..a65f855 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ # Ether +[![Mentioned in Awesome Vapor](https://awesome.re/mentioned-badge.svg)](https://github.com/Cellane/awesome-vapor) + **Notice!** Ether is currently out of comission because the service that was used to fetch package data from (IBM's package catalog) is [no longer hosted](https://packagecatalog.com/). There is work going on for a [replacement](https://github.com/vapor-community/PackageCatalogAPI), but development is moving slowly. If you wold like to pitch in, pop on over to the [Vapor Slack](https://vapor.team/) and ping me @calebkleveter! From a9735cbe7615600fda1876ac63ad21ea3293383d Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Thu, 29 Mar 2018 17:10:17 -0500 Subject: [PATCH 02/66] Created GitHub target --- Package.swift | 1 + Sources/GitHub/API.swift | 0 2 files changed, 1 insertion(+) create mode 100644 Sources/GitHub/API.swift diff --git a/Package.swift b/Package.swift index c74e697..83a3156 100644 --- a/Package.swift +++ b/Package.swift @@ -10,6 +10,7 @@ let package = Package( .package(url: "https://github.com/vapor/core.git", .exact("2.2.0")) ], targets: [ + .target(name: "GitHub", dependencies: ["Core"]), .target(name: "Helpers", dependencies: ["Core", "JSON"]), .target(name: "Ether", dependencies: ["Helpers", "Console", "JSON"]), .target(name: "Executable", dependencies: ["Ether"]) diff --git a/Sources/GitHub/API.swift b/Sources/GitHub/API.swift new file mode 100644 index 0000000..e69de29 From 4a6d176d1a1b47a35fe87d95ab5f49343a2be34c Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Thu, 29 Mar 2018 17:15:17 -0500 Subject: [PATCH 03/66] Updated all packages --- Package.resolved | 41 ++++++++++++++++------------------------- Package.swift | 9 ++++----- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/Package.resolved b/Package.resolved index 6fc2eaa..b8b30af 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,22 +1,13 @@ { "object": { "pins": [ - { - "package": "Bits", - "repositoryURL": "https://github.com/vapor/bits.git", - "state": { - "branch": null, - "revision": "c32f5e6ae2007dccd21a92b7e33eba842dd80d2f", - "version": "1.1.0" - } - }, { "package": "Console", "repositoryURL": "https://github.com/vapor/console.git", "state": { "branch": null, - "revision": "df9eb9a6afd03851abcb3d8204d04c368729776e", - "version": "2.3.0" + "revision": "273cf2ed1f4daba88a452494c342020171d8c7b8", + "version": "3.0.0-rc.2.2" } }, { @@ -24,35 +15,35 @@ "repositoryURL": "https://github.com/vapor/core.git", "state": { "branch": null, - "revision": "f9f3a585ab0ea5764b46d7a36d9c0d9d508b9c63", - "version": "2.2.0" + "revision": "70719b347f2ee7880776d5b03add924628eac3d2", + "version": "3.0.0-rc.2.5.2" } }, { - "package": "Debugging", - "repositoryURL": "https://github.com/vapor/debugging.git", + "package": "Service", + "repositoryURL": "https://github.com/vapor/service.git", "state": { "branch": null, - "revision": "fc5a27d6eb236141dc24e5f14eedaa2e035ae7b3", - "version": "1.1.1" + "revision": "02205a16a3f4714a08836529f5a868c2ce256719", + "version": "1.0.0-rc.2.2" } }, { - "package": "JSON", - "repositoryURL": "https://github.com/vapor/json.git", + "package": "swift-nio", + "repositoryURL": "https://github.com/apple/swift-nio.git", "state": { "branch": null, - "revision": "735800d8f2e75ebe3be25559eb6a781f4666dcfc", - "version": "2.2.1" + "revision": "a0b7f646fba61402da384b3202f54c27debb5e13", + "version": "1.3.1" } }, { - "package": "Node", - "repositoryURL": "https://github.com/vapor/node.git", + "package": "swift-nio-zlib-support", + "repositoryURL": "https://github.com/apple/swift-nio-zlib-support.git", "state": { "branch": null, - "revision": "c4ff32f07657aec849677e5aecb657bb6c85098d", - "version": "2.1.4" + "revision": "37760e9a52030bb9011972c5213c3350fa9d41fd", + "version": "1.0.0" } } ] diff --git a/Package.swift b/Package.swift index 83a3156..4566bad 100644 --- a/Package.swift +++ b/Package.swift @@ -5,14 +5,13 @@ import PackageDescription let package = Package( name: "Ether", dependencies: [ - .package(url: "https://github.com/vapor/console.git", .exact("2.3.0")), - .package(url: "https://github.com/vapor/json.git", .exact("2.2.1")), - .package(url: "https://github.com/vapor/core.git", .exact("2.2.0")) + .package(url: "https://github.com/vapor/console.git", from: "3.0.0-rc"), + .package(url: "https://github.com/vapor/core.git", from: "3.0.0-rc") ], targets: [ .target(name: "GitHub", dependencies: ["Core"]), - .target(name: "Helpers", dependencies: ["Core", "JSON"]), - .target(name: "Ether", dependencies: ["Helpers", "Console", "JSON"]), + .target(name: "Helpers", dependencies: ["Core"]), + .target(name: "Ether", dependencies: ["Helpers", "Console"]), .target(name: "Executable", dependencies: ["Ether"]) ] ) From c6b7076a6fe1b4b3e418c62e9569ca026ae3d9b2 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Thu, 29 Mar 2018 17:19:31 -0500 Subject: [PATCH 04/66] Commented out code until the project built --- Package.swift | 4 +- Sources/Ether/CleanManifest.swift | 80 ++-- Sources/Ether/Configuration.swift | 332 ++++++------- Sources/Ether/FixInstall.swift | 116 ++--- Sources/Ether/Install.swift | 374 +++++++-------- Sources/Ether/New.swift | 198 ++++---- Sources/Ether/Remove.swift | 184 ++++---- Sources/Ether/Search.swift | 226 ++++----- Sources/Ether/Template.swift | 172 +++---- Sources/Ether/Update.swift | 202 ++++---- Sources/Ether/VersionAll.swift | 106 ++--- Sources/Ether/VersionLatest.swift | 170 +++---- Sources/Ether/VersionSet.swift | 230 ++++----- Sources/Executable/main.swift | 186 ++++---- Sources/Helpers/APIClient.swift | 192 ++++---- Sources/Helpers/JSON.swift | 54 +-- Sources/Helpers/Manifest.swift | 576 +++++++++++------------ Sources/Helpers/PackageJSONFetcher.swift | 150 +++--- 18 files changed, 1776 insertions(+), 1776 deletions(-) diff --git a/Package.swift b/Package.swift index 4566bad..f9732ec 100644 --- a/Package.swift +++ b/Package.swift @@ -10,8 +10,8 @@ let package = Package( ], targets: [ .target(name: "GitHub", dependencies: ["Core"]), - .target(name: "Helpers", dependencies: ["Core"]), + .target(name: "Helpers", dependencies: ["Core", "Console"]), .target(name: "Ether", dependencies: ["Helpers", "Console"]), - .target(name: "Executable", dependencies: ["Ether"]) + .target(name: "Executable", dependencies: ["Ether", "Console"]) ] ) diff --git a/Sources/Ether/CleanManifest.swift b/Sources/Ether/CleanManifest.swift index b749610..5fd92d6 100644 --- a/Sources/Ether/CleanManifest.swift +++ b/Sources/Ether/CleanManifest.swift @@ -1,42 +1,42 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//import Console +//import Helpers // -// 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. - -import Console -import Helpers - -public class CleanManifest: Command { - public let id: String = "clean-manifest" - public let console: ConsoleProtocol - - public let help: [String] = [ - "This command is for internal purposes only" - ] - - public init(console: ConsoleProtocol) { - self.console = console - } - - public func run(arguments: [String]) throws { - console.output("Cleaning Manifest...", style: .info, newLine: true) - try Manifest.current.clean() - } -} +//public class CleanManifest: Command { +// public let id: String = "clean-manifest" +// public let console: ConsoleProtocol +// +// public let help: [String] = [ +// "This command is for internal purposes only" +// ] +// +// public init(console: ConsoleProtocol) { +// self.console = console +// } +// +// public func run(arguments: [String]) throws { +// console.output("Cleaning Manifest...", style: .info, newLine: true) +// try Manifest.current.clean() +// } +//} diff --git a/Sources/Ether/Configuration.swift b/Sources/Ether/Configuration.swift index 7bfa1aa..9e14364 100644 --- a/Sources/Ether/Configuration.swift +++ b/Sources/Ether/Configuration.swift @@ -1,170 +1,170 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//import Foundation +//import Console +//import Helpers +//import JSON // -// 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: +//public class Configuration: Command { +// public let id: String = "config" +// public let configPath = "/Library/Application Support/Ether/config.json" +// +// public let signature: [Argument] = [ +// Value(name: "key", help: [ +// "The configuration JSON key to set" +// ]), +// Value(name: "value", help: [ +// "The new value for the key passed in" +// ]) +// ] +// +// public let help: [String] = [ +// "Configure custom actions to occure when a command is run", +// "Run `config help` to get information on expected data for the command options" +// ] +// +// public let console: ConsoleProtocol +// +// public init(console: ConsoleProtocol) { +// self.console = console +// } +// +// public func run(arguments: [String]) throws { +// let setBar = console.loadingBar(title: "Setting Configuration Key") +// setBar.start() +// +// let fileManager = FileManager.default +// let key = try value("key", from: arguments) +// let val: String +// +// do { +// val = try value("value", from: arguments) +// } catch { +// if key == "help" { printHelp() } +// return +// } +// +// guard let jsonPath = ConfigurationKey.getKey(from: key)?.jsonPath else { +// throw fail(bar: setBar, with: "Unable to get JSON path for specified key") +// } +// guard let configURL = URL(string: "file:\(fileManager.currentDirectoryPath)\(configPath)") else { +// throw fail(bar: setBar, with: "Unable to create path to config file") +// } +// +// let jsonData = try Data(contentsOf: configURL).makeBytes() +// var json = try JSON(bytes: jsonData) +// try self.set(jsonPath, with: val, in: &json) +// +// try Data(bytes: json.makeBytes()).write(to: configURL) +// +// setBar.finish() +// } +// +// fileprivate func printHelp() { +// let help = """ +// Below are the keys, values, and expected types for the configuration JSON. // -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. +// id | key | value-type | description +// ---+----------------+------------+------------------------------------------------------------- +// 0 | use-git | Bool | Wheather to run git commands when a project is written to +// 1 | install-commit | String | The message to use when committing after an installation +// 2 | remove-commit | String | The message to use when committing after a package removal +// 3 | latest-commit | String | The message to use when all packages are updated to their +// | | | latest versions +// 4 | new-commit | String | The message to use when committing a newly generated project // -// 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. - -import Foundation -import Console -import Helpers -import JSON - -public class Configuration: Command { - public let id: String = "config" - public let configPath = "/Library/Application Support/Ether/config.json" - - public let signature: [Argument] = [ - Value(name: "key", help: [ - "The configuration JSON key to set" - ]), - Value(name: "value", help: [ - "The new value for the key passed in" - ]) - ] - - public let help: [String] = [ - "Configure custom actions to occure when a command is run", - "Run `config help` to get information on expected data for the command options" - ] - - public let console: ConsoleProtocol - - public init(console: ConsoleProtocol) { - self.console = console - } - - public func run(arguments: [String]) throws { - let setBar = console.loadingBar(title: "Setting Configuration Key") - setBar.start() - - let fileManager = FileManager.default - let key = try value("key", from: arguments) - let val: String - - do { - val = try value("value", from: arguments) - } catch { - if key == "help" { printHelp() } - return - } - - guard let jsonPath = ConfigurationKey.getKey(from: key)?.jsonPath else { - throw fail(bar: setBar, with: "Unable to get JSON path for specified key") - } - guard let configURL = URL(string: "file:\(fileManager.currentDirectoryPath)\(configPath)") else { - throw fail(bar: setBar, with: "Unable to create path to config file") - } - - let jsonData = try Data(contentsOf: configURL).makeBytes() - var json = try JSON(bytes: jsonData) - try self.set(jsonPath, with: val, in: &json) - - try Data(bytes: json.makeBytes()).write(to: configURL) - - setBar.finish() - } - - fileprivate func printHelp() { - let help = """ - Below are the keys, values, and expected types for the configuration JSON. - - id | key | value-type | description - ---+----------------+------------+------------------------------------------------------------- - 0 | use-git | Bool | Wheather to run git commands when a project is written to - 1 | install-commit | String | The message to use when committing after an installation - 2 | remove-commit | String | The message to use when committing after a package removal - 3 | latest-commit | String | The message to use when all packages are updated to their - | | | latest versions - 4 | new-commit | String | The message to use when committing a newly generated project - - When a commit is made, there are variables that can be replaced for more specific messages. - Below are the variables, their values, and the config ID that they belong to: - - id | var | description - ---+-----+-------------------- - 1 | $0 | The package name - 1 | $1 | The package version - 2 | $0 | The package name - 4 | $0 | The project name - 4 | $1 | The package type - """ - console.output(help, style: .plain, newLine: true) - } - - fileprivate func set(_ path: [String], with val: Any?, `in` json: inout JSON)throws { - var jsons: [(key: String, json: JSON)] = [] - var top: JSON = JSON() - var sub: JSON = JSON() - - if path.count < 1 { return } - for key in path { - try jsons.append((key: key, json: json.get(key))) - } - if jsons.count == 0 { return } - else if jsons.count == 1 { - top = jsons[0].json - try top.set(path[0], val) - json = top - return - } - - for index in Array(0...jsons.count-1).reversed() { - sub = jsons[index].json - - if index == jsons.count-1 { - // Force-unwrapping always succedes because we tested for the path count earlier. - try sub.set(path.last!, val) - } else if index > 0 { - top = jsons[index].json - try top.set(jsons[index].key, sub) - } else { - json = top - } - } - } -} - -fileprivate enum ConfigurationKey { - case useGit - case gitInstallMessage - case gitRemoveMessage - case gitLatestMessage - case gitNewMessage - - var jsonPath: [String] { - switch self { - case .useGit: return ["git", "use"] - case .gitInstallMessage: return ["git", "commit-messages", "install"] - case .gitRemoveMessage: return ["git", "commit-message", "remove"] - case .gitLatestMessage: return ["git", "commit-message", "version-latest"] - case .gitNewMessage: return ["git", "commit-message", "new"] - } - } - - static func getKey(from string: String) -> ConfigurationKey? { - switch string.lowercased() { - case "use-git": return .useGit - case "install-commit": return .gitInstallMessage - case "remove-commit": return .gitRemoveMessage - case "latest-commit": return .gitLatestMessage - case "new-commit": return .gitNewMessage - default: return nil - } - } -} +// When a commit is made, there are variables that can be replaced for more specific messages. +// Below are the variables, their values, and the config ID that they belong to: +// +// id | var | description +// ---+-----+-------------------- +// 1 | $0 | The package name +// 1 | $1 | The package version +// 2 | $0 | The package name +// 4 | $0 | The project name +// 4 | $1 | The package type +// """ +// console.output(help, style: .plain, newLine: true) +// } +// +// fileprivate func set(_ path: [String], with val: Any?, `in` json: inout JSON)throws { +// var jsons: [(key: String, json: JSON)] = [] +// var top: JSON = JSON() +// var sub: JSON = JSON() +// +// if path.count < 1 { return } +// for key in path { +// try jsons.append((key: key, json: json.get(key))) +// } +// if jsons.count == 0 { return } +// else if jsons.count == 1 { +// top = jsons[0].json +// try top.set(path[0], val) +// json = top +// return +// } +// +// for index in Array(0...jsons.count-1).reversed() { +// sub = jsons[index].json +// +// if index == jsons.count-1 { +// // Force-unwrapping always succedes because we tested for the path count earlier. +// try sub.set(path.last!, val) +// } else if index > 0 { +// top = jsons[index].json +// try top.set(jsons[index].key, sub) +// } else { +// json = top +// } +// } +// } +//} +// +//fileprivate enum ConfigurationKey { +// case useGit +// case gitInstallMessage +// case gitRemoveMessage +// case gitLatestMessage +// case gitNewMessage +// +// var jsonPath: [String] { +// switch self { +// case .useGit: return ["git", "use"] +// case .gitInstallMessage: return ["git", "commit-messages", "install"] +// case .gitRemoveMessage: return ["git", "commit-message", "remove"] +// case .gitLatestMessage: return ["git", "commit-message", "version-latest"] +// case .gitNewMessage: return ["git", "commit-message", "new"] +// } +// } +// +// static func getKey(from string: String) -> ConfigurationKey? { +// switch string.lowercased() { +// case "use-git": return .useGit +// case "install-commit": return .gitInstallMessage +// case "remove-commit": return .gitRemoveMessage +// case "latest-commit": return .gitLatestMessage +// case "new-commit": return .gitNewMessage +// default: return nil +// } +// } +//} diff --git a/Sources/Ether/FixInstall.swift b/Sources/Ether/FixInstall.swift index beec04a..f7be714 100644 --- a/Sources/Ether/FixInstall.swift +++ b/Sources/Ether/FixInstall.swift @@ -1,60 +1,60 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//import Console // -// 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. - -import Console - -public class FixInstall: Command { - public let id: String = "fix-install" - - public let signature: [Argument] = [ - Option(name: "no-build", help: [ - "Skips the rebuilding proccess after clearing the project cache" - ]) - ] - - public var help: [String] = [ - "Fixes fetching errors that occur during package install" - ] - - public let console: ConsoleProtocol - - public init(console: ConsoleProtocol) { - self.console = console - } - - public func run(arguments: [String]) throws { - let fixBar = console.loadingBar(title: "Fixing Installation") - - console.output("This may take some time...", style: .info, newLine: true) - fixBar.start() - - _ = try console.backgroundExecute(program: "rm", arguments: ["-rf", ".build"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) - - if arguments.option("no-build") == nil { - _ = try console.backgroundExecute(program: "swift", arguments: ["build"]) - } - - fixBar.finish() - } -} +//public class FixInstall: Command { +// public let id: String = "fix-install" +// +// public let signature: [Argument] = [ +// Option(name: "no-build", help: [ +// "Skips the rebuilding proccess after clearing the project cache" +// ]) +// ] +// +// public var help: [String] = [ +// "Fixes fetching errors that occur during package install" +// ] +// +// public let console: ConsoleProtocol +// +// public init(console: ConsoleProtocol) { +// self.console = console +// } +// +// public func run(arguments: [String]) throws { +// let fixBar = console.loadingBar(title: "Fixing Installation") +// +// console.output("This may take some time...", style: .info, newLine: true) +// fixBar.start() +// +// _ = try console.backgroundExecute(program: "rm", arguments: ["-rf", ".build"]) +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) +// +// if arguments.option("no-build") == nil { +// _ = try console.backgroundExecute(program: "swift", arguments: ["build"]) +// } +// +// fixBar.finish() +// } +//} diff --git a/Sources/Ether/Install.swift b/Sources/Ether/Install.swift index 89d7eaf..e35b6ec 100644 --- a/Sources/Ether/Install.swift +++ b/Sources/Ether/Install.swift @@ -1,191 +1,191 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. +// +//import Helpers +//import Console +//import Foundation +//import Core +// +//public final class Install: Command { +// public let id = "install" +// public let baseURL = "https://packagecatalog.com/data/package/" +// +// public let signature: [Argument] = [ +// Value(name: "name", help: [ +// "The name of the package that will be installed" +// ]), +// Option(name: "url", short: "u", help: [ +// "The URL for the package" +// ]), +// Option(name: "version", short: "v", help: [ +// "The desired version for the package", +// "This defaults to the latest version" +// ]), +// Option(name: "xcode", short: "x", help: [ +// "Regenerate the Xcode project after the install is complete" +// ]) +// ] +// +// public var help: [String] = [ +// "Installs a package into the current project" +// ] +// +// public let console: ConsoleProtocol +// public let client = PackageJSONFetcher() +// +// public init(console: ConsoleProtocol) { +// self.console = console +// } +// +// public func run(arguments: [String]) throws { +// console.output("Reading Package Targets...", style: .info, newLine: true) +// +// let fileManager = FileManager.default +// let name = try value("name", from: arguments) +// let installBar = console.loadingBar(title: "Installing Dependency") +// +// // Get package manifest and JSON data +// guard let manifestURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift") else { +// throw EtherError.fail("Bad path to package manifest. Make sure you are in the project root.") +// } +// guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.resolved") else { +// throw EtherError.fail("Bad path to package data. Make sure you are in the project root.") +// } +// let packageManifest = try String(contentsOf: manifestURL) +// let mutablePackageManifest = NSMutableString(string: packageManifest) +// let pinsCount: Int +// +// do { +// let packageData = try Data(contentsOf: resolvedURL).json() +// guard let object = packageData?["object"] as? APIJSON, +// let pins = object["pins"] as? [APIJSON] else { return } +// pinsCount = pins.count +// } catch { +// pinsCount = 0 +// } +// +// // Get the names of the targets to add the dependency to +// let targets = try Manifest.current.getTargets() +// let useTargets: [String] = inquireFor(targets: targets) +// +// installBar.start() +// +// let packageInstenceRegex = try NSRegularExpression(pattern: "(\\.package([\\w\\s\\d\\,\\:\\(\\)\\@\\-\\\"\\/\\.])+\\)),?(?:\\R?)", options: .anchorsMatchLines) +// let dependenciesRegex = try NSRegularExpression(pattern: "products: *\\[(?s:.*?)\\],\\s*dependencies: *\\[", options: .anchorsMatchLines) +// +// // Get the data for the package to install +// let newPackageData = try Manifest.current.getPackageData(for: name) +// let packageVersion = arguments.options["version"] ?? newPackageData.version +// let packageUrl = arguments.options["url"] ?? newPackageData.url +// +// let packageInstance = "$1,\n .package(url: \"\(packageUrl)\", .exact(\"\(packageVersion)\"))\n" +// let depPackageInstance = "$0\n .package(url: \"\(packageUrl)\", .exact(\"\(packageVersion)\"))" +// +// // Add the new package instance to the Package dependencies array. +// if packageInstenceRegex.matches(in: packageManifest, options: [], range: NSMakeRange(0, packageManifest.utf8.count)).count > 0 { +// packageInstenceRegex.replaceMatches(in: mutablePackageManifest, options: [], range: NSMakeRange(0, mutablePackageManifest.length), withTemplate: packageInstance) +// } else { +// dependenciesRegex.replaceMatches(in: mutablePackageManifest, options: [], range: NSMakeRange(0, mutablePackageManifest.length), withTemplate: depPackageInstance) +// } +// +// // Write the new package manifest to the Package.swift file +// try String(mutablePackageManifest).data(using: .utf8)?.write(to: URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift")!) +// +// // Update the packages. +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) +// +// // Get the new package name and add it to the previously accepted targets. +// let dependencyName = try Manifest.current.getPackageName(for: newPackageData.url) +// for target in useTargets { +// try mutablePackageManifest.addDependency(dependencyName, to: target) +// } +// +// // Write the Package.swift file again +// try String(mutablePackageManifest).data(using: .utf8)?.write(to: URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift")!) +// +// // Calculate the number of package that where installed and output it. +// let packageData = try Data(contentsOf: resolvedURL).json() +// guard let object = packageData?["object"] as? APIJSON, +// let pins = object["pins"] as? [APIJSON] else { return } +// +// let newPackageCount = pins.count - pinsCount +// +// installBar.finish() +// +// if let _ = arguments.options["xcode"] { +// let xcodeBar = console.loadingBar(title: "Generating Xcode Project") +// xcodeBar.start() +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "generate-xcodeproj"]) +// xcodeBar.finish() +// try console.execute(program: "/bin/sh", arguments: ["-c", "open *.xcodeproj"], input: nil, output: nil, error: nil) +// } +// +// console.output("📦 \(newPackageCount) packages installed", style: .plain, newLine: true) +// } +// +// /// Asks the user if they want to add a dependency to the targets in the package manifest. +// /// +// /// - Parameter targets: The names of the targets available. +// /// - Returns: The names of the targets that where accepted. +// fileprivate func inquireFor(targets: [String]) -> [String] { +// var acceptedTargets: [String] = [] +// var index = 0 +// +// if targets.count > 1 { +// targetFetch: while index < targets.count { +// let target = targets[index] +// let response = console.ask("Would you like to add the package to the target '\(target)'? (y,n,q,?)") +// +// switch response { +// case "y": +// acceptedTargets.append(target) +// index += 1 +// case "n": +// index += 1 +// case "q": +// break targetFetch +// default: console.output(""" +// y: Add the package as a dependency to the target. +// n: Do not add the package as a dependency to the target. +// q: Do not add the package as a dependency to the current target or any of the following targets. +// ?: Output this message. +// """, style: .info, newLine: true) +// } +// } +// } else { +// acceptedTargets.append(targets[0]) +// } +// +// return acceptedTargets +// } +//} +// +// +// +// +// +// // -// Copyright (c) 2017 Caleb Kleveter // -// 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. - -import Helpers -import Console -import Foundation -import Core - -public final class Install: Command { - public let id = "install" - public let baseURL = "https://packagecatalog.com/data/package/" - - public let signature: [Argument] = [ - Value(name: "name", help: [ - "The name of the package that will be installed" - ]), - Option(name: "url", short: "u", help: [ - "The URL for the package" - ]), - Option(name: "version", short: "v", help: [ - "The desired version for the package", - "This defaults to the latest version" - ]), - Option(name: "xcode", short: "x", help: [ - "Regenerate the Xcode project after the install is complete" - ]) - ] - - public var help: [String] = [ - "Installs a package into the current project" - ] - - public let console: ConsoleProtocol - public let client = PackageJSONFetcher() - - public init(console: ConsoleProtocol) { - self.console = console - } - - public func run(arguments: [String]) throws { - console.output("Reading Package Targets...", style: .info, newLine: true) - - let fileManager = FileManager.default - let name = try value("name", from: arguments) - let installBar = console.loadingBar(title: "Installing Dependency") - - // Get package manifest and JSON data - guard let manifestURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift") else { - throw EtherError.fail("Bad path to package manifest. Make sure you are in the project root.") - } - guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.resolved") else { - throw EtherError.fail("Bad path to package data. Make sure you are in the project root.") - } - let packageManifest = try String(contentsOf: manifestURL) - let mutablePackageManifest = NSMutableString(string: packageManifest) - let pinsCount: Int - - do { - let packageData = try Data(contentsOf: resolvedURL).json() - guard let object = packageData?["object"] as? APIJSON, - let pins = object["pins"] as? [APIJSON] else { return } - pinsCount = pins.count - } catch { - pinsCount = 0 - } - - // Get the names of the targets to add the dependency to - let targets = try Manifest.current.getTargets() - let useTargets: [String] = inquireFor(targets: targets) - - installBar.start() - - let packageInstenceRegex = try NSRegularExpression(pattern: "(\\.package([\\w\\s\\d\\,\\:\\(\\)\\@\\-\\\"\\/\\.])+\\)),?(?:\\R?)", options: .anchorsMatchLines) - let dependenciesRegex = try NSRegularExpression(pattern: "products: *\\[(?s:.*?)\\],\\s*dependencies: *\\[", options: .anchorsMatchLines) - - // Get the data for the package to install - let newPackageData = try Manifest.current.getPackageData(for: name) - let packageVersion = arguments.options["version"] ?? newPackageData.version - let packageUrl = arguments.options["url"] ?? newPackageData.url - - let packageInstance = "$1,\n .package(url: \"\(packageUrl)\", .exact(\"\(packageVersion)\"))\n" - let depPackageInstance = "$0\n .package(url: \"\(packageUrl)\", .exact(\"\(packageVersion)\"))" - - // Add the new package instance to the Package dependencies array. - if packageInstenceRegex.matches(in: packageManifest, options: [], range: NSMakeRange(0, packageManifest.utf8.count)).count > 0 { - packageInstenceRegex.replaceMatches(in: mutablePackageManifest, options: [], range: NSMakeRange(0, mutablePackageManifest.length), withTemplate: packageInstance) - } else { - dependenciesRegex.replaceMatches(in: mutablePackageManifest, options: [], range: NSMakeRange(0, mutablePackageManifest.length), withTemplate: depPackageInstance) - } - - // Write the new package manifest to the Package.swift file - try String(mutablePackageManifest).data(using: .utf8)?.write(to: URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift")!) - - // Update the packages. - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) - - // Get the new package name and add it to the previously accepted targets. - let dependencyName = try Manifest.current.getPackageName(for: newPackageData.url) - for target in useTargets { - try mutablePackageManifest.addDependency(dependencyName, to: target) - } - - // Write the Package.swift file again - try String(mutablePackageManifest).data(using: .utf8)?.write(to: URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift")!) - - // Calculate the number of package that where installed and output it. - let packageData = try Data(contentsOf: resolvedURL).json() - guard let object = packageData?["object"] as? APIJSON, - let pins = object["pins"] as? [APIJSON] else { return } - - let newPackageCount = pins.count - pinsCount - - installBar.finish() - - if let _ = arguments.options["xcode"] { - let xcodeBar = console.loadingBar(title: "Generating Xcode Project") - xcodeBar.start() - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "generate-xcodeproj"]) - xcodeBar.finish() - try console.execute(program: "/bin/sh", arguments: ["-c", "open *.xcodeproj"], input: nil, output: nil, error: nil) - } - - console.output("📦 \(newPackageCount) packages installed", style: .plain, newLine: true) - } - - /// Asks the user if they want to add a dependency to the targets in the package manifest. - /// - /// - Parameter targets: The names of the targets available. - /// - Returns: The names of the targets that where accepted. - fileprivate func inquireFor(targets: [String]) -> [String] { - var acceptedTargets: [String] = [] - var index = 0 - - if targets.count > 1 { - targetFetch: while index < targets.count { - let target = targets[index] - let response = console.ask("Would you like to add the package to the target '\(target)'? (y,n,q,?)") - - switch response { - case "y": - acceptedTargets.append(target) - index += 1 - case "n": - index += 1 - case "q": - break targetFetch - default: console.output(""" - y: Add the package as a dependency to the target. - n: Do not add the package as a dependency to the target. - q: Do not add the package as a dependency to the current target or any of the following targets. - ?: Output this message. - """, style: .info, newLine: true) - } - } - } else { - acceptedTargets.append(targets[0]) - } - - return acceptedTargets - } -} - - - - - - - - - - diff --git a/Sources/Ether/New.swift b/Sources/Ether/New.swift index 8fa43b0..4e98ca2 100644 --- a/Sources/Ether/New.swift +++ b/Sources/Ether/New.swift @@ -1,101 +1,101 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//import Console +//import Helpers +//import Foundation // -// 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. - -import Console -import Helpers -import Foundation - -public final class New: Command { - public let id = "new" - - public let help: [String] = [ - "Create new projects" - ] - - public let signature: [Argument] = [ - Value(name: "name", help: [ - "The name of the new project" - ]), - Option(name: "executable", short: "e", help: [ - "Creates an executable SPM project" - ]), - Option(name: "package", short: "p", help: [ - "Creates an SPM package" - ]), - Option(name: "template", help: [ - "Creates a project starting with a previously saved template" - ]) - ] - - public let console: ConsoleProtocol - - public init(console: ConsoleProtocol) { - self.console = console - } - - public func run(arguments: [String]) throws { - let newProjectBar = console.loadingBar(title: "Generating Project") - newProjectBar.start() - - let executable = try newExecutable(arguments: arguments) - let template = try newFromTemplate(arguments: arguments) - if !executable && !template { - try newPackage(arguments: arguments) - } - - newProjectBar.finish() - } - - func newExecutable(arguments: [String]) throws -> Bool { - if let _ = arguments.option("executable") { - let name = try value("name", from: arguments) - let script = "mkdir \(name); cd \(name); swift package init --type=executable; ether clean-manifest" - _ = try console.backgroundExecute(program: "bash", arguments: ["-c", script]) - return true - } - return false - } - - func newFromTemplate(arguments: [String]) throws -> Bool { - if let template = arguments.option("template") { - let name = try value("name", from: arguments) - let manager = FileManager.default - - if #available(OSX 10.12, *) { - let directoryName = manager.homeDirectoryForCurrentUser.absoluteString - let templatePath = String("\(directoryName)Library/Application Support/Ether/Templates/\(template)".dropFirst(7)) - let current = manager.currentDirectoryPath - shell(command: "/bin/cp", "-a", "\(templatePath)", "\(current)/\(name)") - } else { - throw EtherError.fail("This command is not supported in macOS versions older then 10.12") - } - return true - } - return false - } - - func newPackage(arguments: [String]) throws { - let name = try value("name", from: arguments) - let script = "mkdir \(name); cd \(name); swift package init; ether clean-manifest" - _ = try console.backgroundExecute(program: "bash", arguments: ["-c", script]) - } -} +//public final class New: Command { +// public let id = "new" +// +// public let help: [String] = [ +// "Create new projects" +// ] +// +// public let signature: [Argument] = [ +// Value(name: "name", help: [ +// "The name of the new project" +// ]), +// Option(name: "executable", short: "e", help: [ +// "Creates an executable SPM project" +// ]), +// Option(name: "package", short: "p", help: [ +// "Creates an SPM package" +// ]), +// Option(name: "template", help: [ +// "Creates a project starting with a previously saved template" +// ]) +// ] +// +// public let console: ConsoleProtocol +// +// public init(console: ConsoleProtocol) { +// self.console = console +// } +// +// public func run(arguments: [String]) throws { +// let newProjectBar = console.loadingBar(title: "Generating Project") +// newProjectBar.start() +// +// let executable = try newExecutable(arguments: arguments) +// let template = try newFromTemplate(arguments: arguments) +// if !executable && !template { +// try newPackage(arguments: arguments) +// } +// +// newProjectBar.finish() +// } +// +// func newExecutable(arguments: [String]) throws -> Bool { +// if let _ = arguments.option("executable") { +// let name = try value("name", from: arguments) +// let script = "mkdir \(name); cd \(name); swift package init --type=executable; ether clean-manifest" +// _ = try console.backgroundExecute(program: "bash", arguments: ["-c", script]) +// return true +// } +// return false +// } +// +// func newFromTemplate(arguments: [String]) throws -> Bool { +// if let template = arguments.option("template") { +// let name = try value("name", from: arguments) +// let manager = FileManager.default +// +// if #available(OSX 10.12, *) { +// let directoryName = manager.homeDirectoryForCurrentUser.absoluteString +// let templatePath = String("\(directoryName)Library/Application Support/Ether/Templates/\(template)".dropFirst(7)) +// let current = manager.currentDirectoryPath +// shell(command: "/bin/cp", "-a", "\(templatePath)", "\(current)/\(name)") +// } else { +// throw EtherError.fail("This command is not supported in macOS versions older then 10.12") +// } +// return true +// } +// return false +// } +// +// func newPackage(arguments: [String]) throws { +// let name = try value("name", from: arguments) +// let script = "mkdir \(name); cd \(name); swift package init; ether clean-manifest" +// _ = try console.backgroundExecute(program: "bash", arguments: ["-c", script]) +// } +//} diff --git a/Sources/Ether/Remove.swift b/Sources/Ether/Remove.swift index c4eaa33..454b564 100644 --- a/Sources/Ether/Remove.swift +++ b/Sources/Ether/Remove.swift @@ -1,94 +1,94 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//import Helpers +//import Console +//import Foundation // -// 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. - -import Helpers -import Console -import Foundation - -public final class Remove: Command { - public let id = "remove" - - public var help: [String] = [ - "Removes and uninstalls a package" - ] - - public var signature: [Argument] = [ - Value(name: "name", help: [ - "The name of the package that will be removed" - ]), - Option(name: "xcode", short: "x", help: [ - "Regenerate the Xcode project after removing the package" - ]) - ] - - public let console: ConsoleProtocol - - public init(console: ConsoleProtocol) { - self.console = console - } - - public func run(arguments: [String]) throws { - let removingProgressBar = console.loadingBar(title: "Removing Dependency") - removingProgressBar.start() - - let manager = FileManager.default - let name = try value("name", from: arguments) - let url = try Manifest.current.getPackageUrl(for: name) - - let regex = try NSRegularExpression(pattern: "(\\,?\\n *\\.package\\(url: *\"\(url)\", *)(.*?)(?=,?\n)", options: .caseInsensitive) - let oldPins = try Manifest.current.getPins() - - let packageString = try Manifest.current.get() - let mutableString = NSMutableString(string: packageString) - - if regex.matches(in: packageString, options: [], range: NSMakeRange(0, packageString.utf8.count)).count == 0 { - throw fail(bar: removingProgressBar, with: "No packages matching the name passed in where found") - } - - regex.replaceMatches(in: mutableString, options: [], range: NSMakeRange(0, mutableString.length), withTemplate: "") - try mutableString.removeDependency(name) - - do { - try String(mutableString).data(using: .utf8)?.write(to: URL(string: "file:\(manager.currentDirectoryPath)/Package.swift")!) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) - } catch let error { - removingProgressBar.fail() - throw error - } - - let pins = try Manifest.current.getPins() - let pinsCount = oldPins.count - pins.count - - removingProgressBar.finish() - - if let _ = arguments.options["xcode"] { - let xcodeBar = console.loadingBar(title: "Generating Xcode Project") - xcodeBar.start() - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "generate-xcodeproj"]) - xcodeBar.finish() - try console.execute(program: "/bin/sh", arguments: ["-c", "open *.xcodeproj"], input: nil, output: nil, error: nil) - } - - console.output("📦 \(pinsCount) packages removed", style: .custom(.white), newLine: true) - } -} +//public final class Remove: Command { +// public let id = "remove" +// +// public var help: [String] = [ +// "Removes and uninstalls a package" +// ] +// +// public var signature: [Argument] = [ +// Value(name: "name", help: [ +// "The name of the package that will be removed" +// ]), +// Option(name: "xcode", short: "x", help: [ +// "Regenerate the Xcode project after removing the package" +// ]) +// ] +// +// public let console: ConsoleProtocol +// +// public init(console: ConsoleProtocol) { +// self.console = console +// } +// +// public func run(arguments: [String]) throws { +// let removingProgressBar = console.loadingBar(title: "Removing Dependency") +// removingProgressBar.start() +// +// let manager = FileManager.default +// let name = try value("name", from: arguments) +// let url = try Manifest.current.getPackageUrl(for: name) +// +// let regex = try NSRegularExpression(pattern: "(\\,?\\n *\\.package\\(url: *\"\(url)\", *)(.*?)(?=,?\n)", options: .caseInsensitive) +// let oldPins = try Manifest.current.getPins() +// +// let packageString = try Manifest.current.get() +// let mutableString = NSMutableString(string: packageString) +// +// if regex.matches(in: packageString, options: [], range: NSMakeRange(0, packageString.utf8.count)).count == 0 { +// throw fail(bar: removingProgressBar, with: "No packages matching the name passed in where found") +// } +// +// regex.replaceMatches(in: mutableString, options: [], range: NSMakeRange(0, mutableString.length), withTemplate: "") +// try mutableString.removeDependency(name) +// +// do { +// try String(mutableString).data(using: .utf8)?.write(to: URL(string: "file:\(manager.currentDirectoryPath)/Package.swift")!) +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) +// } catch let error { +// removingProgressBar.fail() +// throw error +// } +// +// let pins = try Manifest.current.getPins() +// let pinsCount = oldPins.count - pins.count +// +// removingProgressBar.finish() +// +// if let _ = arguments.options["xcode"] { +// let xcodeBar = console.loadingBar(title: "Generating Xcode Project") +// xcodeBar.start() +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "generate-xcodeproj"]) +// xcodeBar.finish() +// try console.execute(program: "/bin/sh", arguments: ["-c", "open *.xcodeproj"], input: nil, output: nil, error: nil) +// } +// +// console.output("📦 \(pinsCount) packages removed", style: .custom(.white), newLine: true) +// } +//} diff --git a/Sources/Ether/Search.swift b/Sources/Ether/Search.swift index 9c9b48c..7967bd6 100644 --- a/Sources/Ether/Search.swift +++ b/Sources/Ether/Search.swift @@ -1,116 +1,116 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//import Helpers +//import Console +//import Foundation +//import Core // -// 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: +//public final class Search: Command { +// public let id = "search" +// +// public let baseURL = "https://packagecatalog.com/api/search/" +// public let sort = "chart" +// public let results = "items" +// +// public var help: [String] = [ +// "Searches for availible packages." +// ] +// +// public var signature: [Argument] = [ +// Value(name: "name", help: [ +// "The name of the package to search for." +// ]), +// Option(name: "max-results", help: [ +// "The maximum number of results that will be returned.", +// "This defaults to 20." +// ]), +// Option(name: "sort", help: [ +// "The sorting method to use:", +// "moststarred (Most Starred)", +// "leaststarred (Least Starred)", +// "mostrecent (Most Recent)", +// "leastrecent (Least Recent)", +// "The default value is moststarred." +// ]) +// ] +// +// public let console: ConsoleProtocol +// public let client = PackageJSONFetcher() +// +// public init(console: ConsoleProtocol) { +// self.console = console +// } +// +// public func run(arguments: [String]) throws { +// let searchingBar = console.loadingBar(title: "Searching") +// searchingBar.start() +// +// let name = try value("name", from: arguments) +// let maxResults = arguments.options["max-results"] ?? "20" +// let sortMethod = arguments.options["sort"] ?? "moststarred" +// +// func fail(_ message: String) -> Error { +// searchingBar.fail() +// return EtherError.fail(message) +// } +// +// var totalResults: Int? +// var maxedResults: Bool? +// var packages: [(name: String?, description: String?)]? +// +// let json = try self.client.get(from: self.baseURL + name, withParameters: [self.sort: sortMethod, self.results: maxResults]) +// +// guard let data = json["data"] as? APIJSON else { throw fail("Bad JSON key") } +// guard let hits = data["hits"] as? APIJSON else { throw fail("Bad JSON key") } +// guard let results = hits["hits"] as? [APIJSON] else { throw fail("Bad JSON key") } +// +// packages = try results.map { (result) -> (name: String?, description: String?) in +// guard let source = result["_source"] as? APIJSON else { throw fail("Bad JSON key") } +// return (name: source["package_full_name"] as? String, description: source["description"] as? String) +// } +// +// maxedResults = Int(String(describing: hits["total"] ?? 0 as AnyObject))! > Int(maxResults)! +// totalResults = Int(String(describing: hits["total"] ?? 0 as AnyObject)) // -// 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. - -import Helpers -import Console -import Foundation -import Core - -public final class Search: Command { - public let id = "search" - - public let baseURL = "https://packagecatalog.com/api/search/" - public let sort = "chart" - public let results = "items" - - public var help: [String] = [ - "Searches for availible packages." - ] - - public var signature: [Argument] = [ - Value(name: "name", help: [ - "The name of the package to search for." - ]), - Option(name: "max-results", help: [ - "The maximum number of results that will be returned.", - "This defaults to 20." - ]), - Option(name: "sort", help: [ - "The sorting method to use:", - "moststarred (Most Starred)", - "leaststarred (Least Starred)", - "mostrecent (Most Recent)", - "leastrecent (Least Recent)", - "The default value is moststarred." - ]) - ] - - public let console: ConsoleProtocol - public let client = PackageJSONFetcher() - - public init(console: ConsoleProtocol) { - self.console = console - } - - public func run(arguments: [String]) throws { - let searchingBar = console.loadingBar(title: "Searching") - searchingBar.start() - - let name = try value("name", from: arguments) - let maxResults = arguments.options["max-results"] ?? "20" - let sortMethod = arguments.options["sort"] ?? "moststarred" - - func fail(_ message: String) -> Error { - searchingBar.fail() - return EtherError.fail(message) - } - - var totalResults: Int? - var maxedResults: Bool? - var packages: [(name: String?, description: String?)]? - - let json = try self.client.get(from: self.baseURL + name, withParameters: [self.sort: sortMethod, self.results: maxResults]) - - guard let data = json["data"] as? APIJSON else { throw fail("Bad JSON key") } - guard let hits = data["hits"] as? APIJSON else { throw fail("Bad JSON key") } - guard let results = hits["hits"] as? [APIJSON] else { throw fail("Bad JSON key") } - - packages = try results.map { (result) -> (name: String?, description: String?) in - guard let source = result["_source"] as? APIJSON else { throw fail("Bad JSON key") } - return (name: source["package_full_name"] as? String, description: source["description"] as? String) - } - - maxedResults = Int(String(describing: hits["total"] ?? 0 as AnyObject))! > Int(maxResults)! - totalResults = Int(String(describing: hits["total"] ?? 0 as AnyObject)) - - searchingBar.finish() - - self.console.output("Total results: \(totalResults ?? 0)", style: .info, newLine: true) - - if let maxedResults = maxedResults { - if maxedResults { - self.console.output("Not all results are shown.", style: .info, newLine: true) - } - } - if (totalResults ?? 0) > 0 { - console.output(String(repeating: "-", count: console.size.width), style: .info, newLine: true) - console.output("", style: .info, newLine: true) - } - if let packages = packages { - for package in packages { - self.console.output("\(package.name ?? "N/A"): ", style: .custom(.green), newLine: false) - self.console.output("\(package.description ?? "N/A")", style: .custom(.white), newLine: true) - console.output("", style: .info, newLine: true) - } - } - } -} +// searchingBar.finish() +// +// self.console.output("Total results: \(totalResults ?? 0)", style: .info, newLine: true) +// +// if let maxedResults = maxedResults { +// if maxedResults { +// self.console.output("Not all results are shown.", style: .info, newLine: true) +// } +// } +// if (totalResults ?? 0) > 0 { +// console.output(String(repeating: "-", count: console.size.width), style: .info, newLine: true) +// console.output("", style: .info, newLine: true) +// } +// if let packages = packages { +// for package in packages { +// self.console.output("\(package.name ?? "N/A"): ", style: .custom(.green), newLine: false) +// self.console.output("\(package.description ?? "N/A")", style: .custom(.white), newLine: true) +// console.output("", style: .info, newLine: true) +// } +// } +// } +//} diff --git a/Sources/Ether/Template.swift b/Sources/Ether/Template.swift index 8eacd15..9f52167 100644 --- a/Sources/Ether/Template.swift +++ b/Sources/Ether/Template.swift @@ -1,89 +1,89 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//// Path: ~/Library/Application\ Support/Ether // -// 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: +//import Console +//import Foundation +//import Core +//import Helpers // -// 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. - -// Path: ~/Library/Application\ Support/Ether - -import Console -import Foundation -import Core -import Helpers - -final public class Template: Command { - public let id = "template" - - public let signature: [Argument] = [ - Value(name: "template-name", help: [ - "The name used to identify the template" - ]), - Option(name: "github", help: [ - "Creates a GitHub repo and pushes the template to it (Un-implimented)" - ]), - Option(name: "remove", short: "r", help: [ - "Deletes the template" - ]) - ] - - public let help: [String] = [ - "Creates and stores a template for use as the starting point of a project." - ] - - public let console: ConsoleProtocol - - public init(console: ConsoleProtocol) { - self.console = console - } - - public func run(arguments: [String]) throws { - let name = try value("template-name", from: arguments) - let useGitHub = arguments.option("github") != nil ? true : false - let removeTemplate = arguments.option("remove") != nil ? true : false - let manager = FileManager.default - let loadingBarTitle = removeTemplate ? "Deleting Template" : "Saving Template" - - let savingBar = console.loadingBar(title: loadingBarTitle) - savingBar.start() - - if #available(OSX 10.12, *) { - var isDir : ObjCBool = true - let directoryName = manager.homeDirectoryForCurrentUser.absoluteString - let defaultPath = String("\(directoryName)Library/Application Support/Ether/Templates".dropFirst(7)) - let directoryExists = manager.fileExists(atPath: "\(defaultPath)/\(name)", isDirectory: &isDir) - - if removeTemplate { - if !directoryExists { throw fail(bar: savingBar, with: "No template with that name exists") } - shell(command: "/bin/rm", "-rf", "\(defaultPath)/\(name)") - } else { - if directoryExists { throw fail(bar: savingBar, with: "A template with that name already exists") } - let current = manager.currentDirectoryPath + "/." - shell(command: "/bin/cp", "-a", "\(current)", "\(defaultPath)/\(name)") - } - } else { - throw fail(bar: savingBar, with: "This command is not supported in macOS versions older then 10.12") - } - savingBar.finish() - - if useGitHub { - console.output("The GitHub flag is currently not implimented", style: .warning, newLine: true) - } - - } -} +//final public class Template: Command { +// public let id = "template" +// +// public let signature: [Argument] = [ +// Value(name: "template-name", help: [ +// "The name used to identify the template" +// ]), +// Option(name: "github", help: [ +// "Creates a GitHub repo and pushes the template to it (Un-implimented)" +// ]), +// Option(name: "remove", short: "r", help: [ +// "Deletes the template" +// ]) +// ] +// +// public let help: [String] = [ +// "Creates and stores a template for use as the starting point of a project." +// ] +// +// public let console: ConsoleProtocol +// +// public init(console: ConsoleProtocol) { +// self.console = console +// } +// +// public func run(arguments: [String]) throws { +// let name = try value("template-name", from: arguments) +// let useGitHub = arguments.option("github") != nil ? true : false +// let removeTemplate = arguments.option("remove") != nil ? true : false +// let manager = FileManager.default +// let loadingBarTitle = removeTemplate ? "Deleting Template" : "Saving Template" +// +// let savingBar = console.loadingBar(title: loadingBarTitle) +// savingBar.start() +// +// if #available(OSX 10.12, *) { +// var isDir : ObjCBool = true +// let directoryName = manager.homeDirectoryForCurrentUser.absoluteString +// let defaultPath = String("\(directoryName)Library/Application Support/Ether/Templates".dropFirst(7)) +// let directoryExists = manager.fileExists(atPath: "\(defaultPath)/\(name)", isDirectory: &isDir) +// +// if removeTemplate { +// if !directoryExists { throw fail(bar: savingBar, with: "No template with that name exists") } +// shell(command: "/bin/rm", "-rf", "\(defaultPath)/\(name)") +// } else { +// if directoryExists { throw fail(bar: savingBar, with: "A template with that name already exists") } +// let current = manager.currentDirectoryPath + "/." +// shell(command: "/bin/cp", "-a", "\(current)", "\(defaultPath)/\(name)") +// } +// } else { +// throw fail(bar: savingBar, with: "This command is not supported in macOS versions older then 10.12") +// } +// savingBar.finish() +// +// if useGitHub { +// console.output("The GitHub flag is currently not implimented", style: .warning, newLine: true) +// } +// +// } +//} diff --git a/Sources/Ether/Update.swift b/Sources/Ether/Update.swift index edc1f3b..9fa9d4f 100644 --- a/Sources/Ether/Update.swift +++ b/Sources/Ether/Update.swift @@ -1,105 +1,105 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//import Console // -// 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: +//public final class Update: Command { +// public let id = "update" // -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. +// public let signature: [Argument] = [ +// Option(name: "self", short: "s", help: [ +// "Updates Ether" +// ]), +// Option(name: "xcode", short: "x", help: [ +// "Regenerate and open the Xcode project after update its packages" +// ]) +// ] // -// 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. - -import Console - -public final class Update: Command { - public let id = "update" - - public let signature: [Argument] = [ - Option(name: "self", short: "s", help: [ - "Updates Ether" - ]), - Option(name: "xcode", short: "x", help: [ - "Regenerate and open the Xcode project after update its packages" - ]) - ] - - public let help: [String] = [ - "Updates your dependencies." - ] - - public let console: ConsoleProtocol - - public init(console: ConsoleProtocol) { - self.console = console - } - - public func run(arguments: [String]) throws { - if let _ = arguments.option("self") { - let updateBar = console.loadingBar(title: "Updating Ether") - updateBar.start() - _ = try console.backgroundExecute(program: "/bin/sh", arguments: ["-c", "curl https://raw.githubusercontent.com/calebkleveter/Ether/master/install.sh | bash"]) - updateBar.finish() - self.printEtherArt() - } else { - console.output("This may take some time...", style: .info, newLine: true) - - let updateBar = console.loadingBar(title: "Updating Packages") - updateBar.start() - _ = try console.backgroundExecute(program: "rm", arguments: ["-rf", ".build"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["build"]) - updateBar.finish() - - if let _ = arguments.options["xcode"] { - let xcodeBar = console.loadingBar(title: "Generating Xcode Project") - xcodeBar.start() - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "generate-xcodeproj"]) - xcodeBar.finish() - try console.execute(program: "/bin/sh", arguments: ["-c", "open *.xcodeproj"], input: nil, output: nil, error: nil) - } - } - } - - private func printEtherArt() { - let etherArt = """ - | • | - | • | - | • | - / \\ - / \\ - """ - - let characterColors: [Character: ConsoleColor] = [ - "•": .green - ] - - for character in console.center(etherArt) { - let style: ConsoleStyle - - if let color = characterColors[character] { - style = .custom(color) - } else { - style = .plain - } - - console.output("\(character)", style: style, newLine: false) - } - - console.print() - console.print() - console.output(console.center("Thanks for Updating Ether!"), style: .plain, newLine: true) - } - -} +// public let help: [String] = [ +// "Updates your dependencies." +// ] +// +// public let console: ConsoleProtocol +// +// public init(console: ConsoleProtocol) { +// self.console = console +// } +// +// public func run(arguments: [String]) throws { +// if let _ = arguments.option("self") { +// let updateBar = console.loadingBar(title: "Updating Ether") +// updateBar.start() +// _ = try console.backgroundExecute(program: "/bin/sh", arguments: ["-c", "curl https://raw.githubusercontent.com/calebkleveter/Ether/master/install.sh | bash"]) +// updateBar.finish() +// self.printEtherArt() +// } else { +// console.output("This may take some time...", style: .info, newLine: true) +// +// let updateBar = console.loadingBar(title: "Updating Packages") +// updateBar.start() +// _ = try console.backgroundExecute(program: "rm", arguments: ["-rf", ".build"]) +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) +// _ = try console.backgroundExecute(program: "swift", arguments: ["build"]) +// updateBar.finish() +// +// if let _ = arguments.options["xcode"] { +// let xcodeBar = console.loadingBar(title: "Generating Xcode Project") +// xcodeBar.start() +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "generate-xcodeproj"]) +// xcodeBar.finish() +// try console.execute(program: "/bin/sh", arguments: ["-c", "open *.xcodeproj"], input: nil, output: nil, error: nil) +// } +// } +// } +// +// private func printEtherArt() { +// let etherArt = """ +// | • | +// | • | +// | • | +// / \\ +// / \\ +// """ +// +// let characterColors: [Character: ConsoleColor] = [ +// "•": .green +// ] +// +// for character in console.center(etherArt) { +// let style: ConsoleStyle +// +// if let color = characterColors[character] { +// style = .custom(color) +// } else { +// style = .plain +// } +// +// console.output("\(character)", style: style, newLine: false) +// } +// +// console.print() +// console.print() +// console.output(console.center("Thanks for Updating Ether!"), style: .plain, newLine: true) +// } +// +//} diff --git a/Sources/Ether/VersionAll.swift b/Sources/Ether/VersionAll.swift index 880a913..f6aef6f 100644 --- a/Sources/Ether/VersionAll.swift +++ b/Sources/Ether/VersionAll.swift @@ -1,55 +1,55 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//import Console +//import Foundation +//import Helpers // -// 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. - -import Console -import Foundation -import Helpers - -public final class VersionAll: Command { - public let id = "all" - - public var help: [String] = [ - "Outputs the name of each package installed and its version" - ] - - public var signature: [Argument] = [] - - public let console: ConsoleProtocol - - public init(console: ConsoleProtocol) { - self.console = console - } - - public func run(arguments: [String]) throws { - let fetchingDataBar = console.loadingBar(title: "Getting Package Data") - fetchingDataBar.start() - - let pins = try Manifest.current.getPins() - fetchingDataBar.finish() - pins.forEach { package in - console.output("\(package["package"] ?? "N/A" as AnyObject): ", style: .success, newLine: false) - if let state = package["state"] as? [String: AnyObject] { - console.output("v\(state["version"] ?? "N/A" as AnyObject)", style: .plain, newLine: true) - } - } - } -} +//public final class VersionAll: Command { +// public let id = "all" +// +// public var help: [String] = [ +// "Outputs the name of each package installed and its version" +// ] +// +// public var signature: [Argument] = [] +// +// public let console: ConsoleProtocol +// +// public init(console: ConsoleProtocol) { +// self.console = console +// } +// +// public func run(arguments: [String]) throws { +// let fetchingDataBar = console.loadingBar(title: "Getting Package Data") +// fetchingDataBar.start() +// +// let pins = try Manifest.current.getPins() +// fetchingDataBar.finish() +// pins.forEach { package in +// console.output("\(package["package"] ?? "N/A" as AnyObject): ", style: .success, newLine: false) +// if let state = package["state"] as? [String: AnyObject] { +// console.output("v\(state["version"] ?? "N/A" as AnyObject)", style: .plain, newLine: true) +// } +// } +// } +//} diff --git a/Sources/Ether/VersionLatest.swift b/Sources/Ether/VersionLatest.swift index 47342c5..86d9ddd 100644 --- a/Sources/Ether/VersionLatest.swift +++ b/Sources/Ether/VersionLatest.swift @@ -1,88 +1,88 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//// REGEX: \\.Package\\(url\\:\\s?\\\"https\\:\\/\\/github\\.com([\\d\\w\\:\\/\\.\\@\\-]+)\\.git\\\"\\,([\\d\\w\\s\\:])+\\)\\,? // -// 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: +//import Console +//import Helpers +//import Foundation +//import Core // -// 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. - -// REGEX: \\.Package\\(url\\:\\s?\\\"https\\:\\/\\/github\\.com([\\d\\w\\:\\/\\.\\@\\-]+)\\.git\\\"\\,([\\d\\w\\s\\:])+\\)\\,? - -import Console -import Helpers -import Foundation -import Core - -public final class VersionLatest: Command { - public let id = "latest" - public let baseURL = "https://packagecatalog.com/data/package" - - public var help: [String] = [ - "Updates all packeges to the latest version" - ] - - public var signature: [Argument] = [ - Option(name: "xcode", short: "x", help: [ - "Regenerate Xcode project after updating package versions" - ]) - ] - - public let console: ConsoleProtocol - public let client = PackageJSONFetcher() - - public init(console: ConsoleProtocol) { - self.console = console - } - - public func run(arguments: [String]) throws { - let updateBar = console.loadingBar(title: "Updating Package Versions") - updateBar.start() - - let fileManager = FileManager.default - let manifest = try Manifest.current.get() - let nsManifest = NSMutableString(string: manifest) - let versionPattern = try NSRegularExpression(pattern: "(.package\\(url:\\s*\".*?\\.com\\/(.*?)\\.git\",\\s*)(.*?)(\\),?\\n)", options: []) - let matches = versionPattern.matches(in: manifest, options: [], range: NSMakeRange(0, manifest.utf8.count)) - let packageNames = matches.map { match -> String in - let name = versionPattern.replacementString(for: match, in: manifest, offset: 0, template: "$2") - return name - } - let packageVersions = try packageNames.map { name -> String in - return try Manifest.current.getPackageData(for: name).version - } - - try zip(packageVersions, packageNames).forEach { (arg) in - let (version, name) = arg - let pattern = try NSRegularExpression(pattern: "(.package\\(url:\\s*\".*?\\.com\\/\(name)\\.git\",\\s*)(\\.?\\w+(\\(|:)\\s*\"[\\w\\.]+\"\\)?)(\\))", options: []) - pattern.replaceMatches(in: nsManifest, options: [], range: NSMakeRange(0, nsManifest.length), withTemplate: "$1.exact(\"\(version)\"))") - } - - try String(nsManifest).data(using: .utf8)?.write(to: URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift")!) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) - - updateBar.finish() - - if let _ = arguments.options["xcode"] { - let xcodeBar = console.loadingBar(title: "Generating Xcode Project") - xcodeBar.start() - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "generate-xcodeproj"]) - xcodeBar.finish() - try console.execute(program: "/bin/sh", arguments: ["-c", "open *.xcodeproj"], input: nil, output: nil, error: nil) - } - } -} +//public final class VersionLatest: Command { +// public let id = "latest" +// public let baseURL = "https://packagecatalog.com/data/package" +// +// public var help: [String] = [ +// "Updates all packeges to the latest version" +// ] +// +// public var signature: [Argument] = [ +// Option(name: "xcode", short: "x", help: [ +// "Regenerate Xcode project after updating package versions" +// ]) +// ] +// +// public let console: ConsoleProtocol +// public let client = PackageJSONFetcher() +// +// public init(console: ConsoleProtocol) { +// self.console = console +// } +// +// public func run(arguments: [String]) throws { +// let updateBar = console.loadingBar(title: "Updating Package Versions") +// updateBar.start() +// +// let fileManager = FileManager.default +// let manifest = try Manifest.current.get() +// let nsManifest = NSMutableString(string: manifest) +// let versionPattern = try NSRegularExpression(pattern: "(.package\\(url:\\s*\".*?\\.com\\/(.*?)\\.git\",\\s*)(.*?)(\\),?\\n)", options: []) +// let matches = versionPattern.matches(in: manifest, options: [], range: NSMakeRange(0, manifest.utf8.count)) +// let packageNames = matches.map { match -> String in +// let name = versionPattern.replacementString(for: match, in: manifest, offset: 0, template: "$2") +// return name +// } +// let packageVersions = try packageNames.map { name -> String in +// return try Manifest.current.getPackageData(for: name).version +// } +// +// try zip(packageVersions, packageNames).forEach { (arg) in +// let (version, name) = arg +// let pattern = try NSRegularExpression(pattern: "(.package\\(url:\\s*\".*?\\.com\\/\(name)\\.git\",\\s*)(\\.?\\w+(\\(|:)\\s*\"[\\w\\.]+\"\\)?)(\\))", options: []) +// pattern.replaceMatches(in: nsManifest, options: [], range: NSMakeRange(0, nsManifest.length), withTemplate: "$1.exact(\"\(version)\"))") +// } +// +// try String(nsManifest).data(using: .utf8)?.write(to: URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift")!) +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) +// +// updateBar.finish() +// +// if let _ = arguments.options["xcode"] { +// let xcodeBar = console.loadingBar(title: "Generating Xcode Project") +// xcodeBar.start() +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "generate-xcodeproj"]) +// xcodeBar.finish() +// try console.execute(program: "/bin/sh", arguments: ["-c", "open *.xcodeproj"], input: nil, output: nil, error: nil) +// } +// } +//} diff --git a/Sources/Ether/VersionSet.swift b/Sources/Ether/VersionSet.swift index a75b746..f9e040e 100644 --- a/Sources/Ether/VersionSet.swift +++ b/Sources/Ether/VersionSet.swift @@ -1,117 +1,117 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//import Console +//import Helpers +//import Foundation // -// 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. - -import Console -import Helpers -import Foundation - -public final class VersonSet: Command { - public let id: String = "set" - - public var signature: [Argument] = [ - Value(name: "name", help: [ - "The name of the package to change the version for" - ]), - Value(name: "version", help: [ - "The value for the new version. The format varies depending on the version type used" - ]), - Option(name: "xcode", short: "x", help: [ - "Regenerate the Xcode project after updating a package's version" - ]), - Option(name: "from", short: "f", help: [ - "Sets the dependency version argument to `from: VERSION`" - ]), - Option(name: "up-to-next-major", short: "u", help: [ - "Sets the dependency version argument to `.upToNextMinor(from: \"VERSION\")`" - ]), - Option(name: "exact", short: "e", help: [ - "(Default) Sets the dependency version argument to `.exact(\"VERSION\")`" - ]), - Option(name: "range", short: "r", help: [ - "Sets the dependency version argument to `VERSION`" - ]), - Option(name: "branch", short: "b", help: [ - "Sets the dependency version argument to `.branch(\"VERSION\")`" - ]), - Option(name: "revision", help: [ - "Sets the dependency version argument to `.revision(\"VERSION\")`" - ]) - ] - - public var help: [String] = [ - "Changes the version of a single dependency" - ] - - public let console: ConsoleProtocol - - public init(console: ConsoleProtocol) { - self.console = console - } - - public func run(arguments: [String]) throws { - let updateBar = console.loadingBar(title: "Updating Package Version") - updateBar.start() - - let package = try value("name", from: arguments) - let version = try value("version", from: arguments) - let versionLitteral = versionOption(from: arguments, with: version) - - let url = try Manifest.current.getPackageUrl(for: package) - let manifest = try NSMutableString(string: Manifest.current.get()) - let pattern = try NSRegularExpression( - pattern: "(\\,?\\n *\\.package\\(url: *\"\(url)\", *)(.*?)(\\),?\\n)", - options: [] - ) - pattern.replaceMatches(in: manifest, options: [], range: NSMakeRange(0, manifest.length), withTemplate: "$1\(versionLitteral)$3") - try Manifest.current.write(String(manifest)) - - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) - - updateBar.finish() - - if let _ = arguments.options["xcode"] { - let xcodeBar = console.loadingBar(title: "Generating Xcode Project") - xcodeBar.start() - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "generate-xcodeproj"]) - xcodeBar.finish() - try console.execute(program: "/bin/sh", arguments: ["-c", "open *.xcodeproj"], input: nil, output: nil, error: nil) - } - - console.output("\(package) version was updated", style: .plain, newLine: true) - } - - private func versionOption(from arguments: [String], with version: String) -> String { - if arguments.option("from") != nil { - return "from: \"\(version)\"" - } else if arguments.option("up-to-next-major") != nil { - return ".upToNextMajor(from: \"\(version)\")" - } else if arguments.option("range") != nil { - return "\"\(version.dropLast(8))\"\(String(version.dropFirst(5)).dropLast(5))\"\(version.dropFirst(8))\"" - } else if arguments.option("branch") != nil { - return ".branch(\"\(version)\")" - } else if arguments.option("revision") != nil { - return ".revision(\"\(version)\")" - } - return ".exact(\"\(version)\")" - } -} +//public final class VersonSet: Command { +// public let id: String = "set" +// +// public var signature: [Argument] = [ +// Value(name: "name", help: [ +// "The name of the package to change the version for" +// ]), +// Value(name: "version", help: [ +// "The value for the new version. The format varies depending on the version type used" +// ]), +// Option(name: "xcode", short: "x", help: [ +// "Regenerate the Xcode project after updating a package's version" +// ]), +// Option(name: "from", short: "f", help: [ +// "Sets the dependency version argument to `from: VERSION`" +// ]), +// Option(name: "up-to-next-major", short: "u", help: [ +// "Sets the dependency version argument to `.upToNextMinor(from: \"VERSION\")`" +// ]), +// Option(name: "exact", short: "e", help: [ +// "(Default) Sets the dependency version argument to `.exact(\"VERSION\")`" +// ]), +// Option(name: "range", short: "r", help: [ +// "Sets the dependency version argument to `VERSION`" +// ]), +// Option(name: "branch", short: "b", help: [ +// "Sets the dependency version argument to `.branch(\"VERSION\")`" +// ]), +// Option(name: "revision", help: [ +// "Sets the dependency version argument to `.revision(\"VERSION\")`" +// ]) +// ] +// +// public var help: [String] = [ +// "Changes the version of a single dependency" +// ] +// +// public let console: ConsoleProtocol +// +// public init(console: ConsoleProtocol) { +// self.console = console +// } +// +// public func run(arguments: [String]) throws { +// let updateBar = console.loadingBar(title: "Updating Package Version") +// updateBar.start() +// +// let package = try value("name", from: arguments) +// let version = try value("version", from: arguments) +// let versionLitteral = versionOption(from: arguments, with: version) +// +// let url = try Manifest.current.getPackageUrl(for: package) +// let manifest = try NSMutableString(string: Manifest.current.get()) +// let pattern = try NSRegularExpression( +// pattern: "(\\,?\\n *\\.package\\(url: *\"\(url)\", *)(.*?)(\\),?\\n)", +// options: [] +// ) +// pattern.replaceMatches(in: manifest, options: [], range: NSMakeRange(0, manifest.length), withTemplate: "$1\(versionLitteral)$3") +// try Manifest.current.write(String(manifest)) +// +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) +// +// updateBar.finish() +// +// if let _ = arguments.options["xcode"] { +// let xcodeBar = console.loadingBar(title: "Generating Xcode Project") +// xcodeBar.start() +// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "generate-xcodeproj"]) +// xcodeBar.finish() +// try console.execute(program: "/bin/sh", arguments: ["-c", "open *.xcodeproj"], input: nil, output: nil, error: nil) +// } +// +// console.output("\(package) version was updated", style: .plain, newLine: true) +// } +// +// private func versionOption(from arguments: [String], with version: String) -> String { +// if arguments.option("from") != nil { +// return "from: \"\(version)\"" +// } else if arguments.option("up-to-next-major") != nil { +// return ".upToNextMajor(from: \"\(version)\")" +// } else if arguments.option("range") != nil { +// return "\"\(version.dropLast(8))\"\(String(version.dropFirst(5)).dropLast(5))\"\(version.dropFirst(8))\"" +// } else if arguments.option("branch") != nil { +// return ".branch(\"\(version)\")" +// } else if arguments.option("revision") != nil { +// return ".revision(\"\(version)\")" +// } +// return ".exact(\"\(version)\")" +// } +//} diff --git a/Sources/Executable/main.swift b/Sources/Executable/main.swift index 172104e..b804435 100644 --- a/Sources/Executable/main.swift +++ b/Sources/Executable/main.swift @@ -1,97 +1,97 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//import Foundation +//import Console +//import Ether +//import Helpers +//import libc // -// 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 current version of Ether. This string should be updated with each release. +//let version = "1.10.0" +//var arguments = CommandLine.arguments +//let terminal = Terminal(arguments: arguments) +//var iterator = arguments.makeIterator() // -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. +//guard let executable = iterator.next() else { +// throw ConsoleError.noExecutable +//} // -// 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. - -import Foundation -import Console -import Ether -import Helpers -import libc - -// The current version of Ether. This string should be updated with each release. -let version = "1.10.0" -var arguments = CommandLine.arguments -let terminal = Terminal(arguments: arguments) -var iterator = arguments.makeIterator() - -guard let executable = iterator.next() else { - throw ConsoleError.noExecutable -} - -if arguments.count == 2, arguments[1] == "--version" || arguments[1] == "-v" { - terminal.output("Ether Version: \(version)", style: .info, newLine: true) - exit(0) -} - -let date = Date() -let formatter = DateFormatter() -formatter.dateFormat = "YYYY" -let currentYear = formatter.string(from: date) - -do { - let commands: [Runnable] = [ - Search(console: terminal), - Install(console: terminal), - Update(console: terminal), - Remove(console: terminal), - Template(console: terminal), - New(console: terminal), - FixInstall(console: terminal), - Group(id: "version", commands: [ - VersionLatest(console: terminal), - VersionAll(console: terminal), - VersonSet(console: terminal) - ], help: ["For interacting with dependency versions"]), - CleanManifest(console: terminal) - ] - - try terminal.run(executable: executable, commands: commands, arguments: Array(iterator), help: [ - "MIT \(currentYear) Caleb Kleveter.", - "If you are getting errors, open an issue on GitHub.", - "If you want to help, submit a PR." - ]) -} catch ConsoleError.insufficientArguments { - terminal.error("Error: ", newLine: false) - terminal.print("Insufficient arguments.") -} catch ConsoleError.help { - exit(0) -} catch ConsoleError.cancelled { - print("Cancelled") - exit(2) -} catch ConsoleError.noCommand { - terminal.error("Error: ", newLine: false) - terminal.print("No command supplied.") -} catch let ConsoleError.commandNotFound(id) { - terminal.error("Error: ", newLine: false) - terminal.print("Command \"\(id)\" not found.") -} catch let EtherError.fail(message) { - let err = "Error: " - var output = message.split(separator: "\n").map({ return String(repeating: " ", count: err.count) + $0 }) - output[0] = output[0].trim() - - terminal.error("Error: ", newLine: false) - terminal.print(output.joined(separator: "\n")) - exit(1) -} catch { - terminal.error("Error: ", newLine: false) - terminal.print("\(error)") - exit(1) -} +//if arguments.count == 2, arguments[1] == "--version" || arguments[1] == "-v" { +// terminal.output("Ether Version: \(version)", style: .info, newLine: true) +// exit(0) +//} +// +//let date = Date() +//let formatter = DateFormatter() +//formatter.dateFormat = "YYYY" +//let currentYear = formatter.string(from: date) +// +//do { +// let commands: [Runnable] = [ +// Search(console: terminal), +// Install(console: terminal), +// Update(console: terminal), +// Remove(console: terminal), +// Template(console: terminal), +// New(console: terminal), +// FixInstall(console: terminal), +// Group(id: "version", commands: [ +// VersionLatest(console: terminal), +// VersionAll(console: terminal), +// VersonSet(console: terminal) +// ], help: ["For interacting with dependency versions"]), +// CleanManifest(console: terminal) +// ] +// +// try terminal.run(executable: executable, commands: commands, arguments: Array(iterator), help: [ +// "MIT \(currentYear) Caleb Kleveter.", +// "If you are getting errors, open an issue on GitHub.", +// "If you want to help, submit a PR." +// ]) +//} catch ConsoleError.insufficientArguments { +// terminal.error("Error: ", newLine: false) +// terminal.print("Insufficient arguments.") +//} catch ConsoleError.help { +// exit(0) +//} catch ConsoleError.cancelled { +// print("Cancelled") +// exit(2) +//} catch ConsoleError.noCommand { +// terminal.error("Error: ", newLine: false) +// terminal.print("No command supplied.") +//} catch let ConsoleError.commandNotFound(id) { +// terminal.error("Error: ", newLine: false) +// terminal.print("Command \"\(id)\" not found.") +//} catch let EtherError.fail(message) { +// let err = "Error: " +// var output = message.split(separator: "\n").map({ return String(repeating: " ", count: err.count) + $0 }) +// output[0] = output[0].trim() +// +// terminal.error("Error: ", newLine: false) +// terminal.print(output.joined(separator: "\n")) +// exit(1) +//} catch { +// terminal.error("Error: ", newLine: false) +// terminal.print("\(error)") +// exit(1) +//} diff --git a/Sources/Helpers/APIClient.swift b/Sources/Helpers/APIClient.swift index 5b67350..816d7e6 100644 --- a/Sources/Helpers/APIClient.swift +++ b/Sources/Helpers/APIClient.swift @@ -1,100 +1,100 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//import Foundation +//import Core // -// 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: +//public let CKNetworkingErrorDomain = "com.caleb-kleveter.Ether.NetworkingError" +//public let MissingHTTPResponseError: Int = 0 // -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. +//public typealias APIJSON = [String: AnyObject] +//public typealias FetchCompletion = (APIJSON?, HTTPURLResponse?, DataTaskError?) -> Void // -// 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. - -import Foundation -import Core - -public let CKNetworkingErrorDomain = "com.caleb-kleveter.Ether.NetworkingError" -public let MissingHTTPResponseError: Int = 0 - -public typealias APIJSON = [String: AnyObject] -public typealias FetchCompletion = (APIJSON?, HTTPURLResponse?, DataTaskError?) -> Void - -public enum DataTaskError: Error { - case badStatusCode(Int) - case cannotCastToHTTPURLResponse(NSError) - case dataTaskError(Error) - case noData - case jsonSerializationError(Error) - case noJson -} - -public protocol JSONInitable { - init(json: APIJSON) -} - -public protocol APIClient { - var configuration: URLSessionConfiguration { get } - var session: URLSession { get } - - func dataTask(with request: URLRequest, endingWith completion: @escaping FetchCompletion) -> URLSessionDataTask -} - -extension APIClient { - public func dataTask(with request: URLRequest, endingWith completion: @escaping FetchCompletion) -> URLSessionDataTask { - let task = try! Portal.open({ (portal) in - let task = self.session.dataTask(with: request) { (data, response, error) in - - guard let resp = response as? HTTPURLResponse else { - let userInfo = [ - NSLocalizedDescriptionKey: NSLocalizedString("Missing HTTP Response", comment: "") - ] - - let error = NSError(domain: CKNetworkingErrorDomain, code: MissingHTTPResponseError, userInfo: userInfo) - completion(nil, nil, DataTaskError.cannotCastToHTTPURLResponse(error)) - return - } - - if resp.statusCode >= 200 && resp.statusCode < 300 { - if error == nil { - if data != nil { - do { - let json = try JSONSerialization.jsonObject(with: data!, options: []) as? APIJSON - if let json = json { - completion(json, resp, nil) - } else { - completion(nil, nil, .noJson) - return - } - } catch let error { - completion(nil, nil, .jsonSerializationError(error)) - return - } - return - } else { - completion(nil, nil, .noData) - return - } - } else { - completion(nil, nil, .dataTaskError(error!)) - return - } - } else { - completion(nil, nil, .badStatusCode(resp.statusCode)) - return - } - } - portal.close(with: task) - }) - return task - } -} +//public enum DataTaskError: Error { +// case badStatusCode(Int) +// case cannotCastToHTTPURLResponse(NSError) +// case dataTaskError(Error) +// case noData +// case jsonSerializationError(Error) +// case noJson +//} +// +//public protocol JSONInitable { +// init(json: APIJSON) +//} +// +//public protocol APIClient { +// var configuration: URLSessionConfiguration { get } +// var session: URLSession { get } +// +// func dataTask(with request: URLRequest, endingWith completion: @escaping FetchCompletion) -> URLSessionDataTask +//} +// +//extension APIClient { +// public func dataTask(with request: URLRequest, endingWith completion: @escaping FetchCompletion) -> URLSessionDataTask { +// let task = try! Portal.open({ (portal) in +// let task = self.session.dataTask(with: request) { (data, response, error) in +// +// guard let resp = response as? HTTPURLResponse else { +// let userInfo = [ +// NSLocalizedDescriptionKey: NSLocalizedString("Missing HTTP Response", comment: "") +// ] +// +// let error = NSError(domain: CKNetworkingErrorDomain, code: MissingHTTPResponseError, userInfo: userInfo) +// completion(nil, nil, DataTaskError.cannotCastToHTTPURLResponse(error)) +// return +// } +// +// if resp.statusCode >= 200 && resp.statusCode < 300 { +// if error == nil { +// if data != nil { +// do { +// let json = try JSONSerialization.jsonObject(with: data!, options: []) as? APIJSON +// if let json = json { +// completion(json, resp, nil) +// } else { +// completion(nil, nil, .noJson) +// return +// } +// } catch let error { +// completion(nil, nil, .jsonSerializationError(error)) +// return +// } +// return +// } else { +// completion(nil, nil, .noData) +// return +// } +// } else { +// completion(nil, nil, .dataTaskError(error!)) +// return +// } +// } else { +// completion(nil, nil, .badStatusCode(resp.statusCode)) +// return +// } +// } +// portal.close(with: task) +// }) +// return task +// } +//} diff --git a/Sources/Helpers/JSON.swift b/Sources/Helpers/JSON.swift index 869d69c..20ec7bd 100644 --- a/Sources/Helpers/JSON.swift +++ b/Sources/Helpers/JSON.swift @@ -1,29 +1,29 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//import Foundation // -// 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. - -import Foundation - -public extension Data { - public func json()throws -> APIJSON? { - return try JSONSerialization.jsonObject(with: self, options: []) as? APIJSON - } -} +//public extension Data { +// public func json()throws -> APIJSON? { +// return try JSONSerialization.jsonObject(with: self, options: []) as? APIJSON +// } +//} diff --git a/Sources/Helpers/Manifest.swift b/Sources/Helpers/Manifest.swift index b4ff0e6..9aa9e19 100644 --- a/Sources/Helpers/Manifest.swift +++ b/Sources/Helpers/Manifest.swift @@ -1,291 +1,291 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//import Foundation +//import Console +//import Bits // -// 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: +//public class Manifest { +// public static let current = Manifest() +// private let fileManager = FileManager.default +// private let client = PackageJSONFetcher() +// +// private init() {} +// +// /// Gets the package manifest for the current project. +// /// +// /// - Returns: The manifest data. +// /// - Throws: If a package manifest is not found in the current directory. +// public func get()throws -> String { +// guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift") else { +// throw EtherError.fail("Unable to create URL for package manifest file.") +// } +// if !fileManager.fileExists(atPath: "\(fileManager.currentDirectoryPath)/Package.swift") { +// throw EtherError.fail("Bad path to package manifest. Make sure you are in the project root.") +// } +// +// return try String(contentsOf: resolvedURL) +// } +// +// /// Rewrites the package manifest file with a string. +// /// +// /// - Parameter string: The string the rewrite the manifest with. +// /// - Throws: Any errors that occur when createing the URL to the manifest file or in writing the manifest. +// public func write(_ string: String)throws { +// guard let manifestURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift") else { +// throw EtherError.fail("Unable to create URL for package manifest file.") +// } +// try string.data(using: .utf8)?.write(to: manifestURL) +// } +// +// /// Gets the package manifest data in JSON format. +// /// +// /// - Parameter console: The `ConsoleProtocol` instance to use to run `swift package dump-package`. +// /// - Returns: The JSON data representing the package manifest. +// /// - Throws: `EtherError.fail` if the data returned from the command cannot be converted to JSON. +// public func getJSON(withConsole console: ConsoleProtocol)throws -> APIJSON { +// guard let json = try (console.backgroundExecute(program: "swift", arguments: ["package", "dump-package"]) as Data).json() else { +// throw EtherError.fail("Unable to convert package data to JSON") +// } +// return json +// } +// +// /// Gets the name of the package that has a specefied URL by reading the `Package.resolved` file data. +// /// +// /// - Parameter url: The URL of the package that the name is to get fetched from. +// /// - Returns: The name of the package that was found. +// /// - Throws: An error is thrown if either, 1) The data in the Package.resolved file is corrupted, or 2) A package does not exist with the URL passed in +// public func getPackageName(`for` url: String)throws -> String { +// guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.resolved") else { +// throw EtherError.fail("Bad path to package data. Make sure you are in the project root.") +// } +// let packageData = try Data(contentsOf: resolvedURL).json() +// +// guard let object = packageData?["object"] as? APIJSON, +// let pins = object["pins"] as? [APIJSON] else { throw EtherError.fail("Unable to read Package.resolved") } +// +// guard let package = try pins.filter({ (json) -> Bool in +// guard let repoURL = json["repositoryURL"] as? String else { +// throw EtherError.fail("Unable to read Package.resolved") +// } +// return repoURL == url +// }).first else { +// throw EtherError.fail("Unable to read Package.resolved") +// } +// +// guard let name = package["package"] as? String else { +// throw EtherError.fail("Unable to read Package.resolved") +// } +// +// return name +// } +// +// /// Gets the URL of the package that has a specefied name by reading the `Package.resolved` file data. +// /// +// /// - Parameter name: The ame of the package that the URL is to get fetched from. +// /// - Returns: The URL of the package that was found. +// /// - Throws: An error is thrown if either, 1) The data in the Package.resolved file is corrupted, or 2) A package does not exist with the name passed in +// public func getPackageUrl(`for` name: String)throws -> String { +// guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.resolved") else { +// throw EtherError.fail("Bad path to package data. Make sure you are in the project root.") +// } +// let packageData = try Data(contentsOf: resolvedURL).json() +// +// guard let object = packageData?["object"] as? APIJSON, +// let pins = object["pins"] as? [APIJSON] else { throw EtherError.fail("Unable to read Package.resolved") } +// +// guard let package = try pins.filter({ (json) -> Bool in +// guard let repoURL = json["package"] as? String else { +// throw EtherError.fail("Unable to read Package.resolved") +// } +// return repoURL == name +// }).first else { +// throw EtherError.fail("No package data found for name '\(name)'") +// } +// +// guard let url = package["repositoryURL"] as? String else { +// throw EtherError.fail("Unable to read repo URL for package with name '\(name)'") +// } +// +// return url +// } +// +// /// Gets that names of all the current projects targets. +// /// +// /// - Parameter packageData: The contents of the package manifest file. +// /// - Returns: All the target names. +// /// - Throws: Any errors that occur while creating an `NSRegularExpression` to match targets against. +// public func getTargets()throws -> [String] { +// guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift") else { +// throw EtherError.fail("Bad path to package data. Make sure you are in the project root.") +// } +// let packageData = try String(contentsOf: resolvedURL) +// +// let targetPattern = try NSRegularExpression(pattern: "\\.(testT|t)arget\\(\\s*name:\\s\"(.*?)\".*?(\\)|\\])\\)", options: NSRegularExpression.Options.dotMatchesLineSeparators) +// let targetMatches = targetPattern.matches(in: packageData, options: [], range: NSMakeRange(0, packageData.utf8.count)) +// +// let targetNames = targetMatches.map { (match) in +// return targetPattern.replacementString(for: match, in: packageData, offset: 0, template: "$2") +// } +// +// return targetNames +// } +// +// /// Gets the pins from `Package.resolved`. +// /// +// /// - Returns: The projects package pins. +// /// - Throws: An Ether error if a `Package.resolved` file is not found, or the JSON it contains is malformed. +// public func getPins()throws -> [APIJSON] { +// guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.resolved") else { +// throw EtherError.fail("Bad path to package data. Make sure you are in the project root.") +// } +// let packageData = try Data(contentsOf: resolvedURL).json() +// +// guard let object = packageData?["object"] as? APIJSON, +// let pins = object["pins"] as? [APIJSON] else { +// throw EtherError.fail("Unable to read Package.resolved") +// } +// +// return pins +// } +// +// /// Removes extra comments and white space from a package manifest. +// /// +// /// - Throws: Errors from creating maifest URL, NSRegularExpression objects, or re-writing the maifest. +// public func clean()throws { +// let manifest = try self.get() +// let lines = manifest.split(separator: "\n").map(String.init) +// +// let comment = try NSRegularExpression(pattern: " *\\/\\/ +(?!swift-tools-version).*", options: []) +// let collapse = try NSRegularExpression(pattern: " *\\.(?:library|(?:testT|t)arget)\\(", options: []) +// +// var newManifest: [String] = [] +// var currentLine = "" +// var lineIndex = 0 +// +// while lineIndex < lines.count { +// var line = lines[lineIndex] +// if comment.matches(in: line, options: [], range: NSMakeRange(0, line.count)).count > 0 { +// lineIndex += 1 +// } else if collapse.matches(in: line, options: [], range: NSMakeRange(0, line.count)).count > 0 { +// currentLine = "" +// while !line.contains(")") { +// if currentLine.last != nil, currentLine.last! == "(" { +// currentLine.append(line.trim()) +// } else if currentLine == "" { +// currentLine.append(line) +// } else { +// currentLine.append(" " + line.trim()) +// } +// lineIndex += 1 +// line = lines[lineIndex] +// } +// currentLine.append(" " + line.trim()) +// lineIndex += 1 +// line = lines[lineIndex] +// +// newManifest.append(currentLine) +// } else { +// newManifest.append(line) +// lineIndex += 1 +// } +// } +// +// try self.write(newManifest.joined(separator: "\n")) +// } +// +// /// Gets the URL and version of a package from the IBM package catalog API on a search URL. +// /// +// /// - Parameter name: The name of the package to get data for. If it contains a forward slash, the data will be fetched for the matching package, if it does not contain a forward slash, a search will be preformed and the first result will be used. +// /// - Returns: The URL and version of the package found. +// /// - Throws: Any errors that occur while fetching the JSON, or unwrapping the package data. +// public func getPackageData(for name: String)throws -> (url: String, version: String) { +// let packageUrl: String +// let version: String +// +// if name.contains("/") { +// let clientUrl = "https://packagecatalog.com/data/package/\(name)" +// let json = try client.get(from: clientUrl, withParameters: [:]) +// guard let ghUrl = json["ghUrl"] as? String, +// let packageVersion = json["version"] as? String else { +// throw EtherError.fail("Bad JSON") +// } +// +// packageUrl = ghUrl +// version = packageVersion +// } else { +// let clientUrl = "https://packagecatalog.com/api/search/\(name)" +// let json = try client.get(from: clientUrl, withParameters: ["items": "1", "chart": "moststarred"]) +// guard let data = json["data"] as? APIJSON, +// let hits = data["hits"] as? APIJSON, +// let results = hits["hits"] as? [APIJSON], +// let source = results[0]["_source"] as? APIJSON else { +// throw EtherError.fail("Bad JSON") +// } +// +// packageUrl = String(describing: source["git_clone_url"]!) +// version = String(describing: source["latest_version"]!) +// } +// +// return (url: packageUrl, version: version) +// } +//} // -// 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. - -import Foundation -import Console -import Bits - -public class Manifest { - public static let current = Manifest() - private let fileManager = FileManager.default - private let client = PackageJSONFetcher() - - private init() {} - - /// Gets the package manifest for the current project. - /// - /// - Returns: The manifest data. - /// - Throws: If a package manifest is not found in the current directory. - public func get()throws -> String { - guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift") else { - throw EtherError.fail("Unable to create URL for package manifest file.") - } - if !fileManager.fileExists(atPath: "\(fileManager.currentDirectoryPath)/Package.swift") { - throw EtherError.fail("Bad path to package manifest. Make sure you are in the project root.") - } - - return try String(contentsOf: resolvedURL) - } - - /// Rewrites the package manifest file with a string. - /// - /// - Parameter string: The string the rewrite the manifest with. - /// - Throws: Any errors that occur when createing the URL to the manifest file or in writing the manifest. - public func write(_ string: String)throws { - guard let manifestURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift") else { - throw EtherError.fail("Unable to create URL for package manifest file.") - } - try string.data(using: .utf8)?.write(to: manifestURL) - } - - /// Gets the package manifest data in JSON format. - /// - /// - Parameter console: The `ConsoleProtocol` instance to use to run `swift package dump-package`. - /// - Returns: The JSON data representing the package manifest. - /// - Throws: `EtherError.fail` if the data returned from the command cannot be converted to JSON. - public func getJSON(withConsole console: ConsoleProtocol)throws -> APIJSON { - guard let json = try (console.backgroundExecute(program: "swift", arguments: ["package", "dump-package"]) as Data).json() else { - throw EtherError.fail("Unable to convert package data to JSON") - } - return json - } - - /// Gets the name of the package that has a specefied URL by reading the `Package.resolved` file data. - /// - /// - Parameter url: The URL of the package that the name is to get fetched from. - /// - Returns: The name of the package that was found. - /// - Throws: An error is thrown if either, 1) The data in the Package.resolved file is corrupted, or 2) A package does not exist with the URL passed in - public func getPackageName(`for` url: String)throws -> String { - guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.resolved") else { - throw EtherError.fail("Bad path to package data. Make sure you are in the project root.") - } - let packageData = try Data(contentsOf: resolvedURL).json() - - guard let object = packageData?["object"] as? APIJSON, - let pins = object["pins"] as? [APIJSON] else { throw EtherError.fail("Unable to read Package.resolved") } - - guard let package = try pins.filter({ (json) -> Bool in - guard let repoURL = json["repositoryURL"] as? String else { - throw EtherError.fail("Unable to read Package.resolved") - } - return repoURL == url - }).first else { - throw EtherError.fail("Unable to read Package.resolved") - } - - guard let name = package["package"] as? String else { - throw EtherError.fail("Unable to read Package.resolved") - } - - return name - } - - /// Gets the URL of the package that has a specefied name by reading the `Package.resolved` file data. - /// - /// - Parameter name: The ame of the package that the URL is to get fetched from. - /// - Returns: The URL of the package that was found. - /// - Throws: An error is thrown if either, 1) The data in the Package.resolved file is corrupted, or 2) A package does not exist with the name passed in - public func getPackageUrl(`for` name: String)throws -> String { - guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.resolved") else { - throw EtherError.fail("Bad path to package data. Make sure you are in the project root.") - } - let packageData = try Data(contentsOf: resolvedURL).json() - - guard let object = packageData?["object"] as? APIJSON, - let pins = object["pins"] as? [APIJSON] else { throw EtherError.fail("Unable to read Package.resolved") } - - guard let package = try pins.filter({ (json) -> Bool in - guard let repoURL = json["package"] as? String else { - throw EtherError.fail("Unable to read Package.resolved") - } - return repoURL == name - }).first else { - throw EtherError.fail("No package data found for name '\(name)'") - } - - guard let url = package["repositoryURL"] as? String else { - throw EtherError.fail("Unable to read repo URL for package with name '\(name)'") - } - - return url - } - - /// Gets that names of all the current projects targets. - /// - /// - Parameter packageData: The contents of the package manifest file. - /// - Returns: All the target names. - /// - Throws: Any errors that occur while creating an `NSRegularExpression` to match targets against. - public func getTargets()throws -> [String] { - guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift") else { - throw EtherError.fail("Bad path to package data. Make sure you are in the project root.") - } - let packageData = try String(contentsOf: resolvedURL) - - let targetPattern = try NSRegularExpression(pattern: "\\.(testT|t)arget\\(\\s*name:\\s\"(.*?)\".*?(\\)|\\])\\)", options: NSRegularExpression.Options.dotMatchesLineSeparators) - let targetMatches = targetPattern.matches(in: packageData, options: [], range: NSMakeRange(0, packageData.utf8.count)) - - let targetNames = targetMatches.map { (match) in - return targetPattern.replacementString(for: match, in: packageData, offset: 0, template: "$2") - } - - return targetNames - } - - /// Gets the pins from `Package.resolved`. - /// - /// - Returns: The projects package pins. - /// - Throws: An Ether error if a `Package.resolved` file is not found, or the JSON it contains is malformed. - public func getPins()throws -> [APIJSON] { - guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.resolved") else { - throw EtherError.fail("Bad path to package data. Make sure you are in the project root.") - } - let packageData = try Data(contentsOf: resolvedURL).json() - - guard let object = packageData?["object"] as? APIJSON, - let pins = object["pins"] as? [APIJSON] else { - throw EtherError.fail("Unable to read Package.resolved") - } - - return pins - } - - /// Removes extra comments and white space from a package manifest. - /// - /// - Throws: Errors from creating maifest URL, NSRegularExpression objects, or re-writing the maifest. - public func clean()throws { - let manifest = try self.get() - let lines = manifest.split(separator: "\n").map(String.init) - - let comment = try NSRegularExpression(pattern: " *\\/\\/ +(?!swift-tools-version).*", options: []) - let collapse = try NSRegularExpression(pattern: " *\\.(?:library|(?:testT|t)arget)\\(", options: []) - - var newManifest: [String] = [] - var currentLine = "" - var lineIndex = 0 - - while lineIndex < lines.count { - var line = lines[lineIndex] - if comment.matches(in: line, options: [], range: NSMakeRange(0, line.count)).count > 0 { - lineIndex += 1 - } else if collapse.matches(in: line, options: [], range: NSMakeRange(0, line.count)).count > 0 { - currentLine = "" - while !line.contains(")") { - if currentLine.last != nil, currentLine.last! == "(" { - currentLine.append(line.trim()) - } else if currentLine == "" { - currentLine.append(line) - } else { - currentLine.append(" " + line.trim()) - } - lineIndex += 1 - line = lines[lineIndex] - } - currentLine.append(" " + line.trim()) - lineIndex += 1 - line = lines[lineIndex] - - newManifest.append(currentLine) - } else { - newManifest.append(line) - lineIndex += 1 - } - } - - try self.write(newManifest.joined(separator: "\n")) - } - - /// Gets the URL and version of a package from the IBM package catalog API on a search URL. - /// - /// - Parameter name: The name of the package to get data for. If it contains a forward slash, the data will be fetched for the matching package, if it does not contain a forward slash, a search will be preformed and the first result will be used. - /// - Returns: The URL and version of the package found. - /// - Throws: Any errors that occur while fetching the JSON, or unwrapping the package data. - public func getPackageData(for name: String)throws -> (url: String, version: String) { - let packageUrl: String - let version: String - - if name.contains("/") { - let clientUrl = "https://packagecatalog.com/data/package/\(name)" - let json = try client.get(from: clientUrl, withParameters: [:]) - guard let ghUrl = json["ghUrl"] as? String, - let packageVersion = json["version"] as? String else { - throw EtherError.fail("Bad JSON") - } - - packageUrl = ghUrl - version = packageVersion - } else { - let clientUrl = "https://packagecatalog.com/api/search/\(name)" - let json = try client.get(from: clientUrl, withParameters: ["items": "1", "chart": "moststarred"]) - guard let data = json["data"] as? APIJSON, - let hits = data["hits"] as? APIJSON, - let results = hits["hits"] as? [APIJSON], - let source = results[0]["_source"] as? APIJSON else { - throw EtherError.fail("Bad JSON") - } - - packageUrl = String(describing: source["git_clone_url"]!) - version = String(describing: source["latest_version"]!) - } - - return (url: packageUrl, version: version) - } -} - -extension NSMutableString { - - /// Adds a package dependency to a target in a package manifest file. - /// - /// - Parameters: - /// - dependency: The name of the dependency that will be added to a target. - /// - target: The target the dependency will be added to. - /// - packageData: The contents of the package manifest file. - /// - Returns: The package manifest with the dependency added to the target. - /// - Throws: Any errors that originate when creating an `NSRegularExpression`. - public func addDependency(_ dependency: String, to target: String)throws { - let targetPattern = try NSRegularExpression(pattern: "\\.(testT|t)arget\\(\\s*name:\\s\"(.*?)\".*?(\\)|\\])\\)", options: .dotMatchesLineSeparators) - let dependenciesPattern = try NSRegularExpression(pattern: "(dependencies:\\s*\\[\\n?(\\s*).*?(\"|\\))),?\\s*\\]", options: .dotMatchesLineSeparators) - let targetMatches = targetPattern.matches(in: String(self), options: [], range: NSMakeRange(0, self.length)) - - guard let targetRange: NSRange = targetMatches.map({ (match) -> (name: String, range: NSRange) in - let name = targetPattern.replacementString(for: match, in: self as String, offset: 0, template: "$2") - let range = match.range - return (name: name, range: range) - }).filter({ (name: String, range: NSRange) -> Bool in - return name == target - }).first?.1 else { throw EtherError.fail("Attempted to add a dependency to a non-existent target") } - - dependenciesPattern.replaceMatches(in: self, options: [], range: targetRange, withTemplate: "$1, \"\(dependency)\"]") - } - - /// Removes a package dependency from all targets in a package manifest file. - /// - /// - Parameters: - /// - dependency: The name of the dependency that will be removed from all targets. - /// - Returns: The package manifest with the dependency added to the target. - /// - Throws: Any errors that originate when creating an `NSRegularExpression`. - public func removeDependency(_ dependency: String)throws { - let dependenciesPattern = try NSRegularExpression(pattern: "(dependencies: *\\[)((\\s*(\\.\\w+)?\"\\w+\",?\\s*)*)\"\(dependency)\",?\\s*((\\s*(\\.\\w+)?\"\\w+\",?\\s*)*)(\\])", options: .dotMatchesLineSeparators) - let range = NSMakeRange(0, self.length) - - dependenciesPattern.replaceMatches(in: self, options: [], range: range, withTemplate: "$1$2$5$8") - } -} +//extension NSMutableString { +// +// /// Adds a package dependency to a target in a package manifest file. +// /// +// /// - Parameters: +// /// - dependency: The name of the dependency that will be added to a target. +// /// - target: The target the dependency will be added to. +// /// - packageData: The contents of the package manifest file. +// /// - Returns: The package manifest with the dependency added to the target. +// /// - Throws: Any errors that originate when creating an `NSRegularExpression`. +// public func addDependency(_ dependency: String, to target: String)throws { +// let targetPattern = try NSRegularExpression(pattern: "\\.(testT|t)arget\\(\\s*name:\\s\"(.*?)\".*?(\\)|\\])\\)", options: .dotMatchesLineSeparators) +// let dependenciesPattern = try NSRegularExpression(pattern: "(dependencies:\\s*\\[\\n?(\\s*).*?(\"|\\))),?\\s*\\]", options: .dotMatchesLineSeparators) +// let targetMatches = targetPattern.matches(in: String(self), options: [], range: NSMakeRange(0, self.length)) +// +// guard let targetRange: NSRange = targetMatches.map({ (match) -> (name: String, range: NSRange) in +// let name = targetPattern.replacementString(for: match, in: self as String, offset: 0, template: "$2") +// let range = match.range +// return (name: name, range: range) +// }).filter({ (name: String, range: NSRange) -> Bool in +// return name == target +// }).first?.1 else { throw EtherError.fail("Attempted to add a dependency to a non-existent target") } +// +// dependenciesPattern.replaceMatches(in: self, options: [], range: targetRange, withTemplate: "$1, \"\(dependency)\"]") +// } +// +// /// Removes a package dependency from all targets in a package manifest file. +// /// +// /// - Parameters: +// /// - dependency: The name of the dependency that will be removed from all targets. +// /// - Returns: The package manifest with the dependency added to the target. +// /// - Throws: Any errors that originate when creating an `NSRegularExpression`. +// public func removeDependency(_ dependency: String)throws { +// let dependenciesPattern = try NSRegularExpression(pattern: "(dependencies: *\\[)((\\s*(\\.\\w+)?\"\\w+\",?\\s*)*)\"\(dependency)\",?\\s*((\\s*(\\.\\w+)?\"\\w+\",?\\s*)*)(\\])", options: .dotMatchesLineSeparators) +// let range = NSMakeRange(0, self.length) +// +// dependenciesPattern.replaceMatches(in: self, options: [], range: range, withTemplate: "$1$2$5$8") +// } +//} diff --git a/Sources/Helpers/PackageJSONFetcher.swift b/Sources/Helpers/PackageJSONFetcher.swift index d817db4..36a66df 100644 --- a/Sources/Helpers/PackageJSONFetcher.swift +++ b/Sources/Helpers/PackageJSONFetcher.swift @@ -1,78 +1,78 @@ -// The MIT License (MIT) +//// The MIT License (MIT) +//// +//// Copyright (c) 2017 Caleb Kleveter +//// +//// 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. // -// Copyright (c) 2017 Caleb Kleveter +//import Foundation +//import Core // -// 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: +//public enum GetJSONError: Error { +// case badURL(String) +// case noJSON +//} // -// 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. - -import Foundation -import Core - -public enum GetJSONError: Error { - case badURL(String) - case noJSON -} - -public final class PackageJSONFetcher: APIClient { - - public let session: URLSession - - public let configuration: URLSessionConfiguration - - public init() { - self.configuration = URLSessionConfiguration.default - self.session = URLSession(configuration: configuration) - } - - /// Gets the data from a URL in semi-asynchronusly. - /// - /// - Parameters: - /// - urlString: The URL the data will be fetched from. - /// - parameters: The URL's parameters. - /// - completion: The completion handler where either the JSON or Error can be accessed. - public func get(from urlString: String, withParameters parameters: [String: String], _ completion: @escaping (APIJSON?, Error?)->()) { - let parameterString = parameters.map({ return "\($0)=\($1)"}).joined(separator:"&") - if let url = URL(string: urlString + "?" + parameterString) { - let request = URLRequest(url: url) - do { - let (json, error) = try Portal<(APIJSON?,Error?)>.open({ (portal) in - self.dataTask(with: request, endingWith: { (json, reponse, error) in - portal.close(with: (json, error)) - }).resume() - }) - completion(json, error) - } catch {} - } else { completion(nil, GetJSONError.badURL(urlString + "?" + parameterString)) } - } - - /// Synchronously fetches data from a URL - /// - /// - Parameters: - /// - url: The URL the data will be fetched from. - /// - parameters: The paramters for the URL. - /// - Returns: The JSON is returned from the network request. - /// - Throws: Any errors that occur in the Portal or in the network request. - public func get(from url: String, withParameters parameters: [String: String])throws -> APIJSON { - let requestResult = try Portal<(APIJSON?,Error?)>.open({ (portal) in - self.get(from: url, withParameters: parameters, { (json, error) in portal.close(with: (json,error)) }) - }) - if let error = requestResult.1 { throw error } - if requestResult.0 == nil { throw GetJSONError.noJSON } - return requestResult.0! - } -} +//public final class PackageJSONFetcher: APIClient { +// +// public let session: URLSession +// +// public let configuration: URLSessionConfiguration +// +// public init() { +// self.configuration = URLSessionConfiguration.default +// self.session = URLSession(configuration: configuration) +// } +// +// /// Gets the data from a URL in semi-asynchronusly. +// /// +// /// - Parameters: +// /// - urlString: The URL the data will be fetched from. +// /// - parameters: The URL's parameters. +// /// - completion: The completion handler where either the JSON or Error can be accessed. +// public func get(from urlString: String, withParameters parameters: [String: String], _ completion: @escaping (APIJSON?, Error?)->()) { +// let parameterString = parameters.map({ return "\($0)=\($1)"}).joined(separator:"&") +// if let url = URL(string: urlString + "?" + parameterString) { +// let request = URLRequest(url: url) +// do { +// let (json, error) = try Portal<(APIJSON?,Error?)>.open({ (portal) in +// self.dataTask(with: request, endingWith: { (json, reponse, error) in +// portal.close(with: (json, error)) +// }).resume() +// }) +// completion(json, error) +// } catch {} +// } else { completion(nil, GetJSONError.badURL(urlString + "?" + parameterString)) } +// } +// +// /// Synchronously fetches data from a URL +// /// +// /// - Parameters: +// /// - url: The URL the data will be fetched from. +// /// - parameters: The paramters for the URL. +// /// - Returns: The JSON is returned from the network request. +// /// - Throws: Any errors that occur in the Portal or in the network request. +// public func get(from url: String, withParameters parameters: [String: String])throws -> APIJSON { +// let requestResult = try Portal<(APIJSON?,Error?)>.open({ (portal) in +// self.get(from: url, withParameters: parameters, { (json, error) in portal.close(with: (json,error)) }) +// }) +// if let error = requestResult.1 { throw error } +// if requestResult.0 == nil { throw GetJSONError.noJSON } +// return requestResult.0! +// } +//} From ca23360874183d757a10cce2f0eceff9fa8e6df4 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Thu, 29 Mar 2018 17:20:23 -0500 Subject: [PATCH 05/66] Created GitHub class --- Sources/GitHub/API.swift | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Sources/GitHub/API.swift b/Sources/GitHub/API.swift index e69de29..88e6397 100644 --- a/Sources/GitHub/API.swift +++ b/Sources/GitHub/API.swift @@ -0,0 +1,27 @@ +// The MIT License (MIT) +// +// Copyright (c) 2017 Caleb Kleveter +// +// 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. + +import Foundation + +final class GitHub { + +} From bf4edea96ccfc6c4be8f9680bfdac1f809564b7f Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Wed, 4 Apr 2018 16:45:25 -0500 Subject: [PATCH 06/66] Added Command product to Ether target dependencies --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index f9732ec..1d22047 100644 --- a/Package.swift +++ b/Package.swift @@ -11,7 +11,7 @@ let package = Package( targets: [ .target(name: "GitHub", dependencies: ["Core"]), .target(name: "Helpers", dependencies: ["Core", "Console"]), - .target(name: "Ether", dependencies: ["Helpers", "Console"]), + .target(name: "Ether", dependencies: ["Helpers", "Console", "Command"]), .target(name: "Executable", dependencies: ["Ether", "Console"]) ] ) From 4f6321720d73aaa4ecc7817b06e144246e806586 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Wed, 4 Apr 2018 16:57:59 -0500 Subject: [PATCH 07/66] Implemented Install command signiture with Console 3 --- Sources/Ether/Install.swift | 109 +++++++++++++++--------------------- 1 file changed, 44 insertions(+), 65 deletions(-) diff --git a/Sources/Ether/Install.swift b/Sources/Ether/Install.swift index e35b6ec..e22edfe 100644 --- a/Sources/Ether/Install.swift +++ b/Sources/Ether/Install.swift @@ -1,60 +1,49 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. +// The MIT License (MIT) // -//import Helpers -//import Console -//import Foundation -//import Core +// Copyright (c) 2017 Caleb Kleveter // -//public final class Install: Command { -// public let id = "install" -// public let baseURL = "https://packagecatalog.com/data/package/" -// -// public let signature: [Argument] = [ -// Value(name: "name", help: [ -// "The name of the package that will be installed" -// ]), -// Option(name: "url", short: "u", help: [ -// "The URL for the package" -// ]), -// Option(name: "version", short: "v", help: [ -// "The desired version for the package", -// "This defaults to the latest version" -// ]), -// Option(name: "xcode", short: "x", help: [ -// "Regenerate the Xcode project after the install is complete" -// ]) -// ] -// -// public var help: [String] = [ -// "Installs a package into the current project" -// ] -// -// public let console: ConsoleProtocol -// public let client = PackageJSONFetcher() -// -// public init(console: ConsoleProtocol) { -// self.console = console -// } +// 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. + +import Command +import Async + +public final class Install: Command { + public var arguments: [CommandArgument] = [ + CommandArgument.argument(name: "name", help: ["The name of the package that will be installed"]) + ] + + public var options: [CommandOption] = [ + CommandOption.value(name: "url", short: "u", help: ["The URL for the package"]), + CommandOption.value(name: "version", short: "v", help: [ + "The desired version for the package", + "This defaults to the latest version" + ]), + CommandOption.flag(name: "xcode", short: "x", help: ["Regenerate the Xcode project after the install is complete"]) + ] + + public var help: [String] = ["Installs a package into the current project"] + + public func run(using context: CommandContext) throws -> Future { + return context.container.eventLoop.newSucceededFuture(result: ()) + } +} + // // public func run(arguments: [String]) throws { // console.output("Reading Package Targets...", style: .info, newLine: true) @@ -179,13 +168,3 @@ // return acceptedTargets // } //} -// -// -// -// -// -// -// -// -// -// From 07ef16a0e7d1d0c36ceeeea7464c319d8efc7ff4 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Wed, 4 Apr 2018 17:37:12 -0500 Subject: [PATCH 08/66] Ported New command to Console 3 API --- Sources/Ether/New.swift | 187 +++++++++++++++++++--------------------- 1 file changed, 88 insertions(+), 99 deletions(-) diff --git a/Sources/Ether/New.swift b/Sources/Ether/New.swift index 4e98ca2..ae2e9cb 100644 --- a/Sources/Ether/New.swift +++ b/Sources/Ether/New.swift @@ -1,101 +1,90 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. +// The MIT License (MIT) // -//import Console -//import Helpers -//import Foundation +// Copyright (c) 2017 Caleb Kleveter // -//public final class New: Command { -// public let id = "new" -// -// public let help: [String] = [ -// "Create new projects" -// ] -// -// public let signature: [Argument] = [ -// Value(name: "name", help: [ -// "The name of the new project" -// ]), -// Option(name: "executable", short: "e", help: [ -// "Creates an executable SPM project" -// ]), -// Option(name: "package", short: "p", help: [ -// "Creates an SPM package" -// ]), -// Option(name: "template", help: [ -// "Creates a project starting with a previously saved template" -// ]) -// ] -// -// public let console: ConsoleProtocol -// -// public init(console: ConsoleProtocol) { -// self.console = console -// } -// -// public func run(arguments: [String]) throws { -// let newProjectBar = console.loadingBar(title: "Generating Project") -// newProjectBar.start() -// -// let executable = try newExecutable(arguments: arguments) -// let template = try newFromTemplate(arguments: arguments) -// if !executable && !template { -// try newPackage(arguments: arguments) -// } -// -// newProjectBar.finish() -// } -// -// func newExecutable(arguments: [String]) throws -> Bool { -// if let _ = arguments.option("executable") { -// let name = try value("name", from: arguments) -// let script = "mkdir \(name); cd \(name); swift package init --type=executable; ether clean-manifest" -// _ = try console.backgroundExecute(program: "bash", arguments: ["-c", script]) -// return true -// } -// return false -// } -// -// func newFromTemplate(arguments: [String]) throws -> Bool { -// if let template = arguments.option("template") { -// let name = try value("name", from: arguments) -// let manager = FileManager.default -// -// if #available(OSX 10.12, *) { -// let directoryName = manager.homeDirectoryForCurrentUser.absoluteString -// let templatePath = String("\(directoryName)Library/Application Support/Ether/Templates/\(template)".dropFirst(7)) -// let current = manager.currentDirectoryPath -// shell(command: "/bin/cp", "-a", "\(templatePath)", "\(current)/\(name)") -// } else { -// throw EtherError.fail("This command is not supported in macOS versions older then 10.12") -// } -// return true -// } -// return false -// } -// -// func newPackage(arguments: [String]) throws { -// let name = try value("name", from: arguments) -// let script = "mkdir \(name); cd \(name); swift package init; ether clean-manifest" -// _ = try console.backgroundExecute(program: "bash", arguments: ["-c", script]) -// } -//} +// 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. + +import Foundation +import Command +import Console +import Async + +public final class New: Command { + public var arguments: [CommandArgument] = [ + CommandArgument.argument(name: "name", help: ["The name of the new project"]) + ] + + public var options: [CommandOption] = [ + CommandOption.flag(name: "executable", short: "e", help: ["Creates an executable SPM project"]), + CommandOption.flag(name: "package", short: "p", help: ["(default) Creates an SPM package"]), + CommandOption.value(name: "template", help: ["Creates a project with a previously saved template"]) + ] + + public var help: [String] = ["Creates a new project"] + + public func run(using context: CommandContext) throws -> EventLoopFuture { + let newProject = context.console.loadingBar(title: "Generating Project") + newProject.start() + + let executable = try newExecutable(from: context) + let template = try newFromTemplate(using: context) + if !executable && !template { + try newPackage(from: context) + } + + newProject.finish() + + return context.container.eventLoop.newSucceededFuture(result: ()) + } + + func newExecutable(from context: CommandContext) throws -> Bool { + if let _ = context.options["executable"] { + let name = try context.argument("name") + let script = "mkdir \(name); cd \(name); swift package init --type=executable; ether clean-manifest" + _ = try context.console.backgroundExecute(program: "bash", arguments: ["-c", script]) + return true + } + return false + } + + func newFromTemplate(using context: CommandContext) throws -> Bool { + if let template = context.options["template"] { + let name = try context.argument("name") + let manager = FileManager.default + + if #available(OSX 10.12, *) { + let directoryName = manager.homeDirectoryForCurrentUser.absoluteString + let templatePath = String("\(directoryName)Library/Application Support/Ether/Templates/\(template)".dropFirst(7)) + let current = manager.currentDirectoryPath + _ = try context.console.backgroundExecuteRaw(program: "/bin/cp", arguments: ["-a", "\(templatePath)", "\(current)/\(name)"]) + } else { + fatalError("This command is not supported in macOS versions older then 10.12") + // throw EtherError.fail("This command is not supported in macOS versions older then 10.12") + } + return true + } + return false + } + + func newPackage(from context: CommandContext) throws { + let name = try context.argument("name") + let script = "mkdir \(name); cd \(name); swift package init; ether clean-manifest" + _ = try context.console.backgroundExecute(program: "bash", arguments: ["-c", script]) + } +} From 8880cd874ada70228b4ff665167d0952659c8a22 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Wed, 4 Apr 2018 18:26:51 -0500 Subject: [PATCH 09/66] Implemented Remove command signiture in Console 3 --- Sources/Ether/Remove.swift | 87 ++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 46 deletions(-) diff --git a/Sources/Ether/Remove.swift b/Sources/Ether/Remove.swift index 454b564..ba7ed99 100644 --- a/Sources/Ether/Remove.swift +++ b/Sources/Ether/Remove.swift @@ -1,51 +1,46 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. +// The MIT License (MIT) // -//import Helpers -//import Console -//import Foundation +// Copyright (c) 2017 Caleb Kleveter // -//public final class Remove: Command { -// public let id = "remove" -// -// public var help: [String] = [ -// "Removes and uninstalls a package" -// ] -// -// public var signature: [Argument] = [ -// Value(name: "name", help: [ -// "The name of the package that will be removed" -// ]), -// Option(name: "xcode", short: "x", help: [ -// "Regenerate the Xcode project after removing the package" -// ]) -// ] -// -// public let console: ConsoleProtocol -// -// public init(console: ConsoleProtocol) { -// self.console = console -// } -// +// 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. +// + +import Console +import Command +import Async + +public final class Remove: Command { + public var arguments: [CommandArgument] = [ + CommandArgument.argument(name: "name", help: ["The name of the package that will be removed"]) + ] + + public var options: [CommandOption] = [ + CommandOption.flag(name: "xcode", short: "x", help: ["Regenerate the Xcode project after removing the package"]) + ] + + public var help: [String] = ["Removes a package from the manifest and uninstalls it"] + + public func run(using context: CommandContext) throws -> EventLoopFuture { + return context.container.eventLoop.newSucceededFuture(result: ()) + } +} + // public func run(arguments: [String]) throws { // let removingProgressBar = console.loadingBar(title: "Removing Dependency") // removingProgressBar.start() From 0404822d95b98cb0118f4a055f943bf5e37deb8c Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Wed, 4 Apr 2018 18:31:49 -0500 Subject: [PATCH 10/66] Implemented Search command signiture in Console 3 --- Sources/Ether/Search.swift | 111 +++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 60 deletions(-) diff --git a/Sources/Ether/Search.swift b/Sources/Ether/Search.swift index 7967bd6..648d19e 100644 --- a/Sources/Ether/Search.swift +++ b/Sources/Ether/Search.swift @@ -1,65 +1,56 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. +// The MIT License (MIT) // -//import Helpers -//import Console -//import Foundation -//import Core +// Copyright (c) 2017 Caleb Kleveter // -//public final class Search: Command { -// public let id = "search" -// -// public let baseURL = "https://packagecatalog.com/api/search/" -// public let sort = "chart" -// public let results = "items" -// -// public var help: [String] = [ -// "Searches for availible packages." -// ] -// -// public var signature: [Argument] = [ -// Value(name: "name", help: [ -// "The name of the package to search for." -// ]), -// Option(name: "max-results", help: [ -// "The maximum number of results that will be returned.", -// "This defaults to 20." -// ]), -// Option(name: "sort", help: [ -// "The sorting method to use:", -// "moststarred (Most Starred)", -// "leaststarred (Least Starred)", -// "mostrecent (Most Recent)", -// "leastrecent (Least Recent)", -// "The default value is moststarred." -// ]) -// ] -// -// public let console: ConsoleProtocol -// public let client = PackageJSONFetcher() -// -// public init(console: ConsoleProtocol) { -// self.console = console -// } +// 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. + +import Console +import Command +import Async + +public final class Search: Command { + public var arguments: [CommandArgument] = [ + CommandArgument.argument(name: "name", help: ["The name of the package to search for."]) + ] + + public var options: [CommandOption] = [ + CommandOption.value(name: "max-results", default: "20", help: [ + "The maximum number of results that will be returned.", + "This defaults value 20." + ]), + CommandOption.value(name: "sort", default: "moststarred", help: [ + "The sorting method to use:", + "moststarred (Most Starred)", + "leaststarred (Least Starred)", + "mostrecent (Most Recent)", + "leastrecent (Least Recent)", + "The default value is moststarred." + ]) + ] + + public var help: [String] = ["Searches for availible packages."] + + public func run(using context: CommandContext) throws -> EventLoopFuture { + return context.container.eventLoop.newSucceededFuture(result: ()) + } +} + // // public func run(arguments: [String]) throws { // let searchingBar = console.loadingBar(title: "Searching") From 0a29a33fbb1f19a4c51a9a916cf64d3a1f8ab2bf Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Wed, 4 Apr 2018 18:35:59 -0500 Subject: [PATCH 11/66] Implemented Template command signiture in Console 3 --- Sources/Ether/Template.swift | 93 ++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 51 deletions(-) diff --git a/Sources/Ether/Template.swift b/Sources/Ether/Template.swift index 9f52167..285257d 100644 --- a/Sources/Ether/Template.swift +++ b/Sources/Ether/Template.swift @@ -1,57 +1,48 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. +// The MIT License (MIT) // -//// Path: ~/Library/Application\ Support/Ether +// Copyright (c) 2017 Caleb Kleveter // -//import Console -//import Foundation -//import Core -//import Helpers +// 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: // -//final public class Template: Command { -// public let id = "template" -// -// public let signature: [Argument] = [ -// Value(name: "template-name", help: [ -// "The name used to identify the template" -// ]), -// Option(name: "github", help: [ -// "Creates a GitHub repo and pushes the template to it (Un-implimented)" -// ]), -// Option(name: "remove", short: "r", help: [ -// "Deletes the template" -// ]) -// ] -// -// public let help: [String] = [ -// "Creates and stores a template for use as the starting point of a project." -// ] -// -// public let console: ConsoleProtocol -// -// public init(console: ConsoleProtocol) { -// self.console = console -// } -// +// 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. + +// Path: ~/Library/Application\ Support/Ether + +import Console +import Command +import Async + +public final class Template: Command { + public var arguments: [CommandArgument] = [ + CommandArgument.argument(name: "name", help: ["The name used to identify the template"]) + ] + + public var options: [CommandOption] = [ + CommandOption.flag(name: "remove", short: "r", help: ["Deletes the template"]) + // TODO: Add `github` flag to create remote repo and push. + ] + + public var help: [String] = ["Creates and stores a template for use as the starting point of a project."] + + public func run(using context: CommandContext) throws -> EventLoopFuture { + return context.container.eventLoop.newSucceededFuture(result: ()) + } +} + // public func run(arguments: [String]) throws { // let name = try value("template-name", from: arguments) // let useGitHub = arguments.option("github") != nil ? true : false From 67215c9191dcb4004f774cca8f545e66c2e60548 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Wed, 4 Apr 2018 18:40:29 -0500 Subject: [PATCH 12/66] Implemented Update command signiture in Console 3 --- Sources/Ether/Update.swift | 79 ++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/Sources/Ether/Update.swift b/Sources/Ether/Update.swift index 9fa9d4f..1947604 100644 --- a/Sources/Ether/Update.swift +++ b/Sources/Ether/Update.swift @@ -1,49 +1,44 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. +// The MIT License (MIT) // -//import Console +// Copyright (c) 2017 Caleb Kleveter // -//public final class Update: Command { -// public let id = "update" +// 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: // -// public let signature: [Argument] = [ -// Option(name: "self", short: "s", help: [ -// "Updates Ether" -// ]), -// Option(name: "xcode", short: "x", help: [ -// "Regenerate and open the Xcode project after update its packages" -// ]) -// ] -// -// public let help: [String] = [ -// "Updates your dependencies." -// ] -// -// public let console: ConsoleProtocol -// -// public init(console: ConsoleProtocol) { -// self.console = console -// } +// 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. + +import Console +import Command +import Async + +public final class Update: Command { + public var arguments: [CommandArgument] = [] + + public var options: [CommandOption] = [ + CommandOption.flag(name: "ether", short: "e", help: ["Updates Ether CLI"]), + CommandOption.flag(name: "xcode", short: "x", help: ["Regenerate and open the Xcode project after updating packages"]) + ] + + public var help: [String] = ["Updates a project's dependencies."] + + public func run(using context: CommandContext) throws -> EventLoopFuture { + return context.container.eventLoop.newSucceededFuture(result: ()) + } +} + // public func run(arguments: [String]) throws { // if let _ = arguments.option("self") { // let updateBar = console.loadingBar(title: "Updating Ether") From 43b0d555b91031f8c5a501e3eb8b0c26e820e28c Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Wed, 4 Apr 2018 18:43:36 -0500 Subject: [PATCH 13/66] Implemented VersionAll command signiture in Console 3 --- Sources/Ether/VersionAll.swift | 75 ++++++++++++++++------------------ 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/Sources/Ether/VersionAll.swift b/Sources/Ether/VersionAll.swift index f6aef6f..1b785e5 100644 --- a/Sources/Ether/VersionAll.swift +++ b/Sources/Ether/VersionAll.swift @@ -1,44 +1,41 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. +// The MIT License (MIT) // -//import Console -//import Foundation -//import Helpers +// Copyright (c) 2017 Caleb Kleveter // -//public final class VersionAll: Command { -// public let id = "all" -// -// public var help: [String] = [ -// "Outputs the name of each package installed and its version" -// ] -// -// public var signature: [Argument] = [] -// -// public let console: ConsoleProtocol -// -// public init(console: ConsoleProtocol) { -// self.console = console -// } -// +// 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. + +import Console +import Command +import Async + +public final class VersionAll: Command { + public var arguments: [CommandArgument] = [] + + public var options: [CommandOption] = [] + + public var help: [String] = ["Outputs the name of each package installed and its version"] + + public func run(using context: CommandContext) throws -> EventLoopFuture { + return context.container.eventLoop.newSucceededFuture(result: ()) + } +} + // public func run(arguments: [String]) throws { // let fetchingDataBar = console.loadingBar(title: "Getting Package Data") // fetchingDataBar.start() From 25cc787bde2684bcc1d23b12305f67e873e133c6 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Thu, 5 Apr 2018 07:50:40 -0500 Subject: [PATCH 14/66] Installed Manifest package --- Package.resolved | 17 +++++++++++++---- Package.swift | 5 +++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Package.resolved b/Package.resolved index b8b30af..229d56a 100644 --- a/Package.resolved +++ b/Package.resolved @@ -15,8 +15,17 @@ "repositoryURL": "https://github.com/vapor/core.git", "state": { "branch": null, - "revision": "70719b347f2ee7880776d5b03add924628eac3d2", - "version": "3.0.0-rc.2.5.2" + "revision": "5383e40f19d71da99e496afa9972c085abc2379d", + "version": "3.0.2" + } + }, + { + "package": "Manifest", + "repositoryURL": "https://github.com/Ether-CLI/Manifest.git", + "state": { + "branch": null, + "revision": "3722e0a7d47b914342b886a6e9b6c91b4d8ce943", + "version": "0.1.0" } }, { @@ -24,8 +33,8 @@ "repositoryURL": "https://github.com/vapor/service.git", "state": { "branch": null, - "revision": "02205a16a3f4714a08836529f5a868c2ce256719", - "version": "1.0.0-rc.2.2" + "revision": "281a70b69783891900be31a9e70051b6fe19e146", + "version": "1.0.0" } }, { diff --git a/Package.swift b/Package.swift index 1d22047..a802cea 100644 --- a/Package.swift +++ b/Package.swift @@ -6,12 +6,13 @@ let package = Package( name: "Ether", dependencies: [ .package(url: "https://github.com/vapor/console.git", from: "3.0.0-rc"), - .package(url: "https://github.com/vapor/core.git", from: "3.0.0-rc") + .package(url: "https://github.com/vapor/core.git", from: "3.0.0-rc"), + .package(url: "https://github.com/Ether-CLI/Manifest.git", from: "0.1.0") ], targets: [ .target(name: "GitHub", dependencies: ["Core"]), .target(name: "Helpers", dependencies: ["Core", "Console"]), - .target(name: "Ether", dependencies: ["Helpers", "Console", "Command"]), + .target(name: "Ether", dependencies: ["Helpers", "Console", "Command", "Manifest"]), .target(name: "Executable", dependencies: ["Ether", "Console"]) ] ) From fdbf2120cae185ead933787b117f41653242c921 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Thu, 5 Apr 2018 15:21:22 -0500 Subject: [PATCH 15/66] Updated Console version to 3.0.0 --- Package.resolved | 4 ++-- Package.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Package.resolved b/Package.resolved index 229d56a..9c1b203 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/vapor/console.git", "state": { "branch": null, - "revision": "273cf2ed1f4daba88a452494c342020171d8c7b8", - "version": "3.0.0-rc.2.2" + "revision": "038e30ec9004fb1915d14d964a3facc1ec5c80f4", + "version": "3.0.0" } }, { diff --git a/Package.swift b/Package.swift index a802cea..31f7745 100644 --- a/Package.swift +++ b/Package.swift @@ -5,8 +5,8 @@ import PackageDescription let package = Package( name: "Ether", dependencies: [ - .package(url: "https://github.com/vapor/console.git", from: "3.0.0-rc"), - .package(url: "https://github.com/vapor/core.git", from: "3.0.0-rc"), + .package(url: "https://github.com/vapor/console.git", from: "3.0.0"), + .package(url: "https://github.com/vapor/core.git", from: "3.0.0"), .package(url: "https://github.com/Ether-CLI/Manifest.git", from: "0.1.0") ], targets: [ From 908817fb03167152e8415cbb844e32cbf4592e53 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 6 Apr 2018 15:28:52 -0500 Subject: [PATCH 16/66] Replaced console.backgroundExecute with Process.execute --- Sources/Ether/New.swift | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Sources/Ether/New.swift b/Sources/Ether/New.swift index ae2e9cb..ec7aaa6 100644 --- a/Sources/Ether/New.swift +++ b/Sources/Ether/New.swift @@ -40,7 +40,7 @@ public final class New: Command { public func run(using context: CommandContext) throws -> EventLoopFuture { let newProject = context.console.loadingBar(title: "Generating Project") - newProject.start() + _ = newProject.start(on: context.container) let executable = try newExecutable(from: context) let template = try newFromTemplate(using: context) @@ -48,8 +48,7 @@ public final class New: Command { try newPackage(from: context) } - newProject.finish() - + newProject.succeed() return context.container.eventLoop.newSucceededFuture(result: ()) } @@ -57,7 +56,7 @@ public final class New: Command { if let _ = context.options["executable"] { let name = try context.argument("name") let script = "mkdir \(name); cd \(name); swift package init --type=executable; ether clean-manifest" - _ = try context.console.backgroundExecute(program: "bash", arguments: ["-c", script]) + _ = try Process.execute("bash", ["-c", script]) return true } return false @@ -72,7 +71,7 @@ public final class New: Command { let directoryName = manager.homeDirectoryForCurrentUser.absoluteString let templatePath = String("\(directoryName)Library/Application Support/Ether/Templates/\(template)".dropFirst(7)) let current = manager.currentDirectoryPath - _ = try context.console.backgroundExecuteRaw(program: "/bin/cp", arguments: ["-a", "\(templatePath)", "\(current)/\(name)"]) + _ = try Process.execute("cp", ["-a", "\(templatePath)", "\(current)/\(name)"]) } else { fatalError("This command is not supported in macOS versions older then 10.12") // throw EtherError.fail("This command is not supported in macOS versions older then 10.12") @@ -85,6 +84,6 @@ public final class New: Command { func newPackage(from context: CommandContext) throws { let name = try context.argument("name") let script = "mkdir \(name); cd \(name); swift package init; ether clean-manifest" - _ = try context.console.backgroundExecute(program: "bash", arguments: ["-c", script]) + _ = try Process.execute("bash", ["-c", script]) } } From 7122d3c7efa85e19e19052155a19ae62e9bc45ea Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 6 Apr 2018 15:29:30 -0500 Subject: [PATCH 17/66] Commented out EtherError anf global fail method --- Sources/Helpers/EtherError.swift | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Sources/Helpers/EtherError.swift b/Sources/Helpers/EtherError.swift index 89a7ac9..bc6417b 100644 --- a/Sources/Helpers/EtherError.swift +++ b/Sources/Helpers/EtherError.swift @@ -20,13 +20,13 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -import Console - -public enum EtherError: Error { - case fail(String) -} - -public func fail(bar: LoadingBar, with message: String) -> Error { - bar.fail() - return EtherError.fail(message) -} +//import Console +// +//public enum EtherError: Error { +// case fail(String) +//} +// +//public func fail(bar: LoadingBar, with message: String) -> Error { +// bar.fail() +// return EtherError.fail(message) +//} From 0f4fe22bb6af4c776f8c58160e473fc3c6f73175 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 6 Apr 2018 15:41:41 -0500 Subject: [PATCH 18/66] Finished updating Remove command --- Sources/Ether/Remove.swift | 75 ++++++++++++++------------------------ 1 file changed, 28 insertions(+), 47 deletions(-) diff --git a/Sources/Ether/Remove.swift b/Sources/Ether/Remove.swift index ba7ed99..ba6b79a 100644 --- a/Sources/Ether/Remove.swift +++ b/Sources/Ether/Remove.swift @@ -21,6 +21,7 @@ // SOFTWARE. // +import Manifest import Console import Command import Async @@ -37,53 +38,33 @@ public final class Remove: Command { public var help: [String] = ["Removes a package from the manifest and uninstalls it"] public func run(using context: CommandContext) throws -> EventLoopFuture { + let removing = context.console.loadingBar(title: "Removing Dependency") + _ = removing.start(on: context.container) + + let name = try context.argument("name") + let pinCount = try Manifest.current.resolved().object.pins.count + + guard let url = try Manifest.current.resolved().object.pins.filter({ $0.package == name }).first?.repositoryURL else { + fatalError() + } + try Manifest.current.dependency(withURL: url)?.delete() + + _ = try Process.execute("swift", ["package", "update"]) + _ = try Process.execute("swift", ["package", "resolve"]) + + let removed = try pinCount - Manifest.current.resolved().object.pins.count + removing.succeed() + + if context.options["xcode"] != nil { + let xcodeBar = context.console.loadingBar(title: "Generating Xcode Project") + _ = xcodeBar.start(on: context.container) + + _ = try Process.execute("swift", ["package", "generate-xcodeproj"]) + xcodeBar.succeed() + _ = try Process.execute("bash", ["-c", "open *.xcodeproj"]) + } + + context.console.print("📦 \(removed) packages removed") return context.container.eventLoop.newSucceededFuture(result: ()) } } - -// public func run(arguments: [String]) throws { -// let removingProgressBar = console.loadingBar(title: "Removing Dependency") -// removingProgressBar.start() -// -// let manager = FileManager.default -// let name = try value("name", from: arguments) -// let url = try Manifest.current.getPackageUrl(for: name) -// -// let regex = try NSRegularExpression(pattern: "(\\,?\\n *\\.package\\(url: *\"\(url)\", *)(.*?)(?=,?\n)", options: .caseInsensitive) -// let oldPins = try Manifest.current.getPins() -// -// let packageString = try Manifest.current.get() -// let mutableString = NSMutableString(string: packageString) -// -// if regex.matches(in: packageString, options: [], range: NSMakeRange(0, packageString.utf8.count)).count == 0 { -// throw fail(bar: removingProgressBar, with: "No packages matching the name passed in where found") -// } -// -// regex.replaceMatches(in: mutableString, options: [], range: NSMakeRange(0, mutableString.length), withTemplate: "") -// try mutableString.removeDependency(name) -// -// do { -// try String(mutableString).data(using: .utf8)?.write(to: URL(string: "file:\(manager.currentDirectoryPath)/Package.swift")!) -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) -// } catch let error { -// removingProgressBar.fail() -// throw error -// } -// -// let pins = try Manifest.current.getPins() -// let pinsCount = oldPins.count - pins.count -// -// removingProgressBar.finish() -// -// if let _ = arguments.options["xcode"] { -// let xcodeBar = console.loadingBar(title: "Generating Xcode Project") -// xcodeBar.start() -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "generate-xcodeproj"]) -// xcodeBar.finish() -// try console.execute(program: "/bin/sh", arguments: ["-c", "open *.xcodeproj"], input: nil, output: nil, error: nil) -// } -// -// console.output("📦 \(pinsCount) packages removed", style: .custom(.white), newLine: true) -// } -//} From 8ca99f3cfccc412f82ef44481fd3302f0cc03ac1 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 6 Apr 2018 15:47:40 -0500 Subject: [PATCH 19/66] Completed porting Template command --- Sources/Ether/Template.swift | 66 +++++++++++++++--------------------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/Sources/Ether/Template.swift b/Sources/Ether/Template.swift index 285257d..ad193ff 100644 --- a/Sources/Ether/Template.swift +++ b/Sources/Ether/Template.swift @@ -20,8 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -// Path: ~/Library/Application\ Support/Ether - +import Foundation import Console import Command import Async @@ -39,42 +38,33 @@ public final class Template: Command { public var help: [String] = ["Creates and stores a template for use as the starting point of a project."] public func run(using context: CommandContext) throws -> EventLoopFuture { + let name = try context.argument("name") + let removeTemplate = context.options["remove"] == nil ? false : true + let manager = FileManager.default + let barTitle = removeTemplate ? "Deleting Template" : "Saving Template" + + let temapletBar = context.console.loadingBar(title: barTitle) + _ = temapletBar.start(on: context.container) + + if #available(OSX 10.12, *) { + var isDir : ObjCBool = true + let directoryName = manager.homeDirectoryForCurrentUser.absoluteString + let defaultPath = String("\(directoryName)Library/Application Support/Ether/Templates".dropFirst(7)) + let directoryExists = manager.fileExists(atPath: "\(defaultPath)/\(name)", isDirectory: &isDir) + + if removeTemplate { + if !directoryExists { fatalError() } + _ = try Process.execute("rm", ["-rm", "\(defaultPath)/\(name)"]) + } else { + if directoryExists { fatalError() } + let current = manager.currentDirectoryPath + "/." + _ = try Process.execute("cp", ["-a", "\(current)", "\(defaultPath)/\(name)"]) + } + } else { + fatalError() + } + + temapletBar.succeed() return context.container.eventLoop.newSucceededFuture(result: ()) } } - -// public func run(arguments: [String]) throws { -// let name = try value("template-name", from: arguments) -// let useGitHub = arguments.option("github") != nil ? true : false -// let removeTemplate = arguments.option("remove") != nil ? true : false -// let manager = FileManager.default -// let loadingBarTitle = removeTemplate ? "Deleting Template" : "Saving Template" -// -// let savingBar = console.loadingBar(title: loadingBarTitle) -// savingBar.start() -// -// if #available(OSX 10.12, *) { -// var isDir : ObjCBool = true -// let directoryName = manager.homeDirectoryForCurrentUser.absoluteString -// let defaultPath = String("\(directoryName)Library/Application Support/Ether/Templates".dropFirst(7)) -// let directoryExists = manager.fileExists(atPath: "\(defaultPath)/\(name)", isDirectory: &isDir) -// -// if removeTemplate { -// if !directoryExists { throw fail(bar: savingBar, with: "No template with that name exists") } -// shell(command: "/bin/rm", "-rf", "\(defaultPath)/\(name)") -// } else { -// if directoryExists { throw fail(bar: savingBar, with: "A template with that name already exists") } -// let current = manager.currentDirectoryPath + "/." -// shell(command: "/bin/cp", "-a", "\(current)", "\(defaultPath)/\(name)") -// } -// } else { -// throw fail(bar: savingBar, with: "This command is not supported in macOS versions older then 10.12") -// } -// savingBar.finish() -// -// if useGitHub { -// console.output("The GitHub flag is currently not implimented", style: .warning, newLine: true) -// } -// -// } -//} From 3861c47511230194b2b9b657102c950c8842096e Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 6 Apr 2018 15:54:39 -0500 Subject: [PATCH 20/66] Completed porting Update command --- Sources/Ether/Update.swift | 120 ++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/Sources/Ether/Update.swift b/Sources/Ether/Update.swift index 1947604..c58e410 100644 --- a/Sources/Ether/Update.swift +++ b/Sources/Ether/Update.swift @@ -35,66 +35,66 @@ public final class Update: Command { public var help: [String] = ["Updates a project's dependencies."] public func run(using context: CommandContext) throws -> EventLoopFuture { + if context.options["ether"] != nil { + let updating = context.console.loadingBar(title: "Updating Ether") + _ = updating.start(on: context.container) + + _ = try Process.execute("bash", ["-c", "curl https://raw.githubusercontent.com/calebkleveter/Ether/master/install.sh | bash"]) + + updating.succeed() + self.printEtherArt(with: context.console) + } else { + context.console.output("This may take some time...", style: .info, newLine: true) + + let updating = context.console.loadingBar(title: "Updating Packages") + _ = updating.start(on: context.container) + + _ = try Process.execute("swift", ["package", "update"]) + _ = try Process.execute("swift", ["package", "resolve"]) + + updating.succeed() + + if context.options["xcode"] != nil { + let xcode = context.console.loadingBar(title: "Generating Xcode Project") + _ = xcode.start(on: context.container) + + _ = try Process.execute("swift", ["package", "generate-xcodeproj"]) + + xcode.succeed() + _ = try Process.execute("/bin/sh", ["-c", "open *.xcodeproj"]) + } + } + return context.container.eventLoop.newSucceededFuture(result: ()) } -} + + private func printEtherArt(with console: Console) { + let etherArt = """ + | • | + | • | + | • | + / \\ + / \\ + """ -// public func run(arguments: [String]) throws { -// if let _ = arguments.option("self") { -// let updateBar = console.loadingBar(title: "Updating Ether") -// updateBar.start() -// _ = try console.backgroundExecute(program: "/bin/sh", arguments: ["-c", "curl https://raw.githubusercontent.com/calebkleveter/Ether/master/install.sh | bash"]) -// updateBar.finish() -// self.printEtherArt() -// } else { -// console.output("This may take some time...", style: .info, newLine: true) -// -// let updateBar = console.loadingBar(title: "Updating Packages") -// updateBar.start() -// _ = try console.backgroundExecute(program: "rm", arguments: ["-rf", ".build"]) -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) -// _ = try console.backgroundExecute(program: "swift", arguments: ["build"]) -// updateBar.finish() -// -// if let _ = arguments.options["xcode"] { -// let xcodeBar = console.loadingBar(title: "Generating Xcode Project") -// xcodeBar.start() -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "generate-xcodeproj"]) -// xcodeBar.finish() -// try console.execute(program: "/bin/sh", arguments: ["-c", "open *.xcodeproj"], input: nil, output: nil, error: nil) -// } -// } -// } -// -// private func printEtherArt() { -// let etherArt = """ -// | • | -// | • | -// | • | -// / \\ -// / \\ -// """ -// -// let characterColors: [Character: ConsoleColor] = [ -// "•": .green -// ] -// -// for character in console.center(etherArt) { -// let style: ConsoleStyle -// -// if let color = characterColors[character] { -// style = .custom(color) -// } else { -// style = .plain -// } -// -// console.output("\(character)", style: style, newLine: false) -// } -// -// console.print() -// console.print() -// console.output(console.center("Thanks for Updating Ether!"), style: .plain, newLine: true) -// } -// -//} + let characterColors: [Character: ConsoleColor] = [ + "•": .green + ] + + for character in console.center(etherArt) { + let style: ConsoleStyle + + if let color = characterColors[character] { + style = ConsoleStyle(color: color) + } else { + style = .plain + } + + console.output("\(character)", style: style, newLine: false) + } + + console.print() + console.print() + console.output(console.center("Thanks for Updating Ether!"), style: .plain, newLine: true) + } +} From e9f8e383539e726f1eb41ca24e4ec9731b55714b Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 6 Apr 2018 15:59:54 -0500 Subject: [PATCH 21/66] Completed porting VersionAll command --- Sources/Ether/VersionAll.swift | 35 +++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/Sources/Ether/VersionAll.swift b/Sources/Ether/VersionAll.swift index 1b785e5..2c1e8e5 100644 --- a/Sources/Ether/VersionAll.swift +++ b/Sources/Ether/VersionAll.swift @@ -20,6 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +import Manifest import Console import Command import Async @@ -32,21 +33,25 @@ public final class VersionAll: Command { public var help: [String] = ["Outputs the name of each package installed and its version"] public func run(using context: CommandContext) throws -> EventLoopFuture { + context.console.output("Getting Package Data...", style: .success) + + let pins = try Manifest.current.resolved().object.pins + + pins.forEach { package in + context.console.output(package.package, style: .success, newLine: false) + let version: String + + if let number = package.state.version { + version = "v\(number)" + } else if let branch = package.state.branch { + version = branch + } else { + version = package.state.revision + } + + context.console.print(version) + } + return context.container.eventLoop.newSucceededFuture(result: ()) } } - -// public func run(arguments: [String]) throws { -// let fetchingDataBar = console.loadingBar(title: "Getting Package Data") -// fetchingDataBar.start() -// -// let pins = try Manifest.current.getPins() -// fetchingDataBar.finish() -// pins.forEach { package in -// console.output("\(package["package"] ?? "N/A" as AnyObject): ", style: .success, newLine: false) -// if let state = package["state"] as? [String: AnyObject] { -// console.output("v\(state["version"] ?? "N/A" as AnyObject)", style: .plain, newLine: true) -// } -// } -// } -//} From 0e2e5ec735551618f74a1e1aa39f607e4f632525 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 6 Apr 2018 16:01:07 -0500 Subject: [PATCH 22/66] Fixed typo in Search max-results flag help message --- Sources/Ether/Search.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Ether/Search.swift b/Sources/Ether/Search.swift index 648d19e..aaf6b01 100644 --- a/Sources/Ether/Search.swift +++ b/Sources/Ether/Search.swift @@ -32,7 +32,7 @@ public final class Search: Command { public var options: [CommandOption] = [ CommandOption.value(name: "max-results", default: "20", help: [ "The maximum number of results that will be returned.", - "This defaults value 20." + "This defaults to 20." ]), CommandOption.value(name: "sort", default: "moststarred", help: [ "The sorting method to use:", From 864d1e0ae1a544e9a208bf05fe124873af5193c1 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Sat, 7 Apr 2018 00:05:15 -0500 Subject: [PATCH 23/66] Ported FixInstall command to Console 3 --- Sources/Ether/FixInstall.swift | 103 ++++++++++++++------------------- 1 file changed, 45 insertions(+), 58 deletions(-) diff --git a/Sources/Ether/FixInstall.swift b/Sources/Ether/FixInstall.swift index f7be714..593d420 100644 --- a/Sources/Ether/FixInstall.swift +++ b/Sources/Ether/FixInstall.swift @@ -1,60 +1,47 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. +// The MIT License (MIT) // -//import Console +// Copyright (c) 2017 Caleb Kleveter // -//public class FixInstall: Command { -// public let id: String = "fix-install" -// -// public let signature: [Argument] = [ -// Option(name: "no-build", help: [ -// "Skips the rebuilding proccess after clearing the project cache" -// ]) -// ] -// -// public var help: [String] = [ -// "Fixes fetching errors that occur during package install" -// ] -// -// public let console: ConsoleProtocol -// -// public init(console: ConsoleProtocol) { -// self.console = console -// } -// -// public func run(arguments: [String]) throws { -// let fixBar = console.loadingBar(title: "Fixing Installation") -// -// console.output("This may take some time...", style: .info, newLine: true) -// fixBar.start() -// -// _ = try console.backgroundExecute(program: "rm", arguments: ["-rf", ".build"]) -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) -// -// if arguments.option("no-build") == nil { -// _ = try console.backgroundExecute(program: "swift", arguments: ["build"]) -// } -// -// fixBar.finish() -// } -//} +// 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. + +import Console +import Command +import Async + +public final class FixInstall: Command { + public var arguments: [CommandArgument] = [] + public var options: [CommandOption] = [] + + public var help: [String] = ["Fixes fetching errors that occur during package install"] + + public func run(using context: CommandContext) throws -> EventLoopFuture { + context.console.output("This may take some time...", style: .info) + + let fixing = context.console.loadingBar(title: "Fixing Instillation") + _ = fixing.start(on: context.container) + + _ = try Process.execute("rm", ["--rf", ".build"]) + _ = try Process.execute("swift", ["package", "update"]) + _ = try Process.execute("swift", ["package", "resolve"]) + + fixing.succeed() + + return context.container.eventLoop.newSucceededFuture(result: ()) + } +} From 2bd96d047acb87dfba1b1a4479279c371ff97ff6 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Sat, 7 Apr 2018 00:14:34 -0500 Subject: [PATCH 24/66] Replaced use of 'fatalError' with 'EtherError' --- Sources/Ether/New.swift | 4 ++-- Sources/Ether/Remove.swift | 3 ++- Sources/Ether/Template.swift | 7 ++++--- Sources/Helpers/EtherError.swift | 21 +++++++++++---------- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/Sources/Ether/New.swift b/Sources/Ether/New.swift index ec7aaa6..ce34e07 100644 --- a/Sources/Ether/New.swift +++ b/Sources/Ether/New.swift @@ -21,6 +21,7 @@ // SOFTWARE. import Foundation +import Helpers import Command import Console import Async @@ -73,8 +74,7 @@ public final class New: Command { let current = manager.currentDirectoryPath _ = try Process.execute("cp", ["-a", "\(templatePath)", "\(current)/\(name)"]) } else { - fatalError("This command is not supported in macOS versions older then 10.12") - // throw EtherError.fail("This command is not supported in macOS versions older then 10.12") + throw EtherError(identifier: "unsupportedOS", reason: "This command is not supported in macOS versions older then 10.12") } return true } diff --git a/Sources/Ether/Remove.swift b/Sources/Ether/Remove.swift index ba6b79a..f2cc8a4 100644 --- a/Sources/Ether/Remove.swift +++ b/Sources/Ether/Remove.swift @@ -22,6 +22,7 @@ // import Manifest +import Helpers import Console import Command import Async @@ -45,7 +46,7 @@ public final class Remove: Command { let pinCount = try Manifest.current.resolved().object.pins.count guard let url = try Manifest.current.resolved().object.pins.filter({ $0.package == name }).first?.repositoryURL else { - fatalError() + throw EtherError(identifier: "pinNotFound", reason: "No package was found with the name '\(name)'") } try Manifest.current.dependency(withURL: url)?.delete() diff --git a/Sources/Ether/Template.swift b/Sources/Ether/Template.swift index ad193ff..cc4e093 100644 --- a/Sources/Ether/Template.swift +++ b/Sources/Ether/Template.swift @@ -21,6 +21,7 @@ // SOFTWARE. import Foundation +import Helpers import Console import Command import Async @@ -53,15 +54,15 @@ public final class Template: Command { let directoryExists = manager.fileExists(atPath: "\(defaultPath)/\(name)", isDirectory: &isDir) if removeTemplate { - if !directoryExists { fatalError() } + if !directoryExists { throw EtherError(identifier: "templateNotFound", reason: "No template with the name '\(name)' was found") } _ = try Process.execute("rm", ["-rm", "\(defaultPath)/\(name)"]) } else { - if directoryExists { fatalError() } + if directoryExists { throw EtherError(identifier: "templateAlreadyExists", reason: "A template with the name '\(name)' was found") } let current = manager.currentDirectoryPath + "/." _ = try Process.execute("cp", ["-a", "\(current)", "\(defaultPath)/\(name)"]) } } else { - fatalError() + throw EtherError(identifier: "unsupportedOS", reason: "This command is not supported in macOS versions older then 10.12") } temapletBar.succeed() diff --git a/Sources/Helpers/EtherError.swift b/Sources/Helpers/EtherError.swift index bc6417b..53660fb 100644 --- a/Sources/Helpers/EtherError.swift +++ b/Sources/Helpers/EtherError.swift @@ -20,13 +20,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -//import Console -// -//public enum EtherError: Error { -// case fail(String) -//} -// -//public func fail(bar: LoadingBar, with message: String) -> Error { -// bar.fail() -// return EtherError.fail(message) -//} +import Debugging + +public struct EtherError: Error, Debuggable { + public let identifier: String + public let reason: String + + public init(identifier: String, reason: String) { + self.identifier = identifier + self.reason = reason + } +} From 1b73ed6adb3cc95510ef626a39c89499d776a5b6 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Sat, 7 Apr 2018 12:58:23 -0500 Subject: [PATCH 25/66] Updated Manifest version to 0.2.0 --- Package.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.resolved b/Package.resolved index 9c1b203..5425f81 100644 --- a/Package.resolved +++ b/Package.resolved @@ -24,8 +24,8 @@ "repositoryURL": "https://github.com/Ether-CLI/Manifest.git", "state": { "branch": null, - "revision": "3722e0a7d47b914342b886a6e9b6c91b4d8ce943", - "version": "0.1.0" + "revision": "bce7e8c16ce8a495654f785e838df94e269ac821", + "version": "0.2.0" } }, { From cae3997e69fe6d266de15cd3343d3c3bf97e9e39 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Sat, 7 Apr 2018 13:01:56 -0500 Subject: [PATCH 26/66] Deleted CleanManifest command and added Manifest.reset call the New command --- Sources/Ether/CleanManifest.swift | 42 ------------------------------- Sources/Ether/New.swift | 8 ++++-- 2 files changed, 6 insertions(+), 44 deletions(-) delete mode 100644 Sources/Ether/CleanManifest.swift diff --git a/Sources/Ether/CleanManifest.swift b/Sources/Ether/CleanManifest.swift deleted file mode 100644 index 5fd92d6..0000000 --- a/Sources/Ether/CleanManifest.swift +++ /dev/null @@ -1,42 +0,0 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. -// -//import Console -//import Helpers -// -//public class CleanManifest: Command { -// public let id: String = "clean-manifest" -// public let console: ConsoleProtocol -// -// public let help: [String] = [ -// "This command is for internal purposes only" -// ] -// -// public init(console: ConsoleProtocol) { -// self.console = console -// } -// -// public func run(arguments: [String]) throws { -// console.output("Cleaning Manifest...", style: .info, newLine: true) -// try Manifest.current.clean() -// } -//} diff --git a/Sources/Ether/New.swift b/Sources/Ether/New.swift index ce34e07..f83703e 100644 --- a/Sources/Ether/New.swift +++ b/Sources/Ether/New.swift @@ -21,6 +21,7 @@ // SOFTWARE. import Foundation +import Manifest import Helpers import Command import Console @@ -56,8 +57,10 @@ public final class New: Command { func newExecutable(from context: CommandContext) throws -> Bool { if let _ = context.options["executable"] { let name = try context.argument("name") - let script = "mkdir \(name); cd \(name); swift package init --type=executable; ether clean-manifest" + let script = "mkdir \(name); cd \(name); swift package init --type=executable" _ = try Process.execute("bash", ["-c", script]) + + try Manifest.current.reset() return true } return false @@ -83,7 +86,8 @@ public final class New: Command { func newPackage(from context: CommandContext) throws { let name = try context.argument("name") - let script = "mkdir \(name); cd \(name); swift package init; ether clean-manifest" + let script = "mkdir \(name); cd \(name); swift package init" _ = try Process.execute("bash", ["-c", script]) + try Manifest.current.reset() } } From a849b01c213f1627f2706a9986b71570a09b9704 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Sat, 7 Apr 2018 13:03:46 -0500 Subject: [PATCH 27/66] Removed all Async imports --- Sources/Ether/FixInstall.swift | 1 - Sources/Ether/Install.swift | 1 - Sources/Ether/New.swift | 1 - Sources/Ether/Remove.swift | 1 - Sources/Ether/Search.swift | 1 - Sources/Ether/Template.swift | 1 - Sources/Ether/Update.swift | 1 - Sources/Ether/VersionAll.swift | 1 - 8 files changed, 8 deletions(-) diff --git a/Sources/Ether/FixInstall.swift b/Sources/Ether/FixInstall.swift index 593d420..43dfc5b 100644 --- a/Sources/Ether/FixInstall.swift +++ b/Sources/Ether/FixInstall.swift @@ -22,7 +22,6 @@ import Console import Command -import Async public final class FixInstall: Command { public var arguments: [CommandArgument] = [] diff --git a/Sources/Ether/Install.swift b/Sources/Ether/Install.swift index e22edfe..def5ebd 100644 --- a/Sources/Ether/Install.swift +++ b/Sources/Ether/Install.swift @@ -21,7 +21,6 @@ // SOFTWARE. import Command -import Async public final class Install: Command { public var arguments: [CommandArgument] = [ diff --git a/Sources/Ether/New.swift b/Sources/Ether/New.swift index f83703e..1ce6a8c 100644 --- a/Sources/Ether/New.swift +++ b/Sources/Ether/New.swift @@ -25,7 +25,6 @@ import Manifest import Helpers import Command import Console -import Async public final class New: Command { public var arguments: [CommandArgument] = [ diff --git a/Sources/Ether/Remove.swift b/Sources/Ether/Remove.swift index f2cc8a4..de20562 100644 --- a/Sources/Ether/Remove.swift +++ b/Sources/Ether/Remove.swift @@ -25,7 +25,6 @@ import Manifest import Helpers import Console import Command -import Async public final class Remove: Command { public var arguments: [CommandArgument] = [ diff --git a/Sources/Ether/Search.swift b/Sources/Ether/Search.swift index aaf6b01..7127836 100644 --- a/Sources/Ether/Search.swift +++ b/Sources/Ether/Search.swift @@ -22,7 +22,6 @@ import Console import Command -import Async public final class Search: Command { public var arguments: [CommandArgument] = [ diff --git a/Sources/Ether/Template.swift b/Sources/Ether/Template.swift index cc4e093..569ba3d 100644 --- a/Sources/Ether/Template.swift +++ b/Sources/Ether/Template.swift @@ -24,7 +24,6 @@ import Foundation import Helpers import Console import Command -import Async public final class Template: Command { public var arguments: [CommandArgument] = [ diff --git a/Sources/Ether/Update.swift b/Sources/Ether/Update.swift index c58e410..6d4d6c4 100644 --- a/Sources/Ether/Update.swift +++ b/Sources/Ether/Update.swift @@ -22,7 +22,6 @@ import Console import Command -import Async public final class Update: Command { public var arguments: [CommandArgument] = [] diff --git a/Sources/Ether/VersionAll.swift b/Sources/Ether/VersionAll.swift index 2c1e8e5..5a9f60e 100644 --- a/Sources/Ether/VersionAll.swift +++ b/Sources/Ether/VersionAll.swift @@ -23,7 +23,6 @@ import Manifest import Console import Command -import Async public final class VersionAll: Command { public var arguments: [CommandArgument] = [] From 2ea6ee534e6bdc84552c4e4c4c7152197e9f9415 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Sat, 7 Apr 2018 13:07:45 -0500 Subject: [PATCH 28/66] Removed all Console imports --- Sources/Ether/FixInstall.swift | 1 - Sources/Ether/New.swift | 1 - Sources/Ether/Remove.swift | 2 -- Sources/Ether/Search.swift | 1 - Sources/Ether/Template.swift | 1 - Sources/Ether/Update.swift | 1 - Sources/Ether/VersionAll.swift | 1 - 7 files changed, 8 deletions(-) diff --git a/Sources/Ether/FixInstall.swift b/Sources/Ether/FixInstall.swift index 43dfc5b..7a95f62 100644 --- a/Sources/Ether/FixInstall.swift +++ b/Sources/Ether/FixInstall.swift @@ -20,7 +20,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -import Console import Command public final class FixInstall: Command { diff --git a/Sources/Ether/New.swift b/Sources/Ether/New.swift index 1ce6a8c..1b4519b 100644 --- a/Sources/Ether/New.swift +++ b/Sources/Ether/New.swift @@ -24,7 +24,6 @@ import Foundation import Manifest import Helpers import Command -import Console public final class New: Command { public var arguments: [CommandArgument] = [ diff --git a/Sources/Ether/Remove.swift b/Sources/Ether/Remove.swift index de20562..283d8d2 100644 --- a/Sources/Ether/Remove.swift +++ b/Sources/Ether/Remove.swift @@ -19,11 +19,9 @@ // 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. -// import Manifest import Helpers -import Console import Command public final class Remove: Command { diff --git a/Sources/Ether/Search.swift b/Sources/Ether/Search.swift index 7127836..a966ac6 100644 --- a/Sources/Ether/Search.swift +++ b/Sources/Ether/Search.swift @@ -20,7 +20,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -import Console import Command public final class Search: Command { diff --git a/Sources/Ether/Template.swift b/Sources/Ether/Template.swift index 569ba3d..72535a9 100644 --- a/Sources/Ether/Template.swift +++ b/Sources/Ether/Template.swift @@ -22,7 +22,6 @@ import Foundation import Helpers -import Console import Command public final class Template: Command { diff --git a/Sources/Ether/Update.swift b/Sources/Ether/Update.swift index 6d4d6c4..9649bf7 100644 --- a/Sources/Ether/Update.swift +++ b/Sources/Ether/Update.swift @@ -20,7 +20,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -import Console import Command public final class Update: Command { diff --git a/Sources/Ether/VersionAll.swift b/Sources/Ether/VersionAll.swift index 5a9f60e..c1ed40f 100644 --- a/Sources/Ether/VersionAll.swift +++ b/Sources/Ether/VersionAll.swift @@ -21,7 +21,6 @@ // SOFTWARE. import Manifest -import Console import Command public final class VersionAll: Command { From 85132cacefa66a3df6b5f94fabdfe364f006d2d9 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Sat, 7 Apr 2018 13:14:34 -0500 Subject: [PATCH 29/66] Ported VersionLatest command signiture to Console 3 API --- Sources/Ether/VersionLatest.swift | 80 ++++++++++++++----------------- 1 file changed, 36 insertions(+), 44 deletions(-) diff --git a/Sources/Ether/VersionLatest.swift b/Sources/Ether/VersionLatest.swift index 86d9ddd..8e34399 100644 --- a/Sources/Ether/VersionLatest.swift +++ b/Sources/Ether/VersionLatest.swift @@ -1,53 +1,45 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. +// The MIT License (MIT) // -//// REGEX: \\.Package\\(url\\:\\s?\\\"https\\:\\/\\/github\\.com([\\d\\w\\:\\/\\.\\@\\-]+)\\.git\\\"\\,([\\d\\w\\s\\:])+\\)\\,? +// Copyright (c) 2017 Caleb Kleveter // -//import Console -//import Helpers -//import Foundation -//import Core +// 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: // -//public final class VersionLatest: Command { +// 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. + +import Helpers +import Command + +public final class VersionLatest: Command { + public var arguments: [CommandArgument] = [] + + public var options: [CommandOption] = [ + CommandOption.flag(name: "xcode", short: "x", help: ["Regenerate Xcode project after updating package versions"]) + ] + + public var help: [String] = ["Updates all packeges to the latest version"] + + public func run(using context: CommandContext) throws -> EventLoopFuture { + return context.container.eventLoop.newSucceededFuture(result: ()) + } +} + // public let id = "latest" // public let baseURL = "https://packagecatalog.com/data/package" // -// public var help: [String] = [ -// "Updates all packeges to the latest version" -// ] -// -// public var signature: [Argument] = [ -// Option(name: "xcode", short: "x", help: [ -// "Regenerate Xcode project after updating package versions" -// ]) -// ] -// -// public let console: ConsoleProtocol -// public let client = PackageJSONFetcher() -// -// public init(console: ConsoleProtocol) { -// self.console = console -// } -// // public func run(arguments: [String]) throws { // let updateBar = console.loadingBar(title: "Updating Package Versions") // updateBar.start() From 669da3ab6292b0b8d706adb7fba6ecd487f0c9c5 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Sat, 7 Apr 2018 14:49:42 -0500 Subject: [PATCH 30/66] Ported VersionSet command signiture to Console 3 --- Sources/Ether/VersionSet.swift | 113 ++++++++++++++------------------- 1 file changed, 46 insertions(+), 67 deletions(-) diff --git a/Sources/Ether/VersionSet.swift b/Sources/Ether/VersionSet.swift index f9e040e..e5a0ca6 100644 --- a/Sources/Ether/VersionSet.swift +++ b/Sources/Ether/VersionSet.swift @@ -1,72 +1,51 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. +// The MIT License (MIT) // -//import Console -//import Helpers -//import Foundation +// Copyright (c) 2017 Caleb Kleveter // -//public final class VersonSet: Command { -// public let id: String = "set" -// -// public var signature: [Argument] = [ -// Value(name: "name", help: [ -// "The name of the package to change the version for" -// ]), -// Value(name: "version", help: [ -// "The value for the new version. The format varies depending on the version type used" -// ]), -// Option(name: "xcode", short: "x", help: [ -// "Regenerate the Xcode project after updating a package's version" -// ]), -// Option(name: "from", short: "f", help: [ -// "Sets the dependency version argument to `from: VERSION`" -// ]), -// Option(name: "up-to-next-major", short: "u", help: [ -// "Sets the dependency version argument to `.upToNextMinor(from: \"VERSION\")`" -// ]), -// Option(name: "exact", short: "e", help: [ -// "(Default) Sets the dependency version argument to `.exact(\"VERSION\")`" -// ]), -// Option(name: "range", short: "r", help: [ -// "Sets the dependency version argument to `VERSION`" -// ]), -// Option(name: "branch", short: "b", help: [ -// "Sets the dependency version argument to `.branch(\"VERSION\")`" -// ]), -// Option(name: "revision", help: [ -// "Sets the dependency version argument to `.revision(\"VERSION\")`" -// ]) -// ] -// -// public var help: [String] = [ -// "Changes the version of a single dependency" -// ] -// -// public let console: ConsoleProtocol -// -// public init(console: ConsoleProtocol) { -// self.console = console -// } -// +// 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. + +import Command +import Helpers + +public final class VersionSet: Command { + public var arguments: [CommandArgument] = [ + CommandArgument.argument(name: "name", help: ["The name of the package to change the version for"]), + CommandArgument.argument(name: "version", help: ["The version to set the specified package to. The format varies depending on the version type used"]) + ] + + public var options: [CommandOption] = [ + CommandOption.flag(name: "from", short: "f", help: ["(default) Sets the dependency version argument to `from: VERSION`"]), + CommandOption.flag(name: "up-to-next-major", short: "u", help: ["Sets the dependency version argument to `.upToNextMinor(from: \"VERSION\")`"]), + CommandOption.flag(name: "exact", short: "e", help: ["Sets the dependency version argument to `.exact(\"VERSION\")`"]), + CommandOption.flag(name: "range", short: "r", help: ["Sets the dependency version argument to `VERSION`"]), + CommandOption.flag(name: "branch", short: "b", help: ["Sets the dependency version argument to `.branch(\"VERSION\")`"]), + CommandOption.flag(name: "revision", help: ["Sets the dependency version argument to `.revision(\"VERSION\")`"]), + CommandOption.flag(name: "xcode", short: "x", help: ["Regenerate the Xcode project after updating a package's version"]) + ] + + public var help: [String] = ["Changes the version of a single dependency"] + + public func run(using context: CommandContext) throws -> EventLoopFuture { + return context.container.eventLoop.newSucceededFuture(result: ()) + } +} + // public func run(arguments: [String]) throws { // let updateBar = console.loadingBar(title: "Updating Package Version") // updateBar.start() From fcfb486632df966d0ea525722b507f4881faefb2 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Sat, 7 Apr 2018 15:06:45 -0500 Subject: [PATCH 31/66] Ported VersionSet.versionOption method to use Manifest and Console 3 APIs --- Sources/Ether/VersionSet.swift | 46 ++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/Sources/Ether/VersionSet.swift b/Sources/Ether/VersionSet.swift index e5a0ca6..0db06b0 100644 --- a/Sources/Ether/VersionSet.swift +++ b/Sources/Ether/VersionSet.swift @@ -20,6 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +import Manifest import Command import Helpers @@ -44,8 +45,36 @@ public final class VersionSet: Command { public func run(using context: CommandContext) throws -> EventLoopFuture { return context.container.eventLoop.newSucceededFuture(result: ()) } -} + private func version(from options: [String: String], with version: String)throws -> DependencyVersionType { + if options["exact"] != nil { + return .exact(version) + + } else if options["up-to-next-major"] != nil { + return .upToNextMajor(version) + + } else if options["branch"] != nil { + return .branch(version) + + } else if options["revision"] != nil { + return .revision(version) + + } else if options["range"] != nil { + let pattern = try NSRegularExpression(pattern: "(.*?)(\\.\\.(?:\\.|<))(.*)", options: []) + guard let match = pattern.firstMatch(in: version, options: [], range: version.range) else { + throw EtherError(identifier: "badVersionStructure", reason: "The '--range' flag was passed in, but the version is not structured as a range") + } + let open = version.substring(at: match.range(at: 1))! + let `operator` = version.substring(at: match.range(at: 2))! + let close = version.substring(at: match.range(at: 3))! + + return .range("\"\(open)\"\(`operator`)\"\(close)\"") + } + + return .from(version) + } +} + // public func run(arguments: [String]) throws { // let updateBar = console.loadingBar(title: "Updating Package Version") // updateBar.start() @@ -78,19 +107,4 @@ public final class VersionSet: Command { // // console.output("\(package) version was updated", style: .plain, newLine: true) // } -// -// private func versionOption(from arguments: [String], with version: String) -> String { -// if arguments.option("from") != nil { -// return "from: \"\(version)\"" -// } else if arguments.option("up-to-next-major") != nil { -// return ".upToNextMajor(from: \"\(version)\")" -// } else if arguments.option("range") != nil { -// return "\"\(version.dropLast(8))\"\(String(version.dropFirst(5)).dropLast(5))\"\(version.dropFirst(8))\"" -// } else if arguments.option("branch") != nil { -// return ".branch(\"\(version)\")" -// } else if arguments.option("revision") != nil { -// return ".revision(\"\(version)\")" -// } -// return ".exact(\"\(version)\")" -// } //} From af8c8862223488c6b0fe4bbc7b2eff0a69fe2b85 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Sat, 5 May 2018 18:03:26 -0500 Subject: [PATCH 32/66] Deleted GitHub target --- Package.swift | 1 - Sources/GitHub/API.swift | 27 --------------------------- 2 files changed, 28 deletions(-) delete mode 100644 Sources/GitHub/API.swift diff --git a/Package.swift b/Package.swift index 31f7745..622dcbb 100644 --- a/Package.swift +++ b/Package.swift @@ -10,7 +10,6 @@ let package = Package( .package(url: "https://github.com/Ether-CLI/Manifest.git", from: "0.1.0") ], targets: [ - .target(name: "GitHub", dependencies: ["Core"]), .target(name: "Helpers", dependencies: ["Core", "Console"]), .target(name: "Ether", dependencies: ["Helpers", "Console", "Command", "Manifest"]), .target(name: "Executable", dependencies: ["Ether", "Console"]) diff --git a/Sources/GitHub/API.swift b/Sources/GitHub/API.swift deleted file mode 100644 index 88e6397..0000000 --- a/Sources/GitHub/API.swift +++ /dev/null @@ -1,27 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2017 Caleb Kleveter -// -// 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. - -import Foundation - -final class GitHub { - -} From 6dd52c3e4a214bd1ed25251195eec9ff6b17088b Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Sat, 5 May 2018 18:03:45 -0500 Subject: [PATCH 33/66] swift package update --- Package.resolved | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Package.resolved b/Package.resolved index 5425f81..3355d87 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/vapor/console.git", "state": { "branch": null, - "revision": "038e30ec9004fb1915d14d964a3facc1ec5c80f4", - "version": "3.0.0" + "revision": "5b9796d39f201b3dd06800437abd9d774a455e57", + "version": "3.0.2" } }, { @@ -15,8 +15,8 @@ "repositoryURL": "https://github.com/vapor/core.git", "state": { "branch": null, - "revision": "5383e40f19d71da99e496afa9972c085abc2379d", - "version": "3.0.2" + "revision": "efe79e4f59445b661ba7e6511c2a0b80645c2e72", + "version": "3.1.6" } }, { @@ -24,8 +24,8 @@ "repositoryURL": "https://github.com/Ether-CLI/Manifest.git", "state": { "branch": null, - "revision": "bce7e8c16ce8a495654f785e838df94e269ac821", - "version": "0.2.0" + "revision": "6e1369ea6224118e1e07bcaddfac1af30f960486", + "version": "0.4.2" } }, { @@ -42,8 +42,8 @@ "repositoryURL": "https://github.com/apple/swift-nio.git", "state": { "branch": null, - "revision": "a0b7f646fba61402da384b3202f54c27debb5e13", - "version": "1.3.1" + "revision": "a5db2a67515ad2b490ac5646db204a5edf939f47", + "version": "1.6.1" } }, { From 41bc42fd1f8f01b599792f5c8479e1ec062762e7 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Wed, 9 May 2018 17:06:37 -0500 Subject: [PATCH 34/66] Added Core package to Ether target; Ported Configuration command to Console 3 API --- Package.swift | 2 +- Sources/Ether/Configuration.swift | 236 +++++++++--------------------- 2 files changed, 71 insertions(+), 167 deletions(-) diff --git a/Package.swift b/Package.swift index 622dcbb..69c91f1 100644 --- a/Package.swift +++ b/Package.swift @@ -11,7 +11,7 @@ let package = Package( ], targets: [ .target(name: "Helpers", dependencies: ["Core", "Console"]), - .target(name: "Ether", dependencies: ["Helpers", "Console", "Command", "Manifest"]), + .target(name: "Ether", dependencies: ["Helpers", "Console", "Command", "Manifest", "Core"]), .target(name: "Executable", dependencies: ["Ether", "Console"]) ] ) diff --git a/Sources/Ether/Configuration.swift b/Sources/Ether/Configuration.swift index 9e14364..809e549 100644 --- a/Sources/Ether/Configuration.swift +++ b/Sources/Ether/Configuration.swift @@ -1,170 +1,74 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. +// The MIT License (MIT) // -//import Foundation -//import Console -//import Helpers -//import JSON +// Copyright (c) 2017 Caleb Kleveter // -//public class Configuration: Command { -// public let id: String = "config" -// public let configPath = "/Library/Application Support/Ether/config.json" -// -// public let signature: [Argument] = [ -// Value(name: "key", help: [ -// "The configuration JSON key to set" -// ]), -// Value(name: "value", help: [ -// "The new value for the key passed in" -// ]) -// ] -// -// public let help: [String] = [ -// "Configure custom actions to occure when a command is run", -// "Run `config help` to get information on expected data for the command options" -// ] -// -// public let console: ConsoleProtocol -// -// public init(console: ConsoleProtocol) { -// self.console = console -// } -// -// public func run(arguments: [String]) throws { -// let setBar = console.loadingBar(title: "Setting Configuration Key") -// setBar.start() -// -// let fileManager = FileManager.default -// let key = try value("key", from: arguments) -// let val: String -// -// do { -// val = try value("value", from: arguments) -// } catch { -// if key == "help" { printHelp() } -// return -// } -// -// guard let jsonPath = ConfigurationKey.getKey(from: key)?.jsonPath else { -// throw fail(bar: setBar, with: "Unable to get JSON path for specified key") -// } -// guard let configURL = URL(string: "file:\(fileManager.currentDirectoryPath)\(configPath)") else { -// throw fail(bar: setBar, with: "Unable to create path to config file") -// } -// -// let jsonData = try Data(contentsOf: configURL).makeBytes() -// var json = try JSON(bytes: jsonData) -// try self.set(jsonPath, with: val, in: &json) -// -// try Data(bytes: json.makeBytes()).write(to: configURL) -// -// setBar.finish() -// } -// -// fileprivate func printHelp() { -// let help = """ -// Below are the keys, values, and expected types for the configuration JSON. +// 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: // -// id | key | value-type | description -// ---+----------------+------------+------------------------------------------------------------- -// 0 | use-git | Bool | Wheather to run git commands when a project is written to -// 1 | install-commit | String | The message to use when committing after an installation -// 2 | remove-commit | String | The message to use when committing after a package removal -// 3 | latest-commit | String | The message to use when all packages are updated to their -// | | | latest versions -// 4 | new-commit | String | The message to use when committing a newly generated project +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. // -// When a commit is made, there are variables that can be replaced for more specific messages. -// Below are the variables, their values, and the config ID that they belong to: -// -// id | var | description -// ---+-----+-------------------- -// 1 | $0 | The package name -// 1 | $1 | The package version -// 2 | $0 | The package name -// 4 | $0 | The project name -// 4 | $1 | The package type -// """ -// console.output(help, style: .plain, newLine: true) -// } -// -// fileprivate func set(_ path: [String], with val: Any?, `in` json: inout JSON)throws { -// var jsons: [(key: String, json: JSON)] = [] -// var top: JSON = JSON() -// var sub: JSON = JSON() -// -// if path.count < 1 { return } -// for key in path { -// try jsons.append((key: key, json: json.get(key))) -// } -// if jsons.count == 0 { return } -// else if jsons.count == 1 { -// top = jsons[0].json -// try top.set(path[0], val) -// json = top -// return -// } -// -// for index in Array(0...jsons.count-1).reversed() { -// sub = jsons[index].json -// -// if index == jsons.count-1 { -// // Force-unwrapping always succedes because we tested for the path count earlier. -// try sub.set(path.last!, val) -// } else if index > 0 { -// top = jsons[index].json -// try top.set(jsons[index].key, sub) -// } else { -// json = top -// } -// } -// } -//} -// -//fileprivate enum ConfigurationKey { -// case useGit -// case gitInstallMessage -// case gitRemoveMessage -// case gitLatestMessage -// case gitNewMessage -// -// var jsonPath: [String] { -// switch self { -// case .useGit: return ["git", "use"] -// case .gitInstallMessage: return ["git", "commit-messages", "install"] -// case .gitRemoveMessage: return ["git", "commit-message", "remove"] -// case .gitLatestMessage: return ["git", "commit-message", "version-latest"] -// case .gitNewMessage: return ["git", "commit-message", "new"] -// } -// } -// -// static func getKey(from string: String) -> ConfigurationKey? { -// switch string.lowercased() { -// case "use-git": return .useGit -// case "install-commit": return .gitInstallMessage -// case "remove-commit": return .gitRemoveMessage -// case "latest-commit": return .gitLatestMessage -// case "new-commit": return .gitNewMessage -// default: return nil -// } -// } -//} +// 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. + +import Foundation +import Console +import Command +import Helpers +import Core + +public class Configuration: Command { + public static let configPath = "/Library/Application Support/Ether/config.json" + + public var arguments: [CommandArgument] = [ + CommandArgument.argument(name: "key", help: ["The configuration JSON key to set"]), + CommandArgument.argument(name: "value", help: ["The new value for the key passed in"]) + ] + + public var options: [CommandOption] = [] + + public var help: [String] = ["Configure custom actions to occure when a command is run"] + + public func run(using context: CommandContext) throws -> EventLoopFuture { + let setter = context.console.loadingBar(title: "Setting Configuration Ket") + _ = setter.start(on: context.container) + + let key = try context.argument("key") + let value = try context.argument("value") + + var configuration = try Configuration.get() + guard let property = Config.properties[key] else { + throw EtherError(identifier: "noSettingWithName", reason: "No configuration setting found with name '\(key)'") + } + + configuration[keyPath: property] = value + try JSONEncoder().encode(configuration).write(to: URL(string: "file:\(Configuration.configPath)")!) + + setter.succeed() + return context.container.eventLoop.newSucceededFuture(result: ()) + } + + public static func get()throws -> Config { + guard let configuration = FileManager.default.contents(atPath: "file:\(configPath)") else { + throw EtherError(identifier: "fileNotFound", reason: "File at path '\(configPath)' not found") + } + return try JSONDecoder().decode(Config.self, from: configuration) + } +} + +public struct Config: Codable, Reflectable { + public var accessToken: String + + static let properties: [String: WritableKeyPath] = [ + "access-token": \.accessToken + ] +} From 6cd580da421ae4af79857cd51b70f541415ffbc0 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Wed, 9 May 2018 17:15:29 -0500 Subject: [PATCH 35/66] Installed Vapor package --- Package.resolved | 108 +++++++++++++++++++++++++++++++++++++++++++++++ Package.swift | 3 +- 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/Package.resolved b/Package.resolved index 3355d87..1142e80 100644 --- a/Package.resolved +++ b/Package.resolved @@ -19,6 +19,33 @@ "version": "3.1.6" } }, + { + "package": "Crypto", + "repositoryURL": "https://github.com/vapor/crypto.git", + "state": { + "branch": null, + "revision": "1b8c2ba5a42f1adf2aa812204678d8b16466fa59", + "version": "3.1.2" + } + }, + { + "package": "DatabaseKit", + "repositoryURL": "https://github.com/vapor/database-kit.git", + "state": { + "branch": null, + "revision": "0db303439e5ef8b6df50a2b6c4029edddee90cb0", + "version": "1.0.1" + } + }, + { + "package": "HTTP", + "repositoryURL": "https://github.com/vapor/http.git", + "state": { + "branch": null, + "revision": "9246340ae4c5310627099349fc74785267b55607", + "version": "3.0.5" + } + }, { "package": "Manifest", "repositoryURL": "https://github.com/Ether-CLI/Manifest.git", @@ -28,6 +55,24 @@ "version": "0.4.2" } }, + { + "package": "Multipart", + "repositoryURL": "https://github.com/vapor/multipart.git", + "state": { + "branch": null, + "revision": "7778dcb62f3efa845e8e2808937bb347575ba7ce", + "version": "3.0.1" + } + }, + { + "package": "Routing", + "repositoryURL": "https://github.com/vapor/routing.git", + "state": { + "branch": null, + "revision": "3219e328491b0853b8554c5a694add344d2c6cfb", + "version": "3.0.1" + } + }, { "package": "Service", "repositoryURL": "https://github.com/vapor/service.git", @@ -46,6 +91,24 @@ "version": "1.6.1" } }, + { + "package": "swift-nio-ssl", + "repositoryURL": "https://github.com/apple/swift-nio-ssl.git", + "state": { + "branch": null, + "revision": "38955a5f806a952daf2b16fbfe9aa529749cf1dd", + "version": "1.1.0" + } + }, + { + "package": "swift-nio-ssl-support", + "repositoryURL": "https://github.com/apple/swift-nio-ssl-support.git", + "state": { + "branch": null, + "revision": "c02eec4e0e6d351cd092938cf44195a8e669f555", + "version": "1.0.0" + } + }, { "package": "swift-nio-zlib-support", "repositoryURL": "https://github.com/apple/swift-nio-zlib-support.git", @@ -54,6 +117,51 @@ "revision": "37760e9a52030bb9011972c5213c3350fa9d41fd", "version": "1.0.0" } + }, + { + "package": "TemplateKit", + "repositoryURL": "https://github.com/vapor/template-kit.git", + "state": { + "branch": null, + "revision": "43b57b5861d5181b906ac6411d28645e980bb638", + "version": "1.0.1" + } + }, + { + "package": "URLEncodedForm", + "repositoryURL": "https://github.com/vapor/url-encoded-form.git", + "state": { + "branch": null, + "revision": "57cf7fb9c1a1014c50bc05123684a9139ad44127", + "version": "1.0.3" + } + }, + { + "package": "Validation", + "repositoryURL": "https://github.com/vapor/validation.git", + "state": { + "branch": null, + "revision": "ab6c5a352d97c8687b91ed4963aef8e7cfe0795b", + "version": "2.0.0" + } + }, + { + "package": "Vapor", + "repositoryURL": "https://github.com/vapor/vapor.git", + "state": { + "branch": null, + "revision": "8c73eebf7c41c7d8bf83ff87f550e0f97d6aadc4", + "version": "3.0.2" + } + }, + { + "package": "WebSocket", + "repositoryURL": "https://github.com/vapor/websocket.git", + "state": { + "branch": null, + "revision": "141cb4d3814dc8062cb0b2f43e72801b5dfcf272", + "version": "1.0.1" + } } ] }, diff --git a/Package.swift b/Package.swift index 69c91f1..33ce832 100644 --- a/Package.swift +++ b/Package.swift @@ -5,6 +5,7 @@ import PackageDescription let package = Package( name: "Ether", dependencies: [ + .package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"), .package(url: "https://github.com/vapor/console.git", from: "3.0.0"), .package(url: "https://github.com/vapor/core.git", from: "3.0.0"), .package(url: "https://github.com/Ether-CLI/Manifest.git", from: "0.1.0") @@ -12,6 +13,6 @@ let package = Package( targets: [ .target(name: "Helpers", dependencies: ["Core", "Console"]), .target(name: "Ether", dependencies: ["Helpers", "Console", "Command", "Manifest", "Core"]), - .target(name: "Executable", dependencies: ["Ether", "Console"]) + .target(name: "Executable", dependencies: ["Vapor", "Ether", "Console"]) ] ) From 871be19170ebf3a6ac0c23a674ed818989f6cccc Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Wed, 9 May 2018 17:26:22 -0500 Subject: [PATCH 36/66] Rewrote main executable for Console 3 API --- Sources/Executable/main.swift | 120 ++++++++-------------------------- 1 file changed, 27 insertions(+), 93 deletions(-) diff --git a/Sources/Executable/main.swift b/Sources/Executable/main.swift index b804435..35224af 100644 --- a/Sources/Executable/main.swift +++ b/Sources/Executable/main.swift @@ -1,97 +1,31 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. +// The MIT License (MIT) // -//import Foundation -//import Console -//import Ether -//import Helpers -//import libc +// Copyright (c) 2017 Caleb Kleveter // -//// The current version of Ether. This string should be updated with each release. -//let version = "1.10.0" -//var arguments = CommandLine.arguments -//let terminal = Terminal(arguments: arguments) -//var iterator = arguments.makeIterator() +// 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: // -//guard let executable = iterator.next() else { -// throw ConsoleError.noExecutable -//} +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. // -//if arguments.count == 2, arguments[1] == "--version" || arguments[1] == "-v" { -// terminal.output("Ether Version: \(version)", style: .info, newLine: true) -// exit(0) -//} -// -//let date = Date() -//let formatter = DateFormatter() -//formatter.dateFormat = "YYYY" -//let currentYear = formatter.string(from: date) -// -//do { -// let commands: [Runnable] = [ -// Search(console: terminal), -// Install(console: terminal), -// Update(console: terminal), -// Remove(console: terminal), -// Template(console: terminal), -// New(console: terminal), -// FixInstall(console: terminal), -// Group(id: "version", commands: [ -// VersionLatest(console: terminal), -// VersionAll(console: terminal), -// VersonSet(console: terminal) -// ], help: ["For interacting with dependency versions"]), -// CleanManifest(console: terminal) -// ] -// -// try terminal.run(executable: executable, commands: commands, arguments: Array(iterator), help: [ -// "MIT \(currentYear) Caleb Kleveter.", -// "If you are getting errors, open an issue on GitHub.", -// "If you want to help, submit a PR." -// ]) -//} catch ConsoleError.insufficientArguments { -// terminal.error("Error: ", newLine: false) -// terminal.print("Insufficient arguments.") -//} catch ConsoleError.help { -// exit(0) -//} catch ConsoleError.cancelled { -// print("Cancelled") -// exit(2) -//} catch ConsoleError.noCommand { -// terminal.error("Error: ", newLine: false) -// terminal.print("No command supplied.") -//} catch let ConsoleError.commandNotFound(id) { -// terminal.error("Error: ", newLine: false) -// terminal.print("Command \"\(id)\" not found.") -//} catch let EtherError.fail(message) { -// let err = "Error: " -// var output = message.split(separator: "\n").map({ return String(repeating: " ", count: err.count) + $0 }) -// output[0] = output[0].trim() -// -// terminal.error("Error: ", newLine: false) -// terminal.print(output.joined(separator: "\n")) -// exit(1) -//} catch { -// terminal.error("Error: ", newLine: false) -// terminal.print("\(error)") -// exit(1) -//} +// 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. + +import Vapor +import Ether + +var services = Services.default() + +var commands = CommandConfig() +services.register(commands) + +try Application.asyncBoot(services: services).wait().run() From cf7d9d4607a1bf2a7c66365c66649b0d326ec02e Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Wed, 9 May 2018 17:30:52 -0500 Subject: [PATCH 37/66] Registered Configuration command with main executable command service --- Sources/Ether/Configuration.swift | 2 ++ Sources/Executable/main.swift | 1 + 2 files changed, 3 insertions(+) diff --git a/Sources/Ether/Configuration.swift b/Sources/Ether/Configuration.swift index 809e549..098c2a2 100644 --- a/Sources/Ether/Configuration.swift +++ b/Sources/Ether/Configuration.swift @@ -38,6 +38,8 @@ public class Configuration: Command { public var help: [String] = ["Configure custom actions to occure when a command is run"] + public init() {} + public func run(using context: CommandContext) throws -> EventLoopFuture { let setter = context.console.loadingBar(title: "Setting Configuration Ket") _ = setter.start(on: context.container) diff --git a/Sources/Executable/main.swift b/Sources/Executable/main.swift index 35224af..317b7a3 100644 --- a/Sources/Executable/main.swift +++ b/Sources/Executable/main.swift @@ -26,6 +26,7 @@ import Ether var services = Services.default() var commands = CommandConfig() +commands.use(Configuration(), as: "config") services.register(commands) try Application.asyncBoot(services: services).wait().run() From 41091e0d0cf4beb64c5a4f248efe49c293636230 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Wed, 9 May 2018 17:33:49 -0500 Subject: [PATCH 38/66] Added error catch to commnd run in main executable --- Sources/Executable/main.swift | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Sources/Executable/main.swift b/Sources/Executable/main.swift index 317b7a3..40880bf 100644 --- a/Sources/Executable/main.swift +++ b/Sources/Executable/main.swift @@ -20,6 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +import Console import Vapor import Ether @@ -29,4 +30,10 @@ var commands = CommandConfig() commands.use(Configuration(), as: "config") services.register(commands) -try Application.asyncBoot(services: services).wait().run() +do { + try Application.asyncBoot(services: services).wait().run() +} catch { + print("Error:", error) + exit(1) +} + From 6b00ef74b9ae741b232984318bedcc32696121ee Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Wed, 9 May 2018 17:34:54 -0500 Subject: [PATCH 39/66] Registered FixInstall command with main executable --- Sources/Ether/FixInstall.swift | 2 ++ Sources/Executable/main.swift | 1 + 2 files changed, 3 insertions(+) diff --git a/Sources/Ether/FixInstall.swift b/Sources/Ether/FixInstall.swift index 7a95f62..10579bc 100644 --- a/Sources/Ether/FixInstall.swift +++ b/Sources/Ether/FixInstall.swift @@ -28,6 +28,8 @@ public final class FixInstall: Command { public var help: [String] = ["Fixes fetching errors that occur during package install"] + public init() {} + public func run(using context: CommandContext) throws -> EventLoopFuture { context.console.output("This may take some time...", style: .info) diff --git a/Sources/Executable/main.swift b/Sources/Executable/main.swift index 40880bf..fd58c17 100644 --- a/Sources/Executable/main.swift +++ b/Sources/Executable/main.swift @@ -28,6 +28,7 @@ var services = Services.default() var commands = CommandConfig() commands.use(Configuration(), as: "config") +commands.use(FixInstall(), as: "fix-install") services.register(commands) do { From 162c9b96e8c608bc28f9e762eb0a7b1862fe2814 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 11 May 2018 11:59:27 -0500 Subject: [PATCH 40/66] Added Vapor product to Ether targt dependencies --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 33ce832..e2ac9f2 100644 --- a/Package.swift +++ b/Package.swift @@ -12,7 +12,7 @@ let package = Package( ], targets: [ .target(name: "Helpers", dependencies: ["Core", "Console"]), - .target(name: "Ether", dependencies: ["Helpers", "Console", "Command", "Manifest", "Core"]), + .target(name: "Ether", dependencies: ["Vapor", "Helpers", "Console", "Command", "Manifest", "Core"]), .target(name: "Executable", dependencies: ["Vapor", "Ether", "Console"]) ] ) From 86f0982ee6795789d06871b26225c6d95b985978 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 11 May 2018 12:01:06 -0500 Subject: [PATCH 41/66] Fixed bug with file reading and writing due to malformed URL in Configuration command --- Sources/Ether/Configuration.swift | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Sources/Ether/Configuration.swift b/Sources/Ether/Configuration.swift index 098c2a2..413b324 100644 --- a/Sources/Ether/Configuration.swift +++ b/Sources/Ether/Configuration.swift @@ -25,9 +25,10 @@ import Console import Command import Helpers import Core +import Bits public class Configuration: Command { - public static let configPath = "/Library/Application Support/Ether/config.json" + public static let configPath = "/Library/Application\\ Support/Ether/config.json" public var arguments: [CommandArgument] = [ CommandArgument.argument(name: "key", help: ["The configuration JSON key to set"]), @@ -41,36 +42,40 @@ public class Configuration: Command { public init() {} public func run(using context: CommandContext) throws -> EventLoopFuture { - let setter = context.console.loadingBar(title: "Setting Configuration Ket") + let setter = context.console.loadingBar(title: "Setting Configuration Key") _ = setter.start(on: context.container) let key = try context.argument("key") let value = try context.argument("value") + let user = try Process.execute("whoami") var configuration = try Configuration.get() + guard let property = Config.properties[key] else { throw EtherError(identifier: "noSettingWithName", reason: "No configuration setting found with name '\(key)'") } configuration[keyPath: property] = value - try JSONEncoder().encode(configuration).write(to: URL(string: "file:\(Configuration.configPath)")!) + + try JSONEncoder().encode(configuration).write(to: URL(string: "file:/Users/\(user)/Library/Application%20Support/Ether/config.json")!) setter.succeed() return context.container.eventLoop.newSucceededFuture(result: ()) } public static func get()throws -> Config { - guard let configuration = FileManager.default.contents(atPath: "file:\(configPath)") else { - throw EtherError(identifier: "fileNotFound", reason: "File at path '\(configPath)' not found") - } + let user = try Process.execute("whoami") + let url = "file:/Users/\(user)\(configPath)" + + let configuration = FileManager.default.contents(atPath: url) ?? Data([.leftCurlyBracket, .rightCurlyBracket]) return try JSONDecoder().decode(Config.self, from: configuration) } } public struct Config: Codable, Reflectable { - public var accessToken: String + public var accessToken: String? - static let properties: [String: WritableKeyPath] = [ + static let properties: [String: WritableKeyPath] = [ "access-token": \.accessToken ] } From 3f1116db5215e63ea86468e09b8abc648fbb6761 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 11 May 2018 12:07:58 -0500 Subject: [PATCH 42/66] Installed Manifest 0.4.3 --- Package.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.resolved b/Package.resolved index 1142e80..06c3115 100644 --- a/Package.resolved +++ b/Package.resolved @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/Ether-CLI/Manifest.git", "state": { "branch": null, - "revision": "6e1369ea6224118e1e07bcaddfac1af30f960486", - "version": "0.4.2" + "revision": "579d2fd64ec9ba0d7e7f9ff779d46f1f7219fd39", + "version": "0.4.3" } }, { From 62391c581e5dd2ec20877e8a14b12892973d5f87 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 11 May 2018 15:26:00 -0500 Subject: [PATCH 43/66] Use Data(contentsOf:) initializer to access configuration file data --- Sources/Ether/Configuration.swift | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Sources/Ether/Configuration.swift b/Sources/Ether/Configuration.swift index 413b324..752372c 100644 --- a/Sources/Ether/Configuration.swift +++ b/Sources/Ether/Configuration.swift @@ -28,7 +28,7 @@ import Core import Bits public class Configuration: Command { - public static let configPath = "/Library/Application\\ Support/Ether/config.json" +// public static let configPath = "/Library/Application\\ Support/Ether/config.json" public var arguments: [CommandArgument] = [ CommandArgument.argument(name: "key", help: ["The configuration JSON key to set"]), @@ -65,9 +65,15 @@ public class Configuration: Command { public static func get()throws -> Config { let user = try Process.execute("whoami") - let url = "file:/Users/\(user)\(configPath)" + let configuration: Data + + let contents = try Data(contentsOf: URL(string: "file:/Users/\(user)/Library/Application%20Support/Ether/config.json")!) + if contents.count > 0 { + configuration = contents + } else { + configuration = Data([.leftCurlyBracket, .rightCurlyBracket]) + } - let configuration = FileManager.default.contents(atPath: url) ?? Data([.leftCurlyBracket, .rightCurlyBracket]) return try JSONDecoder().decode(Config.self, from: configuration) } } From 7aa08c38b8591c445f6c17accf6e330f3d2dbd3c Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 11 May 2018 16:32:39 -0500 Subject: [PATCH 44/66] Updated Manifest version to 0.4.4 --- Package.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.resolved b/Package.resolved index 06c3115..ab7ac06 100644 --- a/Package.resolved +++ b/Package.resolved @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/Ether-CLI/Manifest.git", "state": { "branch": null, - "revision": "579d2fd64ec9ba0d7e7f9ff779d46f1f7219fd39", - "version": "0.4.3" + "revision": "a1884894e75cde17bec40415df0b50292c4a5128", + "version": "0.4.4" } }, { From 334ec02e177d868904329382cf66bebf8b793d06 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 11 May 2018 16:51:24 -0500 Subject: [PATCH 45/66] Completed porting Install command to Console 3 API --- Sources/Ether/Install.swift | 315 ++++++++++++++++++++-------------- Sources/Executable/main.swift | 1 + 2 files changed, 191 insertions(+), 125 deletions(-) diff --git a/Sources/Ether/Install.swift b/Sources/Ether/Install.swift index def5ebd..e328acb 100644 --- a/Sources/Ether/Install.swift +++ b/Sources/Ether/Install.swift @@ -20,7 +20,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +import Manifest import Command +import Helpers +import Vapor public final class Install: Command { public var arguments: [CommandArgument] = [ @@ -38,132 +41,194 @@ public final class Install: Command { public var help: [String] = ["Installs a package into the current project"] + public init() {} + public func run(using context: CommandContext) throws -> Future { - return context.container.eventLoop.newSucceededFuture(result: ()) + context.console.info("Reading Package Targets...") + let targets = try Manifest.current.targets().map { $0.name } + let approvedTargets = self.inquireFor(targets: targets, in: context) + + let installing = context.console.loadingBar(title: "Installing Dependency") + + let oldPinCount: Int + + do { + oldPinCount = try Manifest.current.resolved().object.pins.count + } catch { oldPinCount = 0 } + + let name = try context.argument("name") + + context.console.info("Fetching Package Data...") + return try self.package(with: name, on: context).map(to: Void.self) { package in + _ = installing.start(on: context.container) + + let dependency = Dependency(url: package.url, version: .from(package.version)) + try dependency.save() + + try approvedTargets.forEach { name in + guard let target = try Manifest.current.target(withName: name) else { return } + target.dependencies.append(contentsOf: package.products) + try target.save() + } + _ = try Process.execute("swift", "package", "update") + let newPinCount = try Manifest.current.resolved().object.pins.count + + installing.succeed() + + if let _ = context.options["xcode"] { + let xcodeBar = context.console.loadingBar(title: "Generating Xcode Project") + _ = xcodeBar.start(on: context.container) + + _ = try Process.execute("swift", "package", "generate-xcodeproj") + xcodeBar.succeed() + _ = try Process.execute("sh", "-c", "open *.xcodeproj") + } + + context.console.output("📦 \(newPinCount - oldPinCount) packages installed", style: .plain, newLine: true) + } + } + + /// Asks the user if they want to add a dependency to the targets in the package manifest. + /// + /// - Parameter targets: The names of the targets available. + /// - Returns: The names of the targets that where accepted. + fileprivate func inquireFor(targets: [String], in context: CommandContext) -> [String] { + var acceptedTargets: [String] = [] + var index = 0 + + if targets.count > 1 { + targetFetch: while index < targets.count { + let target = targets[index] + let response = context.console.ask(ConsoleText(stringLiteral: "Would you like to add the package to the target '\(target)'? (y,n,q,?)")) + + switch response { + case "y": + acceptedTargets.append(target) + index += 1 + case "n": + index += 1 + case "q": + break targetFetch + default: context.console.output(""" + y: Add the package as a dependency to the target. + n: Do not add the package as a dependency to the target. + q: Do not add the package as a dependency to the current target or any of the following targets. + ?: Output this message. + """, style: .info, newLine: true) + } + } + } else { + acceptedTargets.append(targets[0]) + } + + return acceptedTargets + } + + func package(with name: String, on context: CommandContext)throws -> Future<(url: String, version: String, products: [String])> { + let client = try context.container.make(Client.self) + guard let token = try Configuration.get().accessToken else { + throw EtherError( + identifier: "noAccessToken", + reason: "No access token in configuration. Run `ether config access-token `. The token should have permissions to access public repositories" + ) + } + + let fullName: Future + if name.contains("/") { + let url = "https://package.vapor.cloud/packages/\(name)" + fullName = client.get(url).flatMap(to: String.self) { response in + response.content.get(String.self, at: "full_name") + } + } else { + let search = "https://package.vapor.cloud/packages/search?name=\(name)" + fullName = client.get(search, headers: ["Authorization": "Bearer \(token)"]).flatMap(to: String.self) { response in + response.content.get(String.self, at: "repositories", 0, "nameWithOwner") + } + } + + let version = fullName.flatMap(to: String.self) { fullName in + let names = fullName.split(separator: "/").map(String.init) + return try self.version(owner: names[0], repo: names[1], token: token, on: context) + }.map(to: String.self) { version in + if version.first == "v" { return String(version.dropFirst()) } + return version + } + + let products = fullName.flatMap(to: [String].self) { fullName in + let names = fullName.split(separator: "/").map(String.init) + return try self.products(owner: names[0], repo: names[1], token: token, on: context) + } + + return map(to: (url: String, version: String, products: [String]).self, fullName, version, products) { name, version, products in + let url = "https://github.com/\(name).git" + return (url, version, products) + } + } + + fileprivate func version(owner: String, repo: String, token: String, on context: CommandContext)throws -> Future { + let client = try context.container.make(Client.self) + return client.get("https://package.vapor.cloud/packages/\(owner)/\(repo)/releases", headers: ["Authorization":"Bearer \(token)"]).flatMap(to: [String].self) { response in + return try response.content.decode([String].self) + }.map(to: String.self) { releases in + guard let first = releases.first else { + throw EtherError( + identifier: "noReleases", + reason: "No tags where found for the selected package. You might want to open an issue on the package requesting a release." + ) + } + + if first.lowercased().contains("rc") || first.lowercased().contains("beta") || first.lowercased().contains("alpha") { + let majorVersion = Int(String(first.first ?? "0")) ?? 0 + if majorVersion > 0 && releases.count > 1 { + var answer: String + + repeat { + answer = context.console.ask( + ConsoleText(stringLiteral:"The latest version found (\(first)) is a pre-release. Would you like to use an earlier stable release? (y/n)") + ).lowercased() + } while answer != "y" || answer != "n" + + if answer == "y" { + return releases.filter { Int(String($0.first ?? "0")) ?? 0 != majorVersion }.first ?? first + } else { + return first + } + } else { + return first + } + } else { + return first + } + } + } + + fileprivate func products(owner: String, repo: String, token: String, on context: CommandContext)throws -> Future<[String]> { + let client = try context.container.make(Client.self) + return client.get("https://package.vapor.cloud/packages/\(owner)/\(repo)/manifest", headers: ["Authorization":"Bearer \(token)"]).flatMap(to: [Product].self) { response in + return response.content.get([Product].self, at: "products") + }.map(to: [String].self) { products in + if let index = products.index(where: { $0.name.lowercased() == repo.lowercased() }) { + return [products[index].name] + } + if products.count < 1 { return [repo] } + + var allowed: [String]? = nil + + repeat { + let options = products.enumerated().map { return "\($0.offset). \($0.element)" } + let question = ["Unable to automatically detect product to add to target(s). Answer with comma seperated list of products to add"] + options + let seletions = context.console.ask(ConsoleText(stringLiteral: question.joined(separator: "\n"))) + let indexes = seletions.split(separator: "\n").map(String.init).map { $0.trimmingCharacters(in: .whitespaces) }.compactMap(Int.init) + + let selected = products.enumerated().filter { indexes.contains($0.offset) }.map { $0.element.name } + if selected.count > 0 { allowed = selected } + } while allowed == nil + + return allowed! + } } } -// -// public func run(arguments: [String]) throws { -// console.output("Reading Package Targets...", style: .info, newLine: true) -// -// let fileManager = FileManager.default -// let name = try value("name", from: arguments) -// let installBar = console.loadingBar(title: "Installing Dependency") -// -// // Get package manifest and JSON data -// guard let manifestURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift") else { -// throw EtherError.fail("Bad path to package manifest. Make sure you are in the project root.") -// } -// guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.resolved") else { -// throw EtherError.fail("Bad path to package data. Make sure you are in the project root.") -// } -// let packageManifest = try String(contentsOf: manifestURL) -// let mutablePackageManifest = NSMutableString(string: packageManifest) -// let pinsCount: Int -// -// do { -// let packageData = try Data(contentsOf: resolvedURL).json() -// guard let object = packageData?["object"] as? APIJSON, -// let pins = object["pins"] as? [APIJSON] else { return } -// pinsCount = pins.count -// } catch { -// pinsCount = 0 -// } -// -// // Get the names of the targets to add the dependency to -// let targets = try Manifest.current.getTargets() -// let useTargets: [String] = inquireFor(targets: targets) -// -// installBar.start() -// -// let packageInstenceRegex = try NSRegularExpression(pattern: "(\\.package([\\w\\s\\d\\,\\:\\(\\)\\@\\-\\\"\\/\\.])+\\)),?(?:\\R?)", options: .anchorsMatchLines) -// let dependenciesRegex = try NSRegularExpression(pattern: "products: *\\[(?s:.*?)\\],\\s*dependencies: *\\[", options: .anchorsMatchLines) -// -// // Get the data for the package to install -// let newPackageData = try Manifest.current.getPackageData(for: name) -// let packageVersion = arguments.options["version"] ?? newPackageData.version -// let packageUrl = arguments.options["url"] ?? newPackageData.url -// -// let packageInstance = "$1,\n .package(url: \"\(packageUrl)\", .exact(\"\(packageVersion)\"))\n" -// let depPackageInstance = "$0\n .package(url: \"\(packageUrl)\", .exact(\"\(packageVersion)\"))" -// -// // Add the new package instance to the Package dependencies array. -// if packageInstenceRegex.matches(in: packageManifest, options: [], range: NSMakeRange(0, packageManifest.utf8.count)).count > 0 { -// packageInstenceRegex.replaceMatches(in: mutablePackageManifest, options: [], range: NSMakeRange(0, mutablePackageManifest.length), withTemplate: packageInstance) -// } else { -// dependenciesRegex.replaceMatches(in: mutablePackageManifest, options: [], range: NSMakeRange(0, mutablePackageManifest.length), withTemplate: depPackageInstance) -// } -// -// // Write the new package manifest to the Package.swift file -// try String(mutablePackageManifest).data(using: .utf8)?.write(to: URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift")!) -// -// // Update the packages. -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) -// -// // Get the new package name and add it to the previously accepted targets. -// let dependencyName = try Manifest.current.getPackageName(for: newPackageData.url) -// for target in useTargets { -// try mutablePackageManifest.addDependency(dependencyName, to: target) -// } -// -// // Write the Package.swift file again -// try String(mutablePackageManifest).data(using: .utf8)?.write(to: URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift")!) -// -// // Calculate the number of package that where installed and output it. -// let packageData = try Data(contentsOf: resolvedURL).json() -// guard let object = packageData?["object"] as? APIJSON, -// let pins = object["pins"] as? [APIJSON] else { return } -// -// let newPackageCount = pins.count - pinsCount -// -// installBar.finish() -// -// if let _ = arguments.options["xcode"] { -// let xcodeBar = console.loadingBar(title: "Generating Xcode Project") -// xcodeBar.start() -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "generate-xcodeproj"]) -// xcodeBar.finish() -// try console.execute(program: "/bin/sh", arguments: ["-c", "open *.xcodeproj"], input: nil, output: nil, error: nil) -// } -// -// console.output("📦 \(newPackageCount) packages installed", style: .plain, newLine: true) -// } -// -// /// Asks the user if they want to add a dependency to the targets in the package manifest. -// /// -// /// - Parameter targets: The names of the targets available. -// /// - Returns: The names of the targets that where accepted. -// fileprivate func inquireFor(targets: [String]) -> [String] { -// var acceptedTargets: [String] = [] -// var index = 0 -// -// if targets.count > 1 { -// targetFetch: while index < targets.count { -// let target = targets[index] -// let response = console.ask("Would you like to add the package to the target '\(target)'? (y,n,q,?)") -// -// switch response { -// case "y": -// acceptedTargets.append(target) -// index += 1 -// case "n": -// index += 1 -// case "q": -// break targetFetch -// default: console.output(""" -// y: Add the package as a dependency to the target. -// n: Do not add the package as a dependency to the target. -// q: Do not add the package as a dependency to the current target or any of the following targets. -// ?: Output this message. -// """, style: .info, newLine: true) -// } -// } -// } else { -// acceptedTargets.append(targets[0]) -// } -// -// return acceptedTargets -// } -//} +struct Product: Content { + let name: String +} diff --git a/Sources/Executable/main.swift b/Sources/Executable/main.swift index fd58c17..168bc44 100644 --- a/Sources/Executable/main.swift +++ b/Sources/Executable/main.swift @@ -29,6 +29,7 @@ var services = Services.default() var commands = CommandConfig() commands.use(Configuration(), as: "config") commands.use(FixInstall(), as: "fix-install") +commands.use(Install(), as: "install") services.register(commands) do { From dd8436d81ad9323fd94f93f748e25c434e9d0516 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 11 May 2018 16:52:45 -0500 Subject: [PATCH 46/66] Deleted PackageJSONFetcher, Manifest, JSON, CommandLine, and APIClient.swift files --- Sources/Helpers/APIClient.swift | 100 -------- Sources/Helpers/CommandLine.swift | 34 --- Sources/Helpers/JSON.swift | 29 --- Sources/Helpers/Manifest.swift | 291 ----------------------- Sources/Helpers/PackageJSONFetcher.swift | 78 ------ 5 files changed, 532 deletions(-) delete mode 100644 Sources/Helpers/APIClient.swift delete mode 100644 Sources/Helpers/CommandLine.swift delete mode 100644 Sources/Helpers/JSON.swift delete mode 100644 Sources/Helpers/Manifest.swift delete mode 100644 Sources/Helpers/PackageJSONFetcher.swift diff --git a/Sources/Helpers/APIClient.swift b/Sources/Helpers/APIClient.swift deleted file mode 100644 index 816d7e6..0000000 --- a/Sources/Helpers/APIClient.swift +++ /dev/null @@ -1,100 +0,0 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. -// -//import Foundation -//import Core -// -//public let CKNetworkingErrorDomain = "com.caleb-kleveter.Ether.NetworkingError" -//public let MissingHTTPResponseError: Int = 0 -// -//public typealias APIJSON = [String: AnyObject] -//public typealias FetchCompletion = (APIJSON?, HTTPURLResponse?, DataTaskError?) -> Void -// -//public enum DataTaskError: Error { -// case badStatusCode(Int) -// case cannotCastToHTTPURLResponse(NSError) -// case dataTaskError(Error) -// case noData -// case jsonSerializationError(Error) -// case noJson -//} -// -//public protocol JSONInitable { -// init(json: APIJSON) -//} -// -//public protocol APIClient { -// var configuration: URLSessionConfiguration { get } -// var session: URLSession { get } -// -// func dataTask(with request: URLRequest, endingWith completion: @escaping FetchCompletion) -> URLSessionDataTask -//} -// -//extension APIClient { -// public func dataTask(with request: URLRequest, endingWith completion: @escaping FetchCompletion) -> URLSessionDataTask { -// let task = try! Portal.open({ (portal) in -// let task = self.session.dataTask(with: request) { (data, response, error) in -// -// guard let resp = response as? HTTPURLResponse else { -// let userInfo = [ -// NSLocalizedDescriptionKey: NSLocalizedString("Missing HTTP Response", comment: "") -// ] -// -// let error = NSError(domain: CKNetworkingErrorDomain, code: MissingHTTPResponseError, userInfo: userInfo) -// completion(nil, nil, DataTaskError.cannotCastToHTTPURLResponse(error)) -// return -// } -// -// if resp.statusCode >= 200 && resp.statusCode < 300 { -// if error == nil { -// if data != nil { -// do { -// let json = try JSONSerialization.jsonObject(with: data!, options: []) as? APIJSON -// if let json = json { -// completion(json, resp, nil) -// } else { -// completion(nil, nil, .noJson) -// return -// } -// } catch let error { -// completion(nil, nil, .jsonSerializationError(error)) -// return -// } -// return -// } else { -// completion(nil, nil, .noData) -// return -// } -// } else { -// completion(nil, nil, .dataTaskError(error!)) -// return -// } -// } else { -// completion(nil, nil, .badStatusCode(resp.statusCode)) -// return -// } -// } -// portal.close(with: task) -// }) -// return task -// } -//} diff --git a/Sources/Helpers/CommandLine.swift b/Sources/Helpers/CommandLine.swift deleted file mode 100644 index dc52c1d..0000000 --- a/Sources/Helpers/CommandLine.swift +++ /dev/null @@ -1,34 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2017 Caleb Kleveter -// -// 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. - -import Foundation - -// ATTRIBUTION: - @rintaro | https://stackoverflow.com/questions/26971240/how-do-i-run-an-terminal-command-in-a-swift-script-e-g-xcodebuild -@discardableResult -public func shell(command: String, _ args: String...) -> Int32 { - let task = Process() - task.launchPath = command - task.arguments = args - task.launch() - task.waitUntilExit() - return task.terminationStatus -} diff --git a/Sources/Helpers/JSON.swift b/Sources/Helpers/JSON.swift deleted file mode 100644 index 20ec7bd..0000000 --- a/Sources/Helpers/JSON.swift +++ /dev/null @@ -1,29 +0,0 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. -// -//import Foundation -// -//public extension Data { -// public func json()throws -> APIJSON? { -// return try JSONSerialization.jsonObject(with: self, options: []) as? APIJSON -// } -//} diff --git a/Sources/Helpers/Manifest.swift b/Sources/Helpers/Manifest.swift deleted file mode 100644 index 9aa9e19..0000000 --- a/Sources/Helpers/Manifest.swift +++ /dev/null @@ -1,291 +0,0 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. -// -//import Foundation -//import Console -//import Bits -// -//public class Manifest { -// public static let current = Manifest() -// private let fileManager = FileManager.default -// private let client = PackageJSONFetcher() -// -// private init() {} -// -// /// Gets the package manifest for the current project. -// /// -// /// - Returns: The manifest data. -// /// - Throws: If a package manifest is not found in the current directory. -// public func get()throws -> String { -// guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift") else { -// throw EtherError.fail("Unable to create URL for package manifest file.") -// } -// if !fileManager.fileExists(atPath: "\(fileManager.currentDirectoryPath)/Package.swift") { -// throw EtherError.fail("Bad path to package manifest. Make sure you are in the project root.") -// } -// -// return try String(contentsOf: resolvedURL) -// } -// -// /// Rewrites the package manifest file with a string. -// /// -// /// - Parameter string: The string the rewrite the manifest with. -// /// - Throws: Any errors that occur when createing the URL to the manifest file or in writing the manifest. -// public func write(_ string: String)throws { -// guard let manifestURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift") else { -// throw EtherError.fail("Unable to create URL for package manifest file.") -// } -// try string.data(using: .utf8)?.write(to: manifestURL) -// } -// -// /// Gets the package manifest data in JSON format. -// /// -// /// - Parameter console: The `ConsoleProtocol` instance to use to run `swift package dump-package`. -// /// - Returns: The JSON data representing the package manifest. -// /// - Throws: `EtherError.fail` if the data returned from the command cannot be converted to JSON. -// public func getJSON(withConsole console: ConsoleProtocol)throws -> APIJSON { -// guard let json = try (console.backgroundExecute(program: "swift", arguments: ["package", "dump-package"]) as Data).json() else { -// throw EtherError.fail("Unable to convert package data to JSON") -// } -// return json -// } -// -// /// Gets the name of the package that has a specefied URL by reading the `Package.resolved` file data. -// /// -// /// - Parameter url: The URL of the package that the name is to get fetched from. -// /// - Returns: The name of the package that was found. -// /// - Throws: An error is thrown if either, 1) The data in the Package.resolved file is corrupted, or 2) A package does not exist with the URL passed in -// public func getPackageName(`for` url: String)throws -> String { -// guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.resolved") else { -// throw EtherError.fail("Bad path to package data. Make sure you are in the project root.") -// } -// let packageData = try Data(contentsOf: resolvedURL).json() -// -// guard let object = packageData?["object"] as? APIJSON, -// let pins = object["pins"] as? [APIJSON] else { throw EtherError.fail("Unable to read Package.resolved") } -// -// guard let package = try pins.filter({ (json) -> Bool in -// guard let repoURL = json["repositoryURL"] as? String else { -// throw EtherError.fail("Unable to read Package.resolved") -// } -// return repoURL == url -// }).first else { -// throw EtherError.fail("Unable to read Package.resolved") -// } -// -// guard let name = package["package"] as? String else { -// throw EtherError.fail("Unable to read Package.resolved") -// } -// -// return name -// } -// -// /// Gets the URL of the package that has a specefied name by reading the `Package.resolved` file data. -// /// -// /// - Parameter name: The ame of the package that the URL is to get fetched from. -// /// - Returns: The URL of the package that was found. -// /// - Throws: An error is thrown if either, 1) The data in the Package.resolved file is corrupted, or 2) A package does not exist with the name passed in -// public func getPackageUrl(`for` name: String)throws -> String { -// guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.resolved") else { -// throw EtherError.fail("Bad path to package data. Make sure you are in the project root.") -// } -// let packageData = try Data(contentsOf: resolvedURL).json() -// -// guard let object = packageData?["object"] as? APIJSON, -// let pins = object["pins"] as? [APIJSON] else { throw EtherError.fail("Unable to read Package.resolved") } -// -// guard let package = try pins.filter({ (json) -> Bool in -// guard let repoURL = json["package"] as? String else { -// throw EtherError.fail("Unable to read Package.resolved") -// } -// return repoURL == name -// }).first else { -// throw EtherError.fail("No package data found for name '\(name)'") -// } -// -// guard let url = package["repositoryURL"] as? String else { -// throw EtherError.fail("Unable to read repo URL for package with name '\(name)'") -// } -// -// return url -// } -// -// /// Gets that names of all the current projects targets. -// /// -// /// - Parameter packageData: The contents of the package manifest file. -// /// - Returns: All the target names. -// /// - Throws: Any errors that occur while creating an `NSRegularExpression` to match targets against. -// public func getTargets()throws -> [String] { -// guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift") else { -// throw EtherError.fail("Bad path to package data. Make sure you are in the project root.") -// } -// let packageData = try String(contentsOf: resolvedURL) -// -// let targetPattern = try NSRegularExpression(pattern: "\\.(testT|t)arget\\(\\s*name:\\s\"(.*?)\".*?(\\)|\\])\\)", options: NSRegularExpression.Options.dotMatchesLineSeparators) -// let targetMatches = targetPattern.matches(in: packageData, options: [], range: NSMakeRange(0, packageData.utf8.count)) -// -// let targetNames = targetMatches.map { (match) in -// return targetPattern.replacementString(for: match, in: packageData, offset: 0, template: "$2") -// } -// -// return targetNames -// } -// -// /// Gets the pins from `Package.resolved`. -// /// -// /// - Returns: The projects package pins. -// /// - Throws: An Ether error if a `Package.resolved` file is not found, or the JSON it contains is malformed. -// public func getPins()throws -> [APIJSON] { -// guard let resolvedURL = URL(string: "file:\(fileManager.currentDirectoryPath)/Package.resolved") else { -// throw EtherError.fail("Bad path to package data. Make sure you are in the project root.") -// } -// let packageData = try Data(contentsOf: resolvedURL).json() -// -// guard let object = packageData?["object"] as? APIJSON, -// let pins = object["pins"] as? [APIJSON] else { -// throw EtherError.fail("Unable to read Package.resolved") -// } -// -// return pins -// } -// -// /// Removes extra comments and white space from a package manifest. -// /// -// /// - Throws: Errors from creating maifest URL, NSRegularExpression objects, or re-writing the maifest. -// public func clean()throws { -// let manifest = try self.get() -// let lines = manifest.split(separator: "\n").map(String.init) -// -// let comment = try NSRegularExpression(pattern: " *\\/\\/ +(?!swift-tools-version).*", options: []) -// let collapse = try NSRegularExpression(pattern: " *\\.(?:library|(?:testT|t)arget)\\(", options: []) -// -// var newManifest: [String] = [] -// var currentLine = "" -// var lineIndex = 0 -// -// while lineIndex < lines.count { -// var line = lines[lineIndex] -// if comment.matches(in: line, options: [], range: NSMakeRange(0, line.count)).count > 0 { -// lineIndex += 1 -// } else if collapse.matches(in: line, options: [], range: NSMakeRange(0, line.count)).count > 0 { -// currentLine = "" -// while !line.contains(")") { -// if currentLine.last != nil, currentLine.last! == "(" { -// currentLine.append(line.trim()) -// } else if currentLine == "" { -// currentLine.append(line) -// } else { -// currentLine.append(" " + line.trim()) -// } -// lineIndex += 1 -// line = lines[lineIndex] -// } -// currentLine.append(" " + line.trim()) -// lineIndex += 1 -// line = lines[lineIndex] -// -// newManifest.append(currentLine) -// } else { -// newManifest.append(line) -// lineIndex += 1 -// } -// } -// -// try self.write(newManifest.joined(separator: "\n")) -// } -// -// /// Gets the URL and version of a package from the IBM package catalog API on a search URL. -// /// -// /// - Parameter name: The name of the package to get data for. If it contains a forward slash, the data will be fetched for the matching package, if it does not contain a forward slash, a search will be preformed and the first result will be used. -// /// - Returns: The URL and version of the package found. -// /// - Throws: Any errors that occur while fetching the JSON, or unwrapping the package data. -// public func getPackageData(for name: String)throws -> (url: String, version: String) { -// let packageUrl: String -// let version: String -// -// if name.contains("/") { -// let clientUrl = "https://packagecatalog.com/data/package/\(name)" -// let json = try client.get(from: clientUrl, withParameters: [:]) -// guard let ghUrl = json["ghUrl"] as? String, -// let packageVersion = json["version"] as? String else { -// throw EtherError.fail("Bad JSON") -// } -// -// packageUrl = ghUrl -// version = packageVersion -// } else { -// let clientUrl = "https://packagecatalog.com/api/search/\(name)" -// let json = try client.get(from: clientUrl, withParameters: ["items": "1", "chart": "moststarred"]) -// guard let data = json["data"] as? APIJSON, -// let hits = data["hits"] as? APIJSON, -// let results = hits["hits"] as? [APIJSON], -// let source = results[0]["_source"] as? APIJSON else { -// throw EtherError.fail("Bad JSON") -// } -// -// packageUrl = String(describing: source["git_clone_url"]!) -// version = String(describing: source["latest_version"]!) -// } -// -// return (url: packageUrl, version: version) -// } -//} -// -//extension NSMutableString { -// -// /// Adds a package dependency to a target in a package manifest file. -// /// -// /// - Parameters: -// /// - dependency: The name of the dependency that will be added to a target. -// /// - target: The target the dependency will be added to. -// /// - packageData: The contents of the package manifest file. -// /// - Returns: The package manifest with the dependency added to the target. -// /// - Throws: Any errors that originate when creating an `NSRegularExpression`. -// public func addDependency(_ dependency: String, to target: String)throws { -// let targetPattern = try NSRegularExpression(pattern: "\\.(testT|t)arget\\(\\s*name:\\s\"(.*?)\".*?(\\)|\\])\\)", options: .dotMatchesLineSeparators) -// let dependenciesPattern = try NSRegularExpression(pattern: "(dependencies:\\s*\\[\\n?(\\s*).*?(\"|\\))),?\\s*\\]", options: .dotMatchesLineSeparators) -// let targetMatches = targetPattern.matches(in: String(self), options: [], range: NSMakeRange(0, self.length)) -// -// guard let targetRange: NSRange = targetMatches.map({ (match) -> (name: String, range: NSRange) in -// let name = targetPattern.replacementString(for: match, in: self as String, offset: 0, template: "$2") -// let range = match.range -// return (name: name, range: range) -// }).filter({ (name: String, range: NSRange) -> Bool in -// return name == target -// }).first?.1 else { throw EtherError.fail("Attempted to add a dependency to a non-existent target") } -// -// dependenciesPattern.replaceMatches(in: self, options: [], range: targetRange, withTemplate: "$1, \"\(dependency)\"]") -// } -// -// /// Removes a package dependency from all targets in a package manifest file. -// /// -// /// - Parameters: -// /// - dependency: The name of the dependency that will be removed from all targets. -// /// - Returns: The package manifest with the dependency added to the target. -// /// - Throws: Any errors that originate when creating an `NSRegularExpression`. -// public func removeDependency(_ dependency: String)throws { -// let dependenciesPattern = try NSRegularExpression(pattern: "(dependencies: *\\[)((\\s*(\\.\\w+)?\"\\w+\",?\\s*)*)\"\(dependency)\",?\\s*((\\s*(\\.\\w+)?\"\\w+\",?\\s*)*)(\\])", options: .dotMatchesLineSeparators) -// let range = NSMakeRange(0, self.length) -// -// dependenciesPattern.replaceMatches(in: self, options: [], range: range, withTemplate: "$1$2$5$8") -// } -//} diff --git a/Sources/Helpers/PackageJSONFetcher.swift b/Sources/Helpers/PackageJSONFetcher.swift deleted file mode 100644 index 36a66df..0000000 --- a/Sources/Helpers/PackageJSONFetcher.swift +++ /dev/null @@ -1,78 +0,0 @@ -//// The MIT License (MIT) -//// -//// Copyright (c) 2017 Caleb Kleveter -//// -//// 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. -// -//import Foundation -//import Core -// -//public enum GetJSONError: Error { -// case badURL(String) -// case noJSON -//} -// -//public final class PackageJSONFetcher: APIClient { -// -// public let session: URLSession -// -// public let configuration: URLSessionConfiguration -// -// public init() { -// self.configuration = URLSessionConfiguration.default -// self.session = URLSession(configuration: configuration) -// } -// -// /// Gets the data from a URL in semi-asynchronusly. -// /// -// /// - Parameters: -// /// - urlString: The URL the data will be fetched from. -// /// - parameters: The URL's parameters. -// /// - completion: The completion handler where either the JSON or Error can be accessed. -// public func get(from urlString: String, withParameters parameters: [String: String], _ completion: @escaping (APIJSON?, Error?)->()) { -// let parameterString = parameters.map({ return "\($0)=\($1)"}).joined(separator:"&") -// if let url = URL(string: urlString + "?" + parameterString) { -// let request = URLRequest(url: url) -// do { -// let (json, error) = try Portal<(APIJSON?,Error?)>.open({ (portal) in -// self.dataTask(with: request, endingWith: { (json, reponse, error) in -// portal.close(with: (json, error)) -// }).resume() -// }) -// completion(json, error) -// } catch {} -// } else { completion(nil, GetJSONError.badURL(urlString + "?" + parameterString)) } -// } -// -// /// Synchronously fetches data from a URL -// /// -// /// - Parameters: -// /// - url: The URL the data will be fetched from. -// /// - parameters: The paramters for the URL. -// /// - Returns: The JSON is returned from the network request. -// /// - Throws: Any errors that occur in the Portal or in the network request. -// public func get(from url: String, withParameters parameters: [String: String])throws -> APIJSON { -// let requestResult = try Portal<(APIJSON?,Error?)>.open({ (portal) in -// self.get(from: url, withParameters: parameters, { (json, error) in portal.close(with: (json,error)) }) -// }) -// if let error = requestResult.1 { throw error } -// if requestResult.0 == nil { throw GetJSONError.noJSON } -// return requestResult.0! -// } -//} From 1db6acc19f3f95f3f197838a2ac6fc4ecc6e32d2 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Wed, 16 May 2018 20:49:57 -0500 Subject: [PATCH 47/66] Rewrote VersionSet command with Consoel API --- Package.resolved | 18 ++++++++++ Sources/Ether/VersionSet.swift | 61 +++++++++++++++------------------- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/Package.resolved b/Package.resolved index ab7ac06..1cd0dc1 100644 --- a/Package.resolved +++ b/Package.resolved @@ -46,6 +46,15 @@ "version": "3.0.5" } }, + { + "package": "JSON", + "repositoryURL": "https://github.com/soffes/JSON.git", + "state": { + "branch": null, + "revision": "7e79307da7605e493920535bcac0f810252f1f4b", + "version": "0.1.2" + } + }, { "package": "Manifest", "repositoryURL": "https://github.com/Ether-CLI/Manifest.git", @@ -118,6 +127,15 @@ "version": "1.0.0" } }, + { + "package": "SwiftySound", + "repositoryURL": "https://github.com/adamcichy/SwiftySound.git", + "state": { + "branch": null, + "revision": "cbf228cb643a7e6ed4d7e7f4012d247f2844f97b", + "version": "1.0.0" + } + }, { "package": "TemplateKit", "repositoryURL": "https://github.com/vapor/template-kit.git", diff --git a/Sources/Ether/VersionSet.swift b/Sources/Ether/VersionSet.swift index 0db06b0..f62661a 100644 --- a/Sources/Ether/VersionSet.swift +++ b/Sources/Ether/VersionSet.swift @@ -43,6 +43,33 @@ public final class VersionSet: Command { public var help: [String] = ["Changes the version of a single dependency"] public func run(using context: CommandContext) throws -> EventLoopFuture { + let updating = context.console.loadingBar(title: "Updating Package Version") + _ = updating.start(on: context.container) + + let package = try context.argument("name") + let version = try context.argument("version") + let versionLitteral = self.versionOption(from: context.options, with: version) + + guard let url = try Manifest.current.resolved().object.pins.filter({ $0.package == package }).first?.repositoryURL else { + throw EtherError(identifier: "pinNotFound", reason: "No pin entry found for package name '\(package)'") + } + guard let dependency = try Manifest.current.dependency(withURL: url) else { + throw EtherError(identifier: "packageNotFound", reason: "No package found with URL '\(url)'") + } + dependency.version = versionLitteral + try dependency.save() + + _ = Process.execute("swift", "package", "update") + updating.succeed() + + if let _ = context.options["xcode"] { + let xcodeBar = context.console.loadingBar(title: "Generating Xcode Project") + _ = xcodeBar.start(on: context.container) + _ = try Process.execute("swift", "package", "generate-xcodeproj") + xcodeBar.succeed() + _ = try Process.execute("/bin/sh", "-c", "open *.xcodeproj") + } + return context.container.eventLoop.newSucceededFuture(result: ()) } @@ -74,37 +101,3 @@ public final class VersionSet: Command { return .from(version) } } - -// public func run(arguments: [String]) throws { -// let updateBar = console.loadingBar(title: "Updating Package Version") -// updateBar.start() -// -// let package = try value("name", from: arguments) -// let version = try value("version", from: arguments) -// let versionLitteral = versionOption(from: arguments, with: version) -// -// let url = try Manifest.current.getPackageUrl(for: package) -// let manifest = try NSMutableString(string: Manifest.current.get()) -// let pattern = try NSRegularExpression( -// pattern: "(\\,?\\n *\\.package\\(url: *\"\(url)\", *)(.*?)(\\),?\\n)", -// options: [] -// ) -// pattern.replaceMatches(in: manifest, options: [], range: NSMakeRange(0, manifest.length), withTemplate: "$1\(versionLitteral)$3") -// try Manifest.current.write(String(manifest)) -// -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) -// -// updateBar.finish() -// -// if let _ = arguments.options["xcode"] { -// let xcodeBar = console.loadingBar(title: "Generating Xcode Project") -// xcodeBar.start() -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "generate-xcodeproj"]) -// xcodeBar.finish() -// try console.execute(program: "/bin/sh", arguments: ["-c", "open *.xcodeproj"], input: nil, output: nil, error: nil) -// } -// -// console.output("\(package) version was updated", style: .plain, newLine: true) -// } -//} From 58db977a788501f84a8ce06759001ee7966fd8ea Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 09:39:47 -0500 Subject: [PATCH 48/66] swift package update --- Package.resolved | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/Package.resolved b/Package.resolved index 1cd0dc1..9995f1b 100644 --- a/Package.resolved +++ b/Package.resolved @@ -15,8 +15,8 @@ "repositoryURL": "https://github.com/vapor/core.git", "state": { "branch": null, - "revision": "efe79e4f59445b661ba7e6511c2a0b80645c2e72", - "version": "3.1.6" + "revision": "a909eccc41941faac6fb9e511cdb9a5cb30a05de", + "version": "3.1.7" } }, { @@ -42,17 +42,8 @@ "repositoryURL": "https://github.com/vapor/http.git", "state": { "branch": null, - "revision": "9246340ae4c5310627099349fc74785267b55607", - "version": "3.0.5" - } - }, - { - "package": "JSON", - "repositoryURL": "https://github.com/soffes/JSON.git", - "state": { - "branch": null, - "revision": "7e79307da7605e493920535bcac0f810252f1f4b", - "version": "0.1.2" + "revision": "5e766f72d81ef5fe8805d704efdffd17e4906134", + "version": "3.0.6" } }, { @@ -96,8 +87,8 @@ "repositoryURL": "https://github.com/apple/swift-nio.git", "state": { "branch": null, - "revision": "a5db2a67515ad2b490ac5646db204a5edf939f47", - "version": "1.6.1" + "revision": "bad7c297427b5efedb96c4044f9e57b42881e9ea", + "version": "1.7.0" } }, { @@ -127,15 +118,6 @@ "version": "1.0.0" } }, - { - "package": "SwiftySound", - "repositoryURL": "https://github.com/adamcichy/SwiftySound.git", - "state": { - "branch": null, - "revision": "cbf228cb643a7e6ed4d7e7f4012d247f2844f97b", - "version": "1.0.0" - } - }, { "package": "TemplateKit", "repositoryURL": "https://github.com/vapor/template-kit.git", @@ -168,8 +150,8 @@ "repositoryURL": "https://github.com/vapor/vapor.git", "state": { "branch": null, - "revision": "8c73eebf7c41c7d8bf83ff87f550e0f97d6aadc4", - "version": "3.0.2" + "revision": "39b4d3fa36e58c6f7415c9da6c65a703bec34cea", + "version": "3.0.3" } }, { From ee9d91d13db0a61e9b0e70b4c2679ecaf233c449 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 09:43:26 -0500 Subject: [PATCH 49/66] Fixed call to .version method in VersionSet command; Added missing try to Proccess.execute call --- Sources/Ether/VersionSet.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Ether/VersionSet.swift b/Sources/Ether/VersionSet.swift index f62661a..025f7e6 100644 --- a/Sources/Ether/VersionSet.swift +++ b/Sources/Ether/VersionSet.swift @@ -48,7 +48,7 @@ public final class VersionSet: Command { let package = try context.argument("name") let version = try context.argument("version") - let versionLitteral = self.versionOption(from: context.options, with: version) + let versionLitteral = try self.version(from: context.options, with: version) guard let url = try Manifest.current.resolved().object.pins.filter({ $0.package == package }).first?.repositoryURL else { throw EtherError(identifier: "pinNotFound", reason: "No pin entry found for package name '\(package)'") @@ -59,7 +59,7 @@ public final class VersionSet: Command { dependency.version = versionLitteral try dependency.save() - _ = Process.execute("swift", "package", "update") + _ = try Process.execute("swift", "package", "update") updating.succeed() if let _ = context.options["xcode"] { From 07957a17abfff6664c5d57e369f55a0225ed3c14 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 10:29:33 -0500 Subject: [PATCH 50/66] Fixed Install comand pre-release question output loop, to break on a valid answer --- Package.resolved | 169 ------------------------------------ Sources/Ether/Install.swift | 9 +- 2 files changed, 5 insertions(+), 173 deletions(-) delete mode 100644 Package.resolved diff --git a/Package.resolved b/Package.resolved deleted file mode 100644 index 9995f1b..0000000 --- a/Package.resolved +++ /dev/null @@ -1,169 +0,0 @@ -{ - "object": { - "pins": [ - { - "package": "Console", - "repositoryURL": "https://github.com/vapor/console.git", - "state": { - "branch": null, - "revision": "5b9796d39f201b3dd06800437abd9d774a455e57", - "version": "3.0.2" - } - }, - { - "package": "Core", - "repositoryURL": "https://github.com/vapor/core.git", - "state": { - "branch": null, - "revision": "a909eccc41941faac6fb9e511cdb9a5cb30a05de", - "version": "3.1.7" - } - }, - { - "package": "Crypto", - "repositoryURL": "https://github.com/vapor/crypto.git", - "state": { - "branch": null, - "revision": "1b8c2ba5a42f1adf2aa812204678d8b16466fa59", - "version": "3.1.2" - } - }, - { - "package": "DatabaseKit", - "repositoryURL": "https://github.com/vapor/database-kit.git", - "state": { - "branch": null, - "revision": "0db303439e5ef8b6df50a2b6c4029edddee90cb0", - "version": "1.0.1" - } - }, - { - "package": "HTTP", - "repositoryURL": "https://github.com/vapor/http.git", - "state": { - "branch": null, - "revision": "5e766f72d81ef5fe8805d704efdffd17e4906134", - "version": "3.0.6" - } - }, - { - "package": "Manifest", - "repositoryURL": "https://github.com/Ether-CLI/Manifest.git", - "state": { - "branch": null, - "revision": "a1884894e75cde17bec40415df0b50292c4a5128", - "version": "0.4.4" - } - }, - { - "package": "Multipart", - "repositoryURL": "https://github.com/vapor/multipart.git", - "state": { - "branch": null, - "revision": "7778dcb62f3efa845e8e2808937bb347575ba7ce", - "version": "3.0.1" - } - }, - { - "package": "Routing", - "repositoryURL": "https://github.com/vapor/routing.git", - "state": { - "branch": null, - "revision": "3219e328491b0853b8554c5a694add344d2c6cfb", - "version": "3.0.1" - } - }, - { - "package": "Service", - "repositoryURL": "https://github.com/vapor/service.git", - "state": { - "branch": null, - "revision": "281a70b69783891900be31a9e70051b6fe19e146", - "version": "1.0.0" - } - }, - { - "package": "swift-nio", - "repositoryURL": "https://github.com/apple/swift-nio.git", - "state": { - "branch": null, - "revision": "bad7c297427b5efedb96c4044f9e57b42881e9ea", - "version": "1.7.0" - } - }, - { - "package": "swift-nio-ssl", - "repositoryURL": "https://github.com/apple/swift-nio-ssl.git", - "state": { - "branch": null, - "revision": "38955a5f806a952daf2b16fbfe9aa529749cf1dd", - "version": "1.1.0" - } - }, - { - "package": "swift-nio-ssl-support", - "repositoryURL": "https://github.com/apple/swift-nio-ssl-support.git", - "state": { - "branch": null, - "revision": "c02eec4e0e6d351cd092938cf44195a8e669f555", - "version": "1.0.0" - } - }, - { - "package": "swift-nio-zlib-support", - "repositoryURL": "https://github.com/apple/swift-nio-zlib-support.git", - "state": { - "branch": null, - "revision": "37760e9a52030bb9011972c5213c3350fa9d41fd", - "version": "1.0.0" - } - }, - { - "package": "TemplateKit", - "repositoryURL": "https://github.com/vapor/template-kit.git", - "state": { - "branch": null, - "revision": "43b57b5861d5181b906ac6411d28645e980bb638", - "version": "1.0.1" - } - }, - { - "package": "URLEncodedForm", - "repositoryURL": "https://github.com/vapor/url-encoded-form.git", - "state": { - "branch": null, - "revision": "57cf7fb9c1a1014c50bc05123684a9139ad44127", - "version": "1.0.3" - } - }, - { - "package": "Validation", - "repositoryURL": "https://github.com/vapor/validation.git", - "state": { - "branch": null, - "revision": "ab6c5a352d97c8687b91ed4963aef8e7cfe0795b", - "version": "2.0.0" - } - }, - { - "package": "Vapor", - "repositoryURL": "https://github.com/vapor/vapor.git", - "state": { - "branch": null, - "revision": "39b4d3fa36e58c6f7415c9da6c65a703bec34cea", - "version": "3.0.3" - } - }, - { - "package": "WebSocket", - "repositoryURL": "https://github.com/vapor/websocket.git", - "state": { - "branch": null, - "revision": "141cb4d3814dc8062cb0b2f43e72801b5dfcf272", - "version": "1.0.1" - } - } - ] - }, - "version": 1 -} diff --git a/Sources/Ether/Install.swift b/Sources/Ether/Install.swift index e328acb..2559e10 100644 --- a/Sources/Ether/Install.swift +++ b/Sources/Ether/Install.swift @@ -180,13 +180,14 @@ public final class Install: Command { if first.lowercased().contains("rc") || first.lowercased().contains("beta") || first.lowercased().contains("alpha") { let majorVersion = Int(String(first.first ?? "0")) ?? 0 if majorVersion > 0 && releases.count > 1 { - var answer: String + var answer: String = "replace" - repeat { + while true { answer = context.console.ask( ConsoleText(stringLiteral:"The latest version found (\(first)) is a pre-release. Would you like to use an earlier stable release? (y/n)") - ).lowercased() - } while answer != "y" || answer != "n" + ).lowercased() + if answer == "y" || answer == "n" { break } + } if answer == "y" { return releases.filter { Int(String($0.first ?? "0")) ?? 0 != majorVersion }.first ?? first From 8e680e883f924a301239f425cbb1caa37e8460a6 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 10:30:40 -0500 Subject: [PATCH 51/66] Deleted commented out Configuration.configPath property --- Sources/Ether/Configuration.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Sources/Ether/Configuration.swift b/Sources/Ether/Configuration.swift index 752372c..5bd99be 100644 --- a/Sources/Ether/Configuration.swift +++ b/Sources/Ether/Configuration.swift @@ -28,8 +28,6 @@ import Core import Bits public class Configuration: Command { -// public static let configPath = "/Library/Application\\ Support/Ether/config.json" - public var arguments: [CommandArgument] = [ CommandArgument.argument(name: "key", help: ["The configuration JSON key to set"]), CommandArgument.argument(name: "value", help: ["The new value for the key passed in"]) From 23f0df4af7e5205803d94004af718c30db3296b4 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 12:24:13 -0500 Subject: [PATCH 52/66] swift package update --- Package.resolved | 169 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 Package.resolved diff --git a/Package.resolved b/Package.resolved new file mode 100644 index 0000000..9995f1b --- /dev/null +++ b/Package.resolved @@ -0,0 +1,169 @@ +{ + "object": { + "pins": [ + { + "package": "Console", + "repositoryURL": "https://github.com/vapor/console.git", + "state": { + "branch": null, + "revision": "5b9796d39f201b3dd06800437abd9d774a455e57", + "version": "3.0.2" + } + }, + { + "package": "Core", + "repositoryURL": "https://github.com/vapor/core.git", + "state": { + "branch": null, + "revision": "a909eccc41941faac6fb9e511cdb9a5cb30a05de", + "version": "3.1.7" + } + }, + { + "package": "Crypto", + "repositoryURL": "https://github.com/vapor/crypto.git", + "state": { + "branch": null, + "revision": "1b8c2ba5a42f1adf2aa812204678d8b16466fa59", + "version": "3.1.2" + } + }, + { + "package": "DatabaseKit", + "repositoryURL": "https://github.com/vapor/database-kit.git", + "state": { + "branch": null, + "revision": "0db303439e5ef8b6df50a2b6c4029edddee90cb0", + "version": "1.0.1" + } + }, + { + "package": "HTTP", + "repositoryURL": "https://github.com/vapor/http.git", + "state": { + "branch": null, + "revision": "5e766f72d81ef5fe8805d704efdffd17e4906134", + "version": "3.0.6" + } + }, + { + "package": "Manifest", + "repositoryURL": "https://github.com/Ether-CLI/Manifest.git", + "state": { + "branch": null, + "revision": "a1884894e75cde17bec40415df0b50292c4a5128", + "version": "0.4.4" + } + }, + { + "package": "Multipart", + "repositoryURL": "https://github.com/vapor/multipart.git", + "state": { + "branch": null, + "revision": "7778dcb62f3efa845e8e2808937bb347575ba7ce", + "version": "3.0.1" + } + }, + { + "package": "Routing", + "repositoryURL": "https://github.com/vapor/routing.git", + "state": { + "branch": null, + "revision": "3219e328491b0853b8554c5a694add344d2c6cfb", + "version": "3.0.1" + } + }, + { + "package": "Service", + "repositoryURL": "https://github.com/vapor/service.git", + "state": { + "branch": null, + "revision": "281a70b69783891900be31a9e70051b6fe19e146", + "version": "1.0.0" + } + }, + { + "package": "swift-nio", + "repositoryURL": "https://github.com/apple/swift-nio.git", + "state": { + "branch": null, + "revision": "bad7c297427b5efedb96c4044f9e57b42881e9ea", + "version": "1.7.0" + } + }, + { + "package": "swift-nio-ssl", + "repositoryURL": "https://github.com/apple/swift-nio-ssl.git", + "state": { + "branch": null, + "revision": "38955a5f806a952daf2b16fbfe9aa529749cf1dd", + "version": "1.1.0" + } + }, + { + "package": "swift-nio-ssl-support", + "repositoryURL": "https://github.com/apple/swift-nio-ssl-support.git", + "state": { + "branch": null, + "revision": "c02eec4e0e6d351cd092938cf44195a8e669f555", + "version": "1.0.0" + } + }, + { + "package": "swift-nio-zlib-support", + "repositoryURL": "https://github.com/apple/swift-nio-zlib-support.git", + "state": { + "branch": null, + "revision": "37760e9a52030bb9011972c5213c3350fa9d41fd", + "version": "1.0.0" + } + }, + { + "package": "TemplateKit", + "repositoryURL": "https://github.com/vapor/template-kit.git", + "state": { + "branch": null, + "revision": "43b57b5861d5181b906ac6411d28645e980bb638", + "version": "1.0.1" + } + }, + { + "package": "URLEncodedForm", + "repositoryURL": "https://github.com/vapor/url-encoded-form.git", + "state": { + "branch": null, + "revision": "57cf7fb9c1a1014c50bc05123684a9139ad44127", + "version": "1.0.3" + } + }, + { + "package": "Validation", + "repositoryURL": "https://github.com/vapor/validation.git", + "state": { + "branch": null, + "revision": "ab6c5a352d97c8687b91ed4963aef8e7cfe0795b", + "version": "2.0.0" + } + }, + { + "package": "Vapor", + "repositoryURL": "https://github.com/vapor/vapor.git", + "state": { + "branch": null, + "revision": "39b4d3fa36e58c6f7415c9da6c65a703bec34cea", + "version": "3.0.3" + } + }, + { + "package": "WebSocket", + "repositoryURL": "https://github.com/vapor/websocket.git", + "state": { + "branch": null, + "revision": "141cb4d3814dc8062cb0b2f43e72801b5dfcf272", + "version": "1.0.1" + } + } + ] + }, + "version": 1 +} From 2c43f164ae9ff2cbe10a98d76d1350d2d94890fa Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 12:24:48 -0500 Subject: [PATCH 53/66] Finished porting Search command to Console 3 API --- Sources/Ether/Search.swift | 110 ++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 63 deletions(-) diff --git a/Sources/Ether/Search.swift b/Sources/Ether/Search.swift index a966ac6..b0002f3 100644 --- a/Sources/Ether/Search.swift +++ b/Sources/Ether/Search.swift @@ -20,7 +20,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +import Helpers import Command +import Console +import Vapor public final class Search: Command { public var arguments: [CommandArgument] = [ @@ -31,75 +34,56 @@ public final class Search: Command { CommandOption.value(name: "max-results", default: "20", help: [ "The maximum number of results that will be returned.", "This defaults to 20." - ]), - CommandOption.value(name: "sort", default: "moststarred", help: [ - "The sorting method to use:", - "moststarred (Most Starred)", - "leaststarred (Least Starred)", - "mostrecent (Most Recent)", - "leastrecent (Least Recent)", - "The default value is moststarred." ]) ] public var help: [String] = ["Searches for availible packages."] public func run(using context: CommandContext) throws -> EventLoopFuture { - return context.container.eventLoop.newSucceededFuture(result: ()) + let searching = context.console.loadingBar(title: "Searching") + _ = searching.start(on: context.container) + + let client = try context.container.make(Client.self) + let name = try context.argument("name") + let maxResults = context.options["max-results"] ?? "20" + let config = try Configuration.get() + + guard let max = Int(maxResults), max <= 100 && max > 0 else { + throw EtherError(identifier: "badMaxResults", reason: "`max-results` value must be an integer, less than or equal to 100, and greater than 0") + } + guard let token = config.accessToken else { + throw EtherError( + identifier: "noAccessToken", + reason: "No access token in configuration. Run `ether config access-token `. The token should have permissions to access public repositories" + ) + } + + let response = client.get("https://package.vapor.cloud/packages/search?name=\(name)&limit=\(max)", headers: ["Authorization": "Bearer \(token)"]) + return response.flatMap(to: [String: [PackageDescription]].self) { response in + return try response.content.decode([String: [PackageDescription]].self) + }.map(to: Void.self) { json in + guard let packages = json["repositories"] else { + throw EtherError(identifier: "badResponseStructure", reason: "Unable to parse package representations from JSON response") + } + packages.forEach { package in + package.print(on: context) + context.console.print() + } + } } } -// -// public func run(arguments: [String]) throws { -// let searchingBar = console.loadingBar(title: "Searching") -// searchingBar.start() -// -// let name = try value("name", from: arguments) -// let maxResults = arguments.options["max-results"] ?? "20" -// let sortMethod = arguments.options["sort"] ?? "moststarred" -// -// func fail(_ message: String) -> Error { -// searchingBar.fail() -// return EtherError.fail(message) -// } -// -// var totalResults: Int? -// var maxedResults: Bool? -// var packages: [(name: String?, description: String?)]? -// -// let json = try self.client.get(from: self.baseURL + name, withParameters: [self.sort: sortMethod, self.results: maxResults]) -// -// guard let data = json["data"] as? APIJSON else { throw fail("Bad JSON key") } -// guard let hits = data["hits"] as? APIJSON else { throw fail("Bad JSON key") } -// guard let results = hits["hits"] as? [APIJSON] else { throw fail("Bad JSON key") } -// -// packages = try results.map { (result) -> (name: String?, description: String?) in -// guard let source = result["_source"] as? APIJSON else { throw fail("Bad JSON key") } -// return (name: source["package_full_name"] as? String, description: source["description"] as? String) -// } -// -// maxedResults = Int(String(describing: hits["total"] ?? 0 as AnyObject))! > Int(maxResults)! -// totalResults = Int(String(describing: hits["total"] ?? 0 as AnyObject)) -// -// searchingBar.finish() -// -// self.console.output("Total results: \(totalResults ?? 0)", style: .info, newLine: true) -// -// if let maxedResults = maxedResults { -// if maxedResults { -// self.console.output("Not all results are shown.", style: .info, newLine: true) -// } -// } -// if (totalResults ?? 0) > 0 { -// console.output(String(repeating: "-", count: console.size.width), style: .info, newLine: true) -// console.output("", style: .info, newLine: true) -// } -// if let packages = packages { -// for package in packages { -// self.console.output("\(package.name ?? "N/A"): ", style: .custom(.green), newLine: false) -// self.console.output("\(package.description ?? "N/A")", style: .custom(.white), newLine: true) -// console.output("", style: .info, newLine: true) -// } -// } -// } -//} +struct PackageDescription: Codable { + let nameWithOwner: String + let description: String + let license: String + let stargazers: Int + + func print(on context: CommandContext) { + context.console.output(self.nameWithOwner + ": ", style: .info, newLine: false) + context.console.print(self.description) + context.console.print("License: " + self.license) + context.console.print("Stars: " + String(self.stargazers)) + + } +} From da3119c292c98ab443c99ebfe8e48e1dba7c6573 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 12:52:53 -0500 Subject: [PATCH 54/66] Updated VersionLatest command to Console 3 API --- Sources/Ether/VersionLatest.swift | 91 ++++++++++++++++--------------- 1 file changed, 48 insertions(+), 43 deletions(-) diff --git a/Sources/Ether/VersionLatest.swift b/Sources/Ether/VersionLatest.swift index 8e34399..8dd2598 100644 --- a/Sources/Ether/VersionLatest.swift +++ b/Sources/Ether/VersionLatest.swift @@ -20,8 +20,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +import Foundation +import Manifest import Helpers import Command +import Vapor public final class VersionLatest: Command { public var arguments: [CommandArgument] = [] @@ -33,48 +36,50 @@ public final class VersionLatest: Command { public var help: [String] = ["Updates all packeges to the latest version"] public func run(using context: CommandContext) throws -> EventLoopFuture { - return context.container.eventLoop.newSucceededFuture(result: ()) + let updating = context.console.loadingBar(title: "Updating Version Versions") + _ = updating.start(on: context.container) + + let regex = try NSRegularExpression(pattern: ".*?\\.com\\/(.*?)\\.git", options: []) + let client = try context.container.make(Client.self) + + guard let token = try Configuration.get().accessToken else { + throw EtherError( + identifier: "noAccessToken", + reason: "No access token in configuration. Run `ether config access-token `. The token should have permissions to access public repositories" + ) + } + + let packageNames = try Manifest.current.dependencies().compactMap { dependency -> (fullName: String, url: String)? in + guard let result = regex.firstMatch(in: dependency.url, options: [], range: NSMakeRange(0, dependency.url.utf8.count)) else { return nil } + return (regex.replacementString(for: result, in: dependency.url, offset: 0, template: "$1"), dependency.url) + } + let versions = packageNames.map { $0.fullName }.map { name in + return client.get("https://package.vapor.cloud/packages/\(name)/releases", headers: ["Authorization": "Bearer \(token)"]).flatMap { response in + return try response.content.decode([String].self) + }.map { releases in releases.first } + }.flatten(on: context.container) + + return versions.map(to: Void.self) { versions in + try zip(packageNames, versions).forEach { packageVersion in + let (names, version) = packageVersion + let dependency = try Manifest.current.dependency(withURL: names.url) + if let version = version { + dependency?.version = .from(version) + } + try dependency?.save() + } + + _ = try Process.execute("swift", "package", "update") + updating.succeed() + + if let _ = context.options["xcode"] { + let xcodeBar = context.console.loadingBar(title: "Generating Xcode Project") + _ = xcodeBar.start(on: context.container) + + _ = try Process.execute("swift", "package", "generate-xcodeproj") + xcodeBar.succeed() + _ = try Process.execute("sh", "-c", "open *.xcodeproj") + } + } } } - -// public let id = "latest" -// public let baseURL = "https://packagecatalog.com/data/package" -// -// public func run(arguments: [String]) throws { -// let updateBar = console.loadingBar(title: "Updating Package Versions") -// updateBar.start() -// -// let fileManager = FileManager.default -// let manifest = try Manifest.current.get() -// let nsManifest = NSMutableString(string: manifest) -// let versionPattern = try NSRegularExpression(pattern: "(.package\\(url:\\s*\".*?\\.com\\/(.*?)\\.git\",\\s*)(.*?)(\\),?\\n)", options: []) -// let matches = versionPattern.matches(in: manifest, options: [], range: NSMakeRange(0, manifest.utf8.count)) -// let packageNames = matches.map { match -> String in -// let name = versionPattern.replacementString(for: match, in: manifest, offset: 0, template: "$2") -// return name -// } -// let packageVersions = try packageNames.map { name -> String in -// return try Manifest.current.getPackageData(for: name).version -// } -// -// try zip(packageVersions, packageNames).forEach { (arg) in -// let (version, name) = arg -// let pattern = try NSRegularExpression(pattern: "(.package\\(url:\\s*\".*?\\.com\\/\(name)\\.git\",\\s*)(\\.?\\w+(\\(|:)\\s*\"[\\w\\.]+\"\\)?)(\\))", options: []) -// pattern.replaceMatches(in: nsManifest, options: [], range: NSMakeRange(0, nsManifest.length), withTemplate: "$1.exact(\"\(version)\"))") -// } -// -// try String(nsManifest).data(using: .utf8)?.write(to: URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift")!) -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) -// -// updateBar.finish() -// -// if let _ = arguments.options["xcode"] { -// let xcodeBar = console.loadingBar(title: "Generating Xcode Project") -// xcodeBar.start() -// _ = try console.backgroundExecute(program: "swift", arguments: ["package", "generate-xcodeproj"]) -// xcodeBar.finish() -// try console.execute(program: "/bin/sh", arguments: ["-c", "open *.xcodeproj"], input: nil, output: nil, error: nil) -// } -// } -//} From b5a3400f49dd558770ef77cac77dba628321e83d Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 14:37:42 -0500 Subject: [PATCH 55/66] Registered all commands; Added public initializers to command classes w/o them --- Sources/Ether/New.swift | 2 ++ Sources/Ether/Remove.swift | 2 ++ Sources/Ether/Search.swift | 2 ++ Sources/Ether/Template.swift | 2 ++ Sources/Ether/Update.swift | 2 ++ Sources/Ether/VersionAll.swift | 2 ++ Sources/Ether/VersionLatest.swift | 2 ++ Sources/Ether/VersionSet.swift | 2 ++ Sources/Executable/main.swift | 18 ++++++++++++++++++ 9 files changed, 34 insertions(+) diff --git a/Sources/Ether/New.swift b/Sources/Ether/New.swift index 1b4519b..cec15f0 100644 --- a/Sources/Ether/New.swift +++ b/Sources/Ether/New.swift @@ -38,6 +38,8 @@ public final class New: Command { public var help: [String] = ["Creates a new project"] + public init() {} + public func run(using context: CommandContext) throws -> EventLoopFuture { let newProject = context.console.loadingBar(title: "Generating Project") _ = newProject.start(on: context.container) diff --git a/Sources/Ether/Remove.swift b/Sources/Ether/Remove.swift index 283d8d2..d494c46 100644 --- a/Sources/Ether/Remove.swift +++ b/Sources/Ether/Remove.swift @@ -35,6 +35,8 @@ public final class Remove: Command { public var help: [String] = ["Removes a package from the manifest and uninstalls it"] + public init() {} + public func run(using context: CommandContext) throws -> EventLoopFuture { let removing = context.console.loadingBar(title: "Removing Dependency") _ = removing.start(on: context.container) diff --git a/Sources/Ether/Search.swift b/Sources/Ether/Search.swift index b0002f3..19ae71e 100644 --- a/Sources/Ether/Search.swift +++ b/Sources/Ether/Search.swift @@ -39,6 +39,8 @@ public final class Search: Command { public var help: [String] = ["Searches for availible packages."] + public init() {} + public func run(using context: CommandContext) throws -> EventLoopFuture { let searching = context.console.loadingBar(title: "Searching") _ = searching.start(on: context.container) diff --git a/Sources/Ether/Template.swift b/Sources/Ether/Template.swift index 72535a9..533fa18 100644 --- a/Sources/Ether/Template.swift +++ b/Sources/Ether/Template.swift @@ -36,6 +36,8 @@ public final class Template: Command { public var help: [String] = ["Creates and stores a template for use as the starting point of a project."] + public init() {} + public func run(using context: CommandContext) throws -> EventLoopFuture { let name = try context.argument("name") let removeTemplate = context.options["remove"] == nil ? false : true diff --git a/Sources/Ether/Update.swift b/Sources/Ether/Update.swift index 9649bf7..ce31cdc 100644 --- a/Sources/Ether/Update.swift +++ b/Sources/Ether/Update.swift @@ -32,6 +32,8 @@ public final class Update: Command { public var help: [String] = ["Updates a project's dependencies."] + public init() {} + public func run(using context: CommandContext) throws -> EventLoopFuture { if context.options["ether"] != nil { let updating = context.console.loadingBar(title: "Updating Ether") diff --git a/Sources/Ether/VersionAll.swift b/Sources/Ether/VersionAll.swift index c1ed40f..a2e0bc2 100644 --- a/Sources/Ether/VersionAll.swift +++ b/Sources/Ether/VersionAll.swift @@ -30,6 +30,8 @@ public final class VersionAll: Command { public var help: [String] = ["Outputs the name of each package installed and its version"] + public init() {} + public func run(using context: CommandContext) throws -> EventLoopFuture { context.console.output("Getting Package Data...", style: .success) diff --git a/Sources/Ether/VersionLatest.swift b/Sources/Ether/VersionLatest.swift index 8dd2598..df434b4 100644 --- a/Sources/Ether/VersionLatest.swift +++ b/Sources/Ether/VersionLatest.swift @@ -35,6 +35,8 @@ public final class VersionLatest: Command { public var help: [String] = ["Updates all packeges to the latest version"] + public init() {} + public func run(using context: CommandContext) throws -> EventLoopFuture { let updating = context.console.loadingBar(title: "Updating Version Versions") _ = updating.start(on: context.container) diff --git a/Sources/Ether/VersionSet.swift b/Sources/Ether/VersionSet.swift index 025f7e6..ada67e5 100644 --- a/Sources/Ether/VersionSet.swift +++ b/Sources/Ether/VersionSet.swift @@ -42,6 +42,8 @@ public final class VersionSet: Command { public var help: [String] = ["Changes the version of a single dependency"] + public init() {} + public func run(using context: CommandContext) throws -> EventLoopFuture { let updating = context.console.loadingBar(title: "Updating Package Version") _ = updating.start(on: context.container) diff --git a/Sources/Executable/main.swift b/Sources/Executable/main.swift index 168bc44..5f5d65e 100644 --- a/Sources/Executable/main.swift +++ b/Sources/Executable/main.swift @@ -26,10 +26,28 @@ import Ether var services = Services.default() +let versions = Commands( + commands: [ + "all": VersionAll(), + "latest": VersionLatest(), + "set": VersionSet() + ], + defaultCommand: "all" +).group(help: [ + "For interacting with dependency versions" +]) + var commands = CommandConfig() commands.use(Configuration(), as: "config") commands.use(FixInstall(), as: "fix-install") commands.use(Install(), as: "install") +commands.use(New(), as: "new") +commands.use(Remove(), as: "remove") +commands.use(Search(), as: "search") +commands.use(Template(), as: "template") +commands.use(Update(), as: "update") +commands.use(versions, as: "version") + services.register(commands) do { From dc25b3364afce9bb2d685a64efd14b307d35acc1 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 15:19:47 -0500 Subject: [PATCH 56/66] Added check for top-level version flag --- Sources/Executable/main.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Sources/Executable/main.swift b/Sources/Executable/main.swift index 5f5d65e..c5fdc95 100644 --- a/Sources/Executable/main.swift +++ b/Sources/Executable/main.swift @@ -24,6 +24,15 @@ import Console import Vapor import Ether +let version = "2018.05.18" + +let arguments = CommandLine.arguments +if arguments.count == 2, arguments[1] == "--version" || arguments[1] == "-v" { + let terminal = Terminal() + terminal.output("Ether Version: \(version)", style: .info, newLine: true) + exit(0) +} + var services = Services.default() let versions = Commands( From 03a8a4b07629e8e5a4e7c214894c5f8712bbf1d2 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 15:22:10 -0500 Subject: [PATCH 57/66] Added whiteapce between package name and version in VersionAll command --- Sources/Ether/VersionAll.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Sources/Ether/VersionAll.swift b/Sources/Ether/VersionAll.swift index a2e0bc2..984551d 100644 --- a/Sources/Ether/VersionAll.swift +++ b/Sources/Ether/VersionAll.swift @@ -33,12 +33,10 @@ public final class VersionAll: Command { public init() {} public func run(using context: CommandContext) throws -> EventLoopFuture { - context.console.output("Getting Package Data...", style: .success) - let pins = try Manifest.current.resolved().object.pins pins.forEach { package in - context.console.output(package.package, style: .success, newLine: false) + context.console.output(package.package + ": ", style: .success, newLine: false) let version: String if let number = package.state.version { From 223c6e48b176f9ef6aa8426b9c08388ea95b95c2 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 15:35:11 -0500 Subject: [PATCH 58/66] =?UTF-8?q?Verify=20valid=20version=20tag=20nefore?= =?UTF-8?q?=20injection=20in=20VersionLatest=20command.=20Tested=20it=20?= =?UTF-8?q?=F0=9F=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Package.swift | 8 ++++---- Sources/Ether/VersionLatest.swift | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/Package.swift b/Package.swift index e2ac9f2..380ba27 100644 --- a/Package.swift +++ b/Package.swift @@ -5,10 +5,10 @@ import PackageDescription let package = Package( name: "Ether", dependencies: [ - .package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"), - .package(url: "https://github.com/vapor/console.git", from: "3.0.0"), - .package(url: "https://github.com/vapor/core.git", from: "3.0.0"), - .package(url: "https://github.com/Ether-CLI/Manifest.git", from: "0.1.0") + .package(url: "https://github.com/vapor/vapor.git", from: "3.0.3"), + .package(url: "https://github.com/vapor/console.git", from: "3.0.2"), + .package(url: "https://github.com/vapor/core.git", from: "3.1.7"), + .package(url: "https://github.com/Ether-CLI/Manifest.git", from: "0.4.4") ], targets: [ .target(name: "Helpers", dependencies: ["Core", "Console"]), diff --git a/Sources/Ether/VersionLatest.swift b/Sources/Ether/VersionLatest.swift index df434b4..e44b3a0 100644 --- a/Sources/Ether/VersionLatest.swift +++ b/Sources/Ether/VersionLatest.swift @@ -41,7 +41,8 @@ public final class VersionLatest: Command { let updating = context.console.loadingBar(title: "Updating Version Versions") _ = updating.start(on: context.container) - let regex = try NSRegularExpression(pattern: ".*?\\.com\\/(.*?)\\.git", options: []) + let namePattern = try NSRegularExpression(pattern: ".*?\\.com\\/(.*?)\\.git", options: []) + let tagPattern = try NSRegularExpression(pattern: "v?\\d+(?:\\.\\d+)?(?:\\.\\d+)?", options: []) let client = try context.container.make(Client.self) guard let token = try Configuration.get().accessToken else { @@ -52,13 +53,21 @@ public final class VersionLatest: Command { } let packageNames = try Manifest.current.dependencies().compactMap { dependency -> (fullName: String, url: String)? in - guard let result = regex.firstMatch(in: dependency.url, options: [], range: NSMakeRange(0, dependency.url.utf8.count)) else { return nil } - return (regex.replacementString(for: result, in: dependency.url, offset: 0, template: "$1"), dependency.url) + guard let result = namePattern.firstMatch(in: dependency.url, options: [], range: NSMakeRange(0, dependency.url.utf8.count)) else { return nil } + return (namePattern.replacementString(for: result, in: dependency.url, offset: 0, template: "$1"), dependency.url) } let versions = packageNames.map { $0.fullName }.map { name in return client.get("https://package.vapor.cloud/packages/\(name)/releases", headers: ["Authorization": "Bearer \(token)"]).flatMap { response in return try response.content.decode([String].self) - }.map { releases in releases.first } + }.map { releases -> String? in + for tag in releases { + let tagRange = NSMakeRange(0, tag.utf8.count) + if tagRange == tagPattern.rangeOfFirstMatch(in: tag, options: [], range: tagRange) { + return tag + } + } + return nil + } }.flatten(on: context.container) return versions.map(to: Void.self) { versions in From a2b2e11bcbd26be26d4b0e33ca80b0b44ac812ed Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 15:37:41 -0500 Subject: [PATCH 59/66] Fixed template deletion 'rm' flag {'m' => 'f'} --- Sources/Ether/Template.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Ether/Template.swift b/Sources/Ether/Template.swift index 533fa18..efb1dda 100644 --- a/Sources/Ether/Template.swift +++ b/Sources/Ether/Template.swift @@ -55,7 +55,7 @@ public final class Template: Command { if removeTemplate { if !directoryExists { throw EtherError(identifier: "templateNotFound", reason: "No template with the name '\(name)' was found") } - _ = try Process.execute("rm", ["-rm", "\(defaultPath)/\(name)"]) + _ = try Process.execute("rm", ["-rf", "\(defaultPath)/\(name)"]) } else { if directoryExists { throw EtherError(identifier: "templateAlreadyExists", reason: "A template with the name '\(name)' was found") } let current = manager.currentDirectoryPath + "/." From 44954c23b7204c7418710824004101e4cd66f777 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 15:43:53 -0500 Subject: [PATCH 60/66] Fixed decoding package data in Search command with optional properties and decoding single repos array --- Sources/Ether/Search.swift | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/Sources/Ether/Search.swift b/Sources/Ether/Search.swift index 19ae71e..90f3f51 100644 --- a/Sources/Ether/Search.swift +++ b/Sources/Ether/Search.swift @@ -61,12 +61,10 @@ public final class Search: Command { } let response = client.get("https://package.vapor.cloud/packages/search?name=\(name)&limit=\(max)", headers: ["Authorization": "Bearer \(token)"]) - return response.flatMap(to: [String: [PackageDescription]].self) { response in - return try response.content.decode([String: [PackageDescription]].self) - }.map(to: Void.self) { json in - guard let packages = json["repositories"] else { - throw EtherError(identifier: "badResponseStructure", reason: "Unable to parse package representations from JSON response") - } + return response.flatMap(to: [PackageDescription].self) { response in + searching.succeed() + return response.content.get([PackageDescription].self, at: "repositories") + }.map(to: Void.self) { packages in packages.forEach { package in package.print(on: context) context.console.print() @@ -77,15 +75,24 @@ public final class Search: Command { struct PackageDescription: Codable { let nameWithOwner: String - let description: String - let license: String - let stargazers: Int + let description: String? + let license: String? + let stargazers: Int? func print(on context: CommandContext) { - context.console.output(self.nameWithOwner + ": ", style: .info, newLine: false) - context.console.print(self.description) - context.console.print("License: " + self.license) - context.console.print("Stars: " + String(self.stargazers)) + if let description = self.description { + context.console.info(nameWithOwner + ": ", newLine: false) + context.console.print(description) + } else { + context.console.info(self.nameWithOwner) + } + if let license = self.license { + context.console.print("License: " + license) + } + + if let stars = self.stargazers { + context.console.print("Stars: " + String(stars)) + } } } From c074e0d077d8bc4dec0a97850e8dc55030df1ca5 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 16:17:06 -0500 Subject: [PATCH 61/66] Delete dependency from targets in Remove command --- Sources/Ether/Remove.swift | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Sources/Ether/Remove.swift b/Sources/Ether/Remove.swift index d494c46..f866e6b 100644 --- a/Sources/Ether/Remove.swift +++ b/Sources/Ether/Remove.swift @@ -44,10 +44,17 @@ public final class Remove: Command { let name = try context.argument("name") let pinCount = try Manifest.current.resolved().object.pins.count - guard let url = try Manifest.current.resolved().object.pins.filter({ $0.package == name }).first?.repositoryURL else { + guard let pin = try Manifest.current.resolved().object.pins.filter({ $0.package == name }).first else { throw EtherError(identifier: "pinNotFound", reason: "No package was found with the name '\(name)'") } - try Manifest.current.dependency(withURL: url)?.delete() + + try Manifest.current.dependency(withURL: pin.repositoryURL)?.delete() + try Manifest.current.targets().filter { $0.dependencies.contains(pin.package) }.forEach { target in + if let index = target.dependencies.index(of: pin.package) { + target.dependencies.remove(at: index) + try target.save() + } + } _ = try Process.execute("swift", ["package", "update"]) _ = try Process.execute("swift", ["package", "resolve"]) From 87f64746a4f4ee066f88c4d0607775574c45052e Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 16:28:36 -0500 Subject: [PATCH 62/66] Updated Manifest version to 0.4.5 --- Package.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.resolved b/Package.resolved index 9995f1b..5dfdf09 100644 --- a/Package.resolved +++ b/Package.resolved @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/Ether-CLI/Manifest.git", "state": { "branch": null, - "revision": "a1884894e75cde17bec40415df0b50292c4a5128", - "version": "0.4.4" + "revision": "a200f9a6af998f787ac4ea7b92802f7b139d499f", + "version": "0.4.5" } }, { From 7112006f87c4694075cc1877d23ac38b74da0306 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 16:33:31 -0500 Subject: [PATCH 63/66] Added entry for 2018.05.18 to CHANGELOG --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fe1b7a..46bf3bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## [2018.05.18] + +### Updated +- Rewrote whole CLI with Console 3, Manifest, and the vapor-community/PackageCatalogAPI. + ## [1.10.0] 2018-02-18 ### Added From cd55f1c0d8a83bc2d6fb72c991669e82ccdba28c Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 16:36:16 -0500 Subject: [PATCH 64/66] Moved GitHub issue template to .github/ISSUE_TEMPLATE directory --- ISSUE_TEMPLATE.md => .github/ISSUE_TEMPLATE/issue_template.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ISSUE_TEMPLATE.md => .github/ISSUE_TEMPLATE/issue_template.md (100%) diff --git a/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE/issue_template.md similarity index 100% rename from ISSUE_TEMPLATE.md rename to .github/ISSUE_TEMPLATE/issue_template.md From 9bcf645c107da7bc0b2f2e9aac68ca43a40d4b35 Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 16:49:23 -0500 Subject: [PATCH 65/66] Created CircleCI configuration --- circle.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 circle.yml diff --git a/circle.yml b/circle.yml new file mode 100644 index 0000000..fbfc50f --- /dev/null +++ b/circle.yml @@ -0,0 +1,30 @@ +version: 2 + +jobs: + macos: + macos: + xcode: "9.2" + steps: + - checkout + - run: swift build + - run: swift test + linux: + docker: + - image: codevapor/swift:4.1 + steps: + - checkout + - run: + name: Compile code + command: swift build + - run: + name: Run unit tests + command: swift test + + linux-release: + docker: + - image: codevapor/swift:4.1 + steps: + - checkout + - run: + name: Compile code with optimizations + command: swift build -c release From 6e7b81e3540bc6053c69c3ad4adf9378ba3628cd Mon Sep 17 00:00:00 2001 From: Caleb Kleveter Date: Fri, 18 May 2018 17:00:32 -0500 Subject: [PATCH 66/66] Removed macOS build from CircleCI --- circle.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/circle.yml b/circle.yml index fbfc50f..f631f03 100644 --- a/circle.yml +++ b/circle.yml @@ -1,13 +1,6 @@ version: 2 jobs: - macos: - macos: - xcode: "9.2" - steps: - - checkout - - run: swift build - - run: swift test linux: docker: - image: codevapor/swift:4.1