feat: Integrates cli-client dependency into cli-version executable
This commit is contained in:
@@ -34,26 +34,26 @@ public struct CliClient: Sendable {
|
||||
case major, minor, patch
|
||||
}
|
||||
|
||||
// TODO: Use Int for `verbose`.
|
||||
public struct SharedOptions: Equatable, Sendable {
|
||||
let gitDirectory: String?
|
||||
|
||||
let dryRun: Bool
|
||||
let fileName: String
|
||||
let gitDirectory: String?
|
||||
let logLevel: Logger.Level
|
||||
let target: String
|
||||
let verbose: Bool
|
||||
|
||||
public init(
|
||||
gitDirectory: String? = nil,
|
||||
dryRun: Bool = false,
|
||||
fileName: String = "Version.swift",
|
||||
target: String,
|
||||
verbose: Bool = true
|
||||
logLevel: Logger.Level = .debug
|
||||
) {
|
||||
self.gitDirectory = gitDirectory
|
||||
self.dryRun = dryRun
|
||||
self.fileName = fileName
|
||||
self.target = target
|
||||
self.verbose = verbose
|
||||
self.logLevel = logLevel
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ public extension CliClient.SharedOptions {
|
||||
_ operation: () async throws -> T
|
||||
) async rethrows -> T {
|
||||
try await withDependencies {
|
||||
$0.logger.logLevel = .init(verbose: verbose)
|
||||
$0.logger.logLevel = logLevel
|
||||
} operation: {
|
||||
try await operation()
|
||||
}
|
||||
@@ -114,6 +114,7 @@ public extension CliClient.SharedOptions {
|
||||
try await fileClient.write(string: string, to: url)
|
||||
} else {
|
||||
logger.debug("Skipping, due to dry-run being passed.")
|
||||
logger.debug("\(string)")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,7 +148,7 @@ private extension CliClient.SharedOptions {
|
||||
}
|
||||
}
|
||||
|
||||
private func getVersionString() async throws -> (String, Bool) {
|
||||
private func getVersionString() async throws -> (version: String, usesOptionalType: Bool) {
|
||||
@Dependency(\.fileClient) var fileClient
|
||||
@Dependency(\.gitVersionClient) var gitVersionClient
|
||||
@Dependency(\.logger) var logger
|
||||
@@ -290,6 +291,10 @@ public struct Template: Sendable {
|
||||
}
|
||||
|
||||
public static func build(_ version: String? = nil) -> String {
|
||||
nonOptional(version)
|
||||
}
|
||||
|
||||
public static func nonOptional(_ version: String? = nil) -> String {
|
||||
Self(type: .string, version: version).value
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,12 @@ import Logging
|
||||
@_spi(Internal)
|
||||
public extension Logger.Level {
|
||||
|
||||
init(verbose: Bool) {
|
||||
if verbose {
|
||||
self = .debug
|
||||
} else {
|
||||
self = .info
|
||||
init(verbose: Int) {
|
||||
switch verbose {
|
||||
case 1: self = .warning
|
||||
case 2: self = .debug
|
||||
case 3...: self = .trace
|
||||
default: self = .info
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,40 +10,13 @@ extension CliVersionCommand {
|
||||
discussion: "This should generally not be interacted with directly, outside of the build plugin."
|
||||
)
|
||||
|
||||
@OptionGroup var shared: SharedOptions
|
||||
@OptionGroup var globals: GlobalOptions
|
||||
|
||||
@Option(
|
||||
name: .customLong("git-directory"),
|
||||
help: "The git directory for the version."
|
||||
)
|
||||
var gitDirectory: String
|
||||
|
||||
// TODO: Use CliClient
|
||||
func run() async throws {
|
||||
try await withDependencies {
|
||||
$0.logger.logLevel = .debug
|
||||
$0.fileClient = .liveValue
|
||||
$0.gitVersionClient = .liveValue
|
||||
} operation: {
|
||||
@Dependency(\.gitVersionClient) var gitVersion
|
||||
@Dependency(\.fileClient) var fileClient
|
||||
@Dependency(\.logger) var logger: Logger
|
||||
|
||||
logger.info("Building with git-directory: \(gitDirectory)")
|
||||
|
||||
let fileUrl = URL(fileURLWithPath: shared.target)
|
||||
.appendingPathComponent(shared.fileName)
|
||||
|
||||
let fileString = fileUrl.fileString()
|
||||
logger.info("File Url: \(fileString)")
|
||||
|
||||
let currentVersion = try await gitVersion.currentVersion(in: gitDirectory)
|
||||
|
||||
let fileContents = buildTemplate
|
||||
.replacingOccurrences(of: "nil", with: "\"\(currentVersion)\"")
|
||||
|
||||
try await fileClient.write(string: fileContents, to: fileUrl)
|
||||
logger.info("Updated version file: \(fileString)")
|
||||
try await globals.run {
|
||||
@Dependency(\.cliClient) var cliClient
|
||||
let output = try await cliClient.build(globals.shared)
|
||||
print(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
28
Sources/cli-version/BumpCommand.swift
Normal file
28
Sources/cli-version/BumpCommand.swift
Normal file
@@ -0,0 +1,28 @@
|
||||
import ArgumentParser
|
||||
import CliVersion
|
||||
import Dependencies
|
||||
|
||||
extension CliVersionCommand {
|
||||
struct Bump: AsyncParsableCommand {
|
||||
|
||||
static let configuration = CommandConfiguration(
|
||||
commandName: "bump",
|
||||
abstract: "Bump version of a command-line tool."
|
||||
)
|
||||
|
||||
@OptionGroup var globals: GlobalOptions
|
||||
|
||||
@Flag
|
||||
var bumpOption: CliClient.BumpOption = .patch
|
||||
|
||||
func run() async throws {
|
||||
try await globals.run {
|
||||
@Dependency(\.cliClient) var cliClient
|
||||
let output = try await cliClient.bump(bumpOption, globals.shared)
|
||||
print(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension CliClient.BumpOption: EnumerableFlag {}
|
||||
@@ -8,6 +8,7 @@ struct CliVersionCommand: AsyncParsableCommand {
|
||||
version: VERSION ?? "0.0.0",
|
||||
subcommands: [
|
||||
Build.self,
|
||||
Bump.self,
|
||||
Generate.self,
|
||||
Update.self
|
||||
]
|
||||
|
||||
@@ -12,28 +12,13 @@ extension CliVersionCommand {
|
||||
version: VERSION ?? "0.0.0"
|
||||
)
|
||||
|
||||
@OptionGroup var shared: SharedOptions
|
||||
@OptionGroup var globals: GlobalOptions
|
||||
|
||||
// TODO: Use CliClient
|
||||
func run() async 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 await fileClient.write(string: optionalTemplate, to: fileUrl)
|
||||
logger.info("Generated file at: \(fileString)")
|
||||
} else {
|
||||
logger.info("Would generate file at: \(fileString)")
|
||||
try await globals.run {
|
||||
@Dependency(\.cliClient) var cliClient
|
||||
let output = try await cliClient.generate(globals.shared)
|
||||
print(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
88
Sources/cli-version/GlobalOptions.swift
Normal file
88
Sources/cli-version/GlobalOptions.swift
Normal file
@@ -0,0 +1,88 @@
|
||||
import ArgumentParser
|
||||
@_spi(Internal) import CliVersion
|
||||
import Dependencies
|
||||
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 {
|
||||
absoluteString
|
||||
.replacingOccurrences(of: "file://", with: "")
|
||||
}
|
||||
}
|
||||
|
||||
let optionalTemplate = """
|
||||
// Do not set this variable, it is set during the build process.
|
||||
let VERSION: String? = nil
|
||||
|
||||
"""
|
||||
|
||||
let buildTemplate = """
|
||||
// Do not set this variable, it is set during the build process.
|
||||
let VERSION: String = nil
|
||||
|
||||
"""
|
||||
|
||||
struct GlobalOptions: ParsableArguments {
|
||||
|
||||
@Option(
|
||||
name: .customLong("git-directory"),
|
||||
help: "The git directory for the version (default: current directory)"
|
||||
)
|
||||
var gitDirectory: String?
|
||||
|
||||
@Option(
|
||||
name: .shortAndLong,
|
||||
help: "The target for the version file."
|
||||
)
|
||||
var target: String
|
||||
|
||||
@Option(
|
||||
name: .customLong("filename"),
|
||||
help: "Specify the file name for the version file in the target."
|
||||
)
|
||||
var fileName: String = "Version.swift"
|
||||
|
||||
@Flag(name: .customLong("dry-run"))
|
||||
var dryRun: Bool = false
|
||||
|
||||
@Flag(
|
||||
name: .shortAndLong,
|
||||
help: "Increase logging level, can be passed multiple times (example: -vvv)."
|
||||
)
|
||||
var verbose: Int
|
||||
}
|
||||
|
||||
extension GlobalOptions {
|
||||
|
||||
var shared: CliClient.SharedOptions {
|
||||
.init(
|
||||
gitDirectory: gitDirectory,
|
||||
dryRun: dryRun,
|
||||
fileName: fileName,
|
||||
target: target,
|
||||
logLevel: .init(verbose: verbose)
|
||||
)
|
||||
}
|
||||
|
||||
func run(_ operation: () async throws -> Void) async throws {
|
||||
try await withDependencies {
|
||||
$0.fileClient = .liveValue
|
||||
$0.gitVersionClient = .liveValue
|
||||
$0.cliClient = .liveValue
|
||||
} operation: {
|
||||
try await operation()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
import ArgumentParser
|
||||
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 {
|
||||
absoluteString
|
||||
.replacingOccurrences(of: "file://", with: "")
|
||||
}
|
||||
}
|
||||
|
||||
let optionalTemplate = """
|
||||
// Do not set this variable, it is set during the build process.
|
||||
let VERSION: String? = nil
|
||||
|
||||
"""
|
||||
|
||||
let buildTemplate = """
|
||||
// Do not set this variable, it is set during the build process.
|
||||
let VERSION: String = nil
|
||||
|
||||
"""
|
||||
|
||||
// TODO: Use Int for `verbose`.
|
||||
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
|
||||
|
||||
@Flag(name: .long, help: "Increase logging level.")
|
||||
var verbose: Bool = false
|
||||
}
|
||||
@@ -12,45 +12,13 @@ extension CliVersionCommand {
|
||||
discussion: "This command can be interacted with directly outside of the plugin context."
|
||||
)
|
||||
|
||||
@OptionGroup var shared: SharedOptions
|
||||
@OptionGroup var globals: GlobalOptions
|
||||
|
||||
@Option(
|
||||
name: .customLong("git-directory"),
|
||||
help: "The git directory for the version."
|
||||
)
|
||||
var gitDirectory: String?
|
||||
|
||||
// TODO: Use CliClient
|
||||
func run() async throws {
|
||||
try await withDependencies {
|
||||
$0.logger.logLevel = shared.verbose ? .debug : .info
|
||||
$0.fileClient = .liveValue
|
||||
$0.gitVersionClient = .liveValue
|
||||
$0.asyncShellClient = .liveValue
|
||||
} operation: {
|
||||
@Dependency(\.gitVersionClient) var gitVersion
|
||||
@Dependency(\.fileClient) var fileClient
|
||||
@Dependency(\.logger) var logger
|
||||
@Dependency(\.asyncShellClient) var shell
|
||||
|
||||
let targetUrl = parseTarget(shared.target)
|
||||
let fileUrl = targetUrl
|
||||
.appendingPathComponent(shared.fileName)
|
||||
|
||||
let fileString = fileUrl.fileString()
|
||||
|
||||
let currentVersion = try await gitVersion.currentVersion(in: gitDirectory)
|
||||
|
||||
let fileContents = optionalTemplate
|
||||
.replacingOccurrences(of: "nil", with: "\"\(currentVersion)\"")
|
||||
|
||||
if !shared.dryRun {
|
||||
try await fileClient.write(string: fileContents, to: fileUrl)
|
||||
logger.info("Updated version file: \(fileString)")
|
||||
} else {
|
||||
logger.info("Would update file contents to:")
|
||||
logger.info("\(fileContents)")
|
||||
}
|
||||
try await globals.run {
|
||||
@Dependency(\.cliClient) var cliClient
|
||||
let output = try await cliClient.update(globals.shared)
|
||||
print(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
// Do not set this variable, it is set during the build process.
|
||||
let VERSION: String? = "0.1.0"
|
||||
let VERSION: String? = "0.1.1"
|
||||
|
||||
Reference in New Issue
Block a user