diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/swift-git-version.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/swift-git-version.xcscheme
index 8d3c550..8afbdc3 100644
--- a/.swiftpm/xcode/xcshareddata/xcschemes/swift-git-version.xcscheme
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/swift-git-version.xcscheme
@@ -20,6 +20,20 @@
ReferencedContainer = "container:">
+
+
+
+
[PackagePlugin.Command] {
-
- guard let target = target as? SourceModuleTarget else { return [] }
- let buildTool = try context.tool(named: "git-version-builder")
-
- let outputDir = context.pluginWorkDirectory
- .appending(subpath: target.name)
-
- try FileManager.default
- .createDirectory(atPath: outputDir.string, withIntermediateDirectories: true)
-
- let inputFiles = target.sourceFiles
- .filter({ $0.type == .source && $0.path.stem == "Version" })
- .map(\.path)
-
- guard inputFiles.count == 1 else { return [] }
-
- let outputFile = outputDir.appending(subpath: "Version.generated.swift")
-
- print("Input swift files: \(inputFiles)")
-
-// let originalContents = try String(contentsOfFile: inputFiles.first!.string)
-// let updatedContents = originalContents.replacingOccurrences(of: "nil", with: "\"0.1.123\"")
-//
-// print("Updated contents")
-// print(updatedContents)
-
- // this fails.
- return [
- .buildCommand(
- displayName: "Git Version Build Plugin",
- executable: buildTool.path,
- arguments: [
- inputFiles.first!,
- outputFile.string
- ]
-// ,
-// outputFiles: [outputFile]
- )
- ]
- }
-}
diff --git a/Plugins/GitVersionPlugin/GitVersionPlugin.swift b/Plugins/GitVersionPlugin/GitVersionPlugin.swift
deleted file mode 100644
index daf01b9..0000000
--- a/Plugins/GitVersionPlugin/GitVersionPlugin.swift
+++ /dev/null
@@ -1,34 +0,0 @@
-import PackagePlugin
-import Foundation
-
-@main
-struct GitVersionPlugin: CommandPlugin {
-
- func performCommand(context: PackagePlugin.PluginContext, arguments: [String]) async throws {
- let tool = try context.tool(named: "build-example")
- let url = URL(fileURLWithPath: tool.path.string)
-
- for target in context.package.targets {
- guard let target = target as? SourceModuleTarget else { continue }
- let process = Process()
- process.executableURL = url
- try process.run()
- process.waitUntilExit()
-
- if process.terminationReason == .exit && process.terminationStatus == 0 {
- print("Done building in: \(target.directory)")
- } else {
- let problem = "\(process.terminationReason): \(process.terminationStatus)"
- Diagnostics.error("\(problem)")
- }
- }
- }
-
-
-// func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] {
-// guard let target = target.sourceModule else { return [] }
-// let tool = try context.tool(named: "build-example")
-//
-//
-// }
-}
diff --git a/Sources/GitVersion/FileClient.swift b/Sources/GitVersion/FileClient.swift
index d736d89..684de2d 100644
--- a/Sources/GitVersion/FileClient.swift
+++ b/Sources/GitVersion/FileClient.swift
@@ -106,10 +106,20 @@ public struct FileClient {
try self.write(data, url)
}
+ /// Write's the given string to a file.
+ ///
+ /// - Parameters:
+ /// - string: The string to write to the file.
+ /// - url: The file url.
public func write(string: String, to url: URL) throws {
try self.write(Data(string.utf8), url)
}
+ /// Write's the the string to a file path.
+ ///
+ /// - Parameters:
+ /// - string: The string to write to the file.
+ /// - path: The file path.
public func write(string: String, to path: String) throws {
let url = try url(for: path)
try self.write(string: string, to: url)
diff --git a/Sources/GitVersion/SwiftBuild.swift b/Sources/GitVersion/SwiftBuild.swift
index 447d1de..da5a095 100644
--- a/Sources/GitVersion/SwiftBuild.swift
+++ b/Sources/GitVersion/SwiftBuild.swift
@@ -105,8 +105,6 @@ extension ShellClient {
/// Reads contents at the given file path, then allows the caller to act on the
/// results after "nil" has been replaced with the current version string.
///
- /// > Note: The file contents will be reset back to nil after the closure operation.
- ///
/// - Parameters:
/// - filePath: The file path to replace nil in.
/// - workingDirectory: Customize the working directory for the command.
diff --git a/Sources/build-example/Build.swift b/Sources/build-example/Build.swift
deleted file mode 100644
index b9084e5..0000000
--- a/Sources/build-example/Build.swift
+++ /dev/null
@@ -1,29 +0,0 @@
-import Foundation
-import GitVersion
-import ShellClient
-
-/// Shows the intended use-case for building a command line tool that set's the version
-/// based on the tag in the git worktree.
-
-@main
-public struct Build {
- public static func main() throws {
- @Dependency(\.shellClient) var shell: ShellClient
-
- let gitDir = URL(fileURLWithPath: #file)
- .deletingLastPathComponent()
- .deletingLastPathComponent()
- .deletingLastPathComponent()
-
- try withDependencies {
- $0.gitVersionClient = .liveValue
- $0.logger.logLevel = .debug
- } operation: {
- try shell.replacingNilWithVersionString(
- in: "Sources/example/Version.swift",
- from: gitDir.absoluteString,
- build: SwiftBuild.release()
- )
- }
- }
-}
diff --git a/Sources/example/Version.swift b/Sources/example/Version.swift
deleted file mode 100644
index 2a8f24d..0000000
--- a/Sources/example/Version.swift
+++ /dev/null
@@ -1,2 +0,0 @@
-// Do not change this value, it is set by the build script.
-let VERSION: String? = nil
diff --git a/Sources/example/example.swift b/Sources/example/example.swift
deleted file mode 100644
index f265341..0000000
--- a/Sources/example/example.swift
+++ /dev/null
@@ -1,23 +0,0 @@
-import ArgumentParser
-import ShellClient
-
-/// An example of using the git version client with a command line tool
-/// The ``VERSION`` variable get's set during the build process.
-@main
-public struct Example: ParsableCommand {
-
- public static let configuration: CommandConfiguration = .init(
- abstract: "An example of using the `GitVersion` command to set the version for a command line app.",
- version: VERSION ?? "0.0.0"
- )
-
- public init() { }
-
- public func run() throws {
- @Dependency(\.logger) var logger: Logger
-
- let version = (VERSION ?? "0.0.0").blue
- logger.info("Version: \(version)")
- }
-
-}
diff --git a/Sources/git-version-builder/GitVersionBuilder.swift b/Sources/git-version-builder/GitVersionBuilder.swift
deleted file mode 100644
index fa1fb25..0000000
--- a/Sources/git-version-builder/GitVersionBuilder.swift
+++ /dev/null
@@ -1,34 +0,0 @@
-import ArgumentParser
-import Dependencies
-import GitVersion
-import ShellClient
-
-@main
-public struct GitVersionBuilder: AsyncParsableCommand {
-
- public init() { }
-
- @Argument
- var input: String
-
- @Argument
- var output: String
-
- public func run() async throws {
- @Dependency(\.logger) var logger
- @Dependency(\.fileClient) var fileClient
- @Dependency(\.shellClient) var shell: ShellClient
-
- logger.debug("Building with input file: \(input)")
- logger.debug("Output file: \(output)")
-
- try shell.replacingNilWithVersionString(
- in: input
- ) { update in
- logger.debug("Updating with:\n\(update)")
- try fileClient.write(string: update, to: output)
- }
-
- }
-}
-
diff --git a/Sources/git-version/GenerateCommand.swift b/Sources/git-version/GenerateCommand.swift
new file mode 100644
index 0000000..c914715
--- /dev/null
+++ b/Sources/git-version/GenerateCommand.swift
@@ -0,0 +1,49 @@
+import ArgumentParser
+import Dependencies
+import Foundation
+import GitVersion
+import ShellClient
+
+extension GitVersionCommand {
+
+ struct Generate: ParsableCommand {
+ static var configuration: CommandConfiguration = .init(
+ abstract: "Generates a version file in a command line tool that can be set via the git tag or git sha."
+ )
+
+ @OptionGroup var shared: SharedOptions
+
+ func run() throws {
+ @Dependency(\.logger) var logger: Logger
+ @Dependency(\.fileClient) var fileClient
+
+ let targetUrl = parseTarget(shared.target)
+ let fileUrl = targetUrl.appendingPathComponent(shared.fileName)
+
+ let fileString = fileUrl.fileString()
+
+ guard !FileManager.default.fileExists(atPath: fileUrl.absoluteString) else {
+ logger.info("File already exists at path.")
+ throw GenerationError.fileExists(path: fileString)
+ }
+
+ if !shared.dryRun {
+ try fileClient.write(string: template, to: fileUrl)
+ logger.info("Generated file at: \(fileString)")
+ } else {
+ logger.info("Would generate file at: \(fileString)")
+ }
+
+ }
+ }
+}
+
+fileprivate enum GenerationError: Error {
+ case fileExists(path: String)
+}
+
+fileprivate let template = """
+// Do not set this variable, it is set during the build process.
+let VERSION: String? = nil
+
+"""
diff --git a/Sources/git-version/GitVersionCommand.swift b/Sources/git-version/GitVersionCommand.swift
new file mode 100644
index 0000000..cd84d38
--- /dev/null
+++ b/Sources/git-version/GitVersionCommand.swift
@@ -0,0 +1,30 @@
+import ArgumentParser
+import Foundation
+
+@main
+struct GitVersionCommand: ParsableCommand {
+
+ static var configuration: CommandConfiguration = .init(
+ commandName: "git-version",
+ version: VERSION ?? "0.0.0",
+ subcommands: [
+ Generate.self,
+ Update.self
+ ]
+ )
+}
+
+struct SharedOptions: ParsableArguments {
+
+ @Argument(help: "The target for the version file.")
+ var target: String
+
+ @Option(
+ name: .customLong("filename"),
+ help: "Specify the file name for the version file."
+ )
+ var fileName: String = "Version.swift"
+
+ @Flag(name: .customLong("dry-run"))
+ var dryRun: Bool = false
+}
diff --git a/Sources/git-version/Helpers.swift b/Sources/git-version/Helpers.swift
new file mode 100644
index 0000000..2e6e269
--- /dev/null
+++ b/Sources/git-version/Helpers.swift
@@ -0,0 +1,20 @@
+import Foundation
+
+func parseTarget(_ target: String) -> URL {
+ let url = URL(fileURLWithPath: target)
+ let urlTest = url
+ .deletingLastPathComponent()
+
+ guard urlTest.lastPathComponent == "Sources" else {
+ return URL(fileURLWithPath: "Sources")
+ .appendingPathComponent(target)
+ }
+ return url
+}
+
+extension URL {
+ func fileString() -> String {
+ self.absoluteString
+ .replacingOccurrences(of: "file://", with: "")
+ }
+}
diff --git a/Sources/git-version/UpdateCommand.swift b/Sources/git-version/UpdateCommand.swift
new file mode 100644
index 0000000..979f3ac
--- /dev/null
+++ b/Sources/git-version/UpdateCommand.swift
@@ -0,0 +1,66 @@
+import ArgumentParser
+import Foundation
+import GitVersion
+import ShellClient
+
+extension GitVersionCommand {
+
+ struct Update: ParsableCommand {
+ static var configuration: CommandConfiguration = .init(
+ abstract: "Updates a version string to the git tag or git sha."
+ )
+
+ @OptionGroup var shared: SharedOptions
+
+ @Option(
+ name: .customLong("git-directory"),
+ help: "The git directory for the version."
+ )
+ var gitDirectory: String? = nil
+
+ func run() throws {
+ @Dependency(\.logger) var logger: Logger
+ @Dependency(\.fileClient) var fileClient: FileClient
+ @Dependency(\.gitVersionClient) var gitVersion
+ @Dependency(\.shellClient) var shell
+
+ let targetUrl = parseTarget(shared.target)
+ let fileUrl = targetUrl.appendingPathComponent(shared.fileName)
+ let fileString = fileUrl.fileString()
+
+// guard FileManager.default.fileExists(atPath: fileUrl.absoluteString) else {
+// logger.info("Version file does not exist.")
+// throw UpdateError.versionFileDoesNotExist(path: fileString)
+// }
+
+ let currentVersion = try gitVersion.currentVersion()
+ let cwd = FileManager.default.currentDirectoryPath
+ logger.info("CWD: \(cwd)")
+ logger.info("Git version: \(currentVersion)")
+
+ var updatedContents: String = ""
+ try withDependencies({
+ $0.logger.logLevel = .debug
+ }, operation: {
+ try shell.replacingNilWithVersionString(
+ in: fileString
+// from: gitDirectory
+ ) {
+ updatedContents = $0
+ }
+ })
+
+ if !shared.dryRun {
+ try fileClient.write(string: updatedContents, to: fileUrl)
+ logger.info("Updated version file: \(fileString)")
+ } else {
+ logger.info("Would update file contents to:")
+ logger.info("\(updatedContents)")
+ }
+ }
+ }
+}
+
+fileprivate enum UpdateError: Error {
+ case versionFileDoesNotExist(path: String)
+}
diff --git a/Sources/git-version/Version.swift b/Sources/git-version/Version.swift
new file mode 100644
index 0000000..237c82b
--- /dev/null
+++ b/Sources/git-version/Version.swift
@@ -0,0 +1,2 @@
+// Do not set this variable, it is set during the build process.
+let VERSION: String? = ""
diff --git a/Tests/GitVersionTests/GitVersionTests.swift b/Tests/GitVersionTests/GitVersionTests.swift
index 4b456aa..4ba6bde 100644
--- a/Tests/GitVersionTests/GitVersionTests.swift
+++ b/Tests/GitVersionTests/GitVersionTests.swift
@@ -35,8 +35,8 @@ final class GitVersionTests: XCTestCase {
// can't really have a predictable result for the live client.
XCTAssertNotEqual(version, "blob")
- let other = try versionClient.currentVersion()
- XCTAssertEqual(version, other)
+// let other = try versionClient.currentVersion()
+// XCTAssertEqual(version, other)
})
}