diff --git a/.swift-version b/.swift-version index 4d54dad..7d5c902 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -4.0.2 +4.1 diff --git a/CHANGELOG.md b/CHANGELOG.md index c75ccac..9fe1b7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [1.10.0] 2018-02-18 + +### Added +- `ether version set` command to update the version of a single package. + +### Updated +- The RegEx for any command that matches the version of a package, so it handles any version type for a package. + ## [1.9.2] 2017-11-27 ### Fixed diff --git a/Sources/Ether/FixInstall.swift b/Sources/Ether/FixInstall.swift index 99d0440..beec04a 100644 --- a/Sources/Ether/FixInstall.swift +++ b/Sources/Ether/FixInstall.swift @@ -48,11 +48,11 @@ public class FixInstall: Command { fixBar.start() _ = try console.backgroundExecute(program: "rm", arguments: ["-rf", ".build"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "--enable-prefetching", "update"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "--enable-prefetching", "resolve"]) + _ = 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", "--enable-prefetching"]) + _ = try console.backgroundExecute(program: "swift", arguments: ["build"]) } fixBar.finish() diff --git a/Sources/Ether/Install.swift b/Sources/Ether/Install.swift index dba290f..89d7eaf 100644 --- a/Sources/Ether/Install.swift +++ b/Sources/Ether/Install.swift @@ -111,8 +111,8 @@ public final class Install: Command { 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", "--enable-prefetching", "update"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "--enable-prefetching", "resolve"]) + _ = 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) @@ -135,7 +135,7 @@ public final class Install: Command { if let _ = arguments.options["xcode"] { let xcodeBar = console.loadingBar(title: "Generating Xcode Project") xcodeBar.start() - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "--enable-prefetching", "generate-xcodeproj"]) + _ = 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/Remove.swift b/Sources/Ether/Remove.swift index 54ca389..c4eaa33 100644 --- a/Sources/Ether/Remove.swift +++ b/Sources/Ether/Remove.swift @@ -54,7 +54,7 @@ public final class Remove: Command { let name = try value("name", from: arguments) let url = try Manifest.current.getPackageUrl(for: name) - let regex = try NSRegularExpression(pattern: "\\,?\\n *\\.package\\(url: *\"\(url)\", *\\.?\\w+(:|\\() *\"([\\d\\.]+)\"\\)?\\),?", options: .caseInsensitive) + let regex = try NSRegularExpression(pattern: "(\\,?\\n *\\.package\\(url: *\"\(url)\", *)(.*?)(?=,?\n)", options: .caseInsensitive) let oldPins = try Manifest.current.getPins() let packageString = try Manifest.current.get() @@ -69,8 +69,8 @@ public final class Remove: Command { do { try String(mutableString).data(using: .utf8)?.write(to: URL(string: "file:\(manager.currentDirectoryPath)/Package.swift")!) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "--enable-prefetching", "update"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "--enable-prefetching", "resolve"]) + _ = try console.backgroundExecute(program: "swift", arguments: ["package", "update"]) + _ = try console.backgroundExecute(program: "swift", arguments: ["package", "resolve"]) } catch let error { removingProgressBar.fail() throw error @@ -84,7 +84,7 @@ public final class Remove: Command { if let _ = arguments.options["xcode"] { let xcodeBar = console.loadingBar(title: "Generating Xcode Project") xcodeBar.start() - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "--enable-prefetching", "generate-xcodeproj"]) + _ = 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/Update.swift b/Sources/Ether/Update.swift index 52f75ec..edc1f3b 100644 --- a/Sources/Ether/Update.swift +++ b/Sources/Ether/Update.swift @@ -57,15 +57,15 @@ public final class Update: Command { let updateBar = console.loadingBar(title: "Updating Packages") updateBar.start() _ = try console.backgroundExecute(program: "rm", arguments: ["-rf", ".build"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "--enable-prefetching", "update"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "--enable-prefetching", "resolve"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["build", "--enable-prefetching"]) + _ = 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", "--enable-prefetching", "generate-xcodeproj"]) + _ = 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/VersionAll.swift b/Sources/Ether/VersionAll.swift index a923dec..880a913 100644 --- a/Sources/Ether/VersionAll.swift +++ b/Sources/Ether/VersionAll.swift @@ -43,23 +43,12 @@ public final class VersionAll: Command { let fetchingDataBar = console.loadingBar(title: "Getting Package Data") fetchingDataBar.start() - let manager = FileManager.default - - guard let packageData = manager.contents(atPath: "\(manager.currentDirectoryPath)/Package.resolved") else { - throw fail(bar: fetchingDataBar, with: "Make sure you are in the root of an SPM project.") - } - - guard let packageJson = try packageData.json()?["object"] as? [String: AnyObject] else { - throw fail(bar: fetchingDataBar, with: "Unable to parse data from Package.resolved.") - } - - if let pins = packageJson["pins"] as? [[String: AnyObject]] { - 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) - } + 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 c423c68..47342c5 100644 --- a/Sources/Ether/VersionLatest.swift +++ b/Sources/Ether/VersionLatest.swift @@ -55,7 +55,7 @@ public final class VersionLatest: Command { 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*)(\\.?\\w+(\\(|:)\\s*\"[\\w\\.]+\"\\)?)(\\))", options: []) + 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") @@ -72,15 +72,15 @@ public final class VersionLatest: Command { } try String(nsManifest).data(using: .utf8)?.write(to: URL(string: "file:\(fileManager.currentDirectoryPath)/Package.swift")!) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "--enable-prefetching", "update"]) - _ = try console.backgroundExecute(program: "swift", arguments: ["package", "--enable-prefetching", "resolve"]) + _ = 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", "--enable-prefetching", "generate-xcodeproj"]) + _ = 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 new file mode 100644 index 0000000..a75b746 --- /dev/null +++ b/Sources/Ether/VersionSet.swift @@ -0,0 +1,117 @@ +// 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 +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)\")" + } +} diff --git a/Sources/Executable/main.swift b/Sources/Executable/main.swift index 3f0663e..172104e 100644 --- a/Sources/Executable/main.swift +++ b/Sources/Executable/main.swift @@ -27,7 +27,7 @@ import Helpers import libc // The current version of Ether. This string should be updated with each release. -let version = "1.9.2" +let version = "1.10.0" var arguments = CommandLine.arguments let terminal = Terminal(arguments: arguments) var iterator = arguments.makeIterator() @@ -57,7 +57,8 @@ do { FixInstall(console: terminal), Group(id: "version", commands: [ VersionLatest(console: terminal), - VersionAll(console: terminal) + VersionAll(console: terminal), + VersonSet(console: terminal) ], help: ["For interacting with dependency versions"]), CleanManifest(console: terminal) ] diff --git a/Sources/Helpers/Manifest.swift b/Sources/Helpers/Manifest.swift index ba51a1e..b4ff0e6 100644 --- a/Sources/Helpers/Manifest.swift +++ b/Sources/Helpers/Manifest.swift @@ -99,7 +99,7 @@ public class Manifest { return name } - /// Gets the name of the package that has a specefied URL by reading the `Package.resolved` file data. + /// 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.