feat: Integrates configuration-client.

This commit is contained in:
2024-12-23 16:30:15 -05:00
parent c7d349e3cc
commit e2309f5635
10 changed files with 290 additions and 245 deletions

View File

@@ -2,14 +2,6 @@
requireExistingFile = true requireExistingFile = true
requireExistingSemVar = true requireExistingSemVar = true
[strategy.semvar.preRelease]
prefix = 'rc'
style = 'custom'
usesGitTag = false
[strategy.semvar.preRelease.branch]
includeCommitSha = true
[target.module] [target.module]
fileName = 'Version.swift' fileName = 'Version.swift'
name = 'cli-version' name = 'cli-version'

View File

@@ -33,66 +33,29 @@ public struct CliClient: Sendable {
case major, minor, patch, preRelease case major, minor, patch, preRelease
} }
public enum PreReleaseStrategy: Equatable, Sendable {
/// Use output of tag, with branch and commit sha.
case branchAndCommit
/// Provide a custom pre-release tag.
indirect case custom(String, PreReleaseStrategy? = nil)
/// Use the output of `git describe --tags`
case tag
}
public enum VersionStrategy: Equatable, Sendable {
case branchAndCommit
case semVar(SemVarOptions)
// public typealias SemVarOptions = Configuration.SemVar
public struct SemVarOptions: Equatable, Sendable {
let preReleaseStrategy: PreReleaseStrategy?
let requireExistingFile: Bool
let requireExistingSemVar: Bool
public init(
preReleaseStrategy: PreReleaseStrategy? = nil,
requireExistingFile: Bool = true,
requireExistingSemVar: Bool = true
) {
self.preReleaseStrategy = preReleaseStrategy
self.requireExistingFile = requireExistingFile
self.requireExistingSemVar = requireExistingSemVar
}
}
}
public struct SharedOptions: Equatable, Sendable { public struct SharedOptions: Equatable, Sendable {
let dryRun: Bool let dryRun: Bool
let gitDirectory: String? let gitDirectory: String?
let logLevel: Logger.Level let logLevel: Logger.Level
let preReleaseStrategy: PreReleaseStrategy? let configuration: Configuration
let target: String
let versionStrategy: VersionStrategy
public init( public init(
dryRun: Bool = false, dryRun: Bool = false,
gitDirectory: String? = nil, gitDirectory: String? = nil,
logLevel: Logger.Level = .debug, logLevel: Logger.Level = .debug,
preReleaseStrategy: PreReleaseStrategy? = nil, configuration: Configuration
target: String,
versionStrategy: VersionStrategy = .semVar(.init())
) { ) {
self.dryRun = dryRun self.dryRun = dryRun
self.target = target
self.gitDirectory = gitDirectory self.gitDirectory = gitDirectory
self.logLevel = logLevel self.logLevel = logLevel
self.preReleaseStrategy = preReleaseStrategy self.configuration = configuration
self.versionStrategy = versionStrategy
} }
var allowPreReleaseTag: Bool { preReleaseStrategy != nil } var allowPreReleaseTag: Bool {
guard let semvar = configuration.strategy?.semvar else { return false }
return semvar.preRelease != nil
}
} }
} }

View File

@@ -3,8 +3,29 @@ import Dependencies
import Foundation import Foundation
import GitClient import GitClient
extension Configuration {
func targetUrl(gitDirectory: String?) throws -> URL {
guard let target else {
throw ConfigurationParsingError.targetNotFound
}
return try target.url(gitDirectory: gitDirectory)
}
func currentVersion(targetUrl: URL, gitDirectory: String?) async throws -> CurrentVersionContainer {
guard let strategy else {
throw ConfigurationParsingError.versionNotFound
}
return try await strategy.currentVersion(
targetUrl: targetUrl,
gitDirectory: gitDirectory
)
}
}
extension Configuration.Target { extension Configuration.Target {
func url(gitDirectory: String?) throws -> URL { func url(gitDirectory: String?) throws -> URL {
@Dependency(\.logger) var logger
let filePath: String let filePath: String
if let path { if let path {
@@ -15,13 +36,17 @@ extension Configuration.Target {
} }
var path = module.name var path = module.name
if !path.hasPrefix("Sources") || !path.hasPrefix("./Sources") { logger.debug("module.name: \(path)")
path = "Sources/\(path)"
}
if path.hasPrefix("./") { if path.hasPrefix("./") {
path = String(path.dropFirst(2)) path = String(path.dropFirst(2))
} }
if !path.hasPrefix("Sources") {
logger.debug("no prefix")
path = "Sources/\(path)"
}
filePath = "\(path)/\(module.fileName)" filePath = "\(path)/\(module.fileName)"
} }
@@ -70,46 +95,66 @@ extension Configuration.PreReleaseStrategy {
public extension Configuration.SemVar { public extension Configuration.SemVar {
private func applyingPreRelease(_ semVar: SemVar, _ gitDirectory: String?) async throws -> SemVar { private func applyingPreRelease(_ semVar: SemVar, _ gitDirectory: String?) async throws -> SemVar {
guard let preReleaseStrategy = self.preRelease else { return semVar } @Dependency(\.logger) var logger
logger.trace("Start apply pre-release to: \(semVar)")
guard let preReleaseStrategy = self.preRelease else {
logger.trace("No pre-release strategy, returning original semvar.")
return semVar
}
let preRelease = try await preReleaseStrategy.preReleaseString(gitDirectory: gitDirectory) let preRelease = try await preReleaseStrategy.preReleaseString(gitDirectory: gitDirectory)
logger.trace("Pre-release string: \(preRelease)")
return semVar.applyingPreRelease(preRelease) return semVar.applyingPreRelease(preRelease)
} }
func currentVersion(file: URL, gitDirectory: String? = nil) async throws -> CurrentVersionContainer.Version { func currentVersion(file: URL, gitDirectory: String? = nil) async throws -> CurrentVersionContainer.Version {
@Dependency(\.fileClient) var fileClient @Dependency(\.fileClient) var fileClient
@Dependency(\.gitClient) var gitClient @Dependency(\.gitClient) var gitClient
@Dependency(\.logger) var logger
let fileOutput = try? await fileClient.semVar(file: file, gitDirectory: gitDirectory) let fileOutput = try? await fileClient.semVar(file: file, gitDirectory: gitDirectory)
var semVar = fileOutput?.semVar var semVar = fileOutput?.semVar
logger.trace("file output semvar: \(String(describing: semVar))")
let usesOptionalType = fileOutput?.usesOptionalType let usesOptionalType = fileOutput?.usesOptionalType
if requireExistingFile { // We parsed a semvar from the existing file, use it.
guard let semVar else { if semVar != nil {
throw CliClientError.fileDoesNotExist(path: file.cleanFilePath)
}
return try await .semVar( return try await .semVar(
applyingPreRelease(semVar, gitDirectory), applyingPreRelease(semVar!, gitDirectory),
usesOptionalType: usesOptionalType ?? false usesOptionalType: usesOptionalType ?? false
) )
} }
// Didn't have existing semVar loaded from file, so check for git-tag. if requireExistingFile {
logger.debug("Failed to parse existing file, and caller requires it.")
throw CliClientError.fileDoesNotExist(path: file.cleanFilePath)
}
logger.trace("Does not require existing file, checking git-tag.")
// Didn't have existing semVar loaded from file, so check for git-tag.
semVar = try await gitClient.version(.init( semVar = try await gitClient.version(.init(
gitDirectory: gitDirectory, gitDirectory: gitDirectory,
style: .tag(exactMatch: false) style: .tag(exactMatch: false)
)).semVar )).semVar
if requireExistingSemVar { if semVar != nil {
guard let semVar else {
fatalError()
}
return try await .semVar( return try await .semVar(
applyingPreRelease(semVar, gitDirectory), applyingPreRelease(semVar!, gitDirectory),
usesOptionalType: usesOptionalType ?? false usesOptionalType: usesOptionalType ?? false
) )
} }
if requireExistingSemVar {
logger.trace("Caller requires existing semvar and it was not found in file or git-tag.")
throw CliClientError.semVarNotFound
}
// Semvar doesn't exist, so create a new one.
logger.trace("Generating new semvar.")
return try await .semVar( return try await .semVar(
applyingPreRelease(.init(), gitDirectory), applyingPreRelease(.init(), gitDirectory),
usesOptionalType: usesOptionalType ?? false usesOptionalType: usesOptionalType ?? false
@@ -143,6 +188,8 @@ extension Configuration.VersionStrategy {
} }
enum ConfigurationParsingError: Error { enum ConfigurationParsingError: Error {
case targetNotFound
case pathOrModuleNotSet case pathOrModuleNotSet
case versionStrategyError(message: String) case versionStrategyError(message: String)
case versionNotFound
} }

View File

@@ -34,6 +34,7 @@ public extension FileClient {
guard let versionString else { guard let versionString else {
throw CliClientError.failedToParseVersionFile throw CliClientError.failedToParseVersionFile
} }
logger.debug("Parsed version string: \(versionString)")
return (String(versionString), isOptional) return (String(versionString), isOptional)
} }
@@ -41,8 +42,12 @@ public extension FileClient {
file: URL, file: URL,
gitDirectory: String? gitDirectory: String?
) async throws -> (semVar: SemVar?, usesOptionalType: Bool) { ) async throws -> (semVar: SemVar?, usesOptionalType: Bool) {
@Dependency(\.logger) var logger
let (string, usesOptionalType) = try await getVersionString(fileUrl: file, gitDirectory: gitDirectory) let (string, usesOptionalType) = try await getVersionString(fileUrl: file, gitDirectory: gitDirectory)
return (SemVar(string: string), usesOptionalType) let semvar = SemVar(string: string)
logger.debug("Semvar: \(String(describing: semvar))")
return (semvar, usesOptionalType)
} }
} }

View File

@@ -6,30 +6,6 @@ import GitClient
@_spi(Internal) @_spi(Internal)
public extension CliClient.SharedOptions { public extension CliClient.SharedOptions {
func parseTargetUrl() async throws -> URL {
@Dependency(\.fileClient) var fileClient
let target = target.hasPrefix(".") ? String(target.dropFirst()) : target
let targetHasSources = target.hasPrefix("Sources") || target.hasPrefix("/Sources")
var url = url(for: gitDirectory ?? (targetHasSources ? target : "Sources"))
if gitDirectory != nil {
if !targetHasSources {
url.appendPathComponent("Sources")
}
url.appendPathComponent(target)
}
let isDirectory = try await fileClient.isDirectory(url.cleanFilePath)
if isDirectory {
url.appendPathComponent(Constants.defaultFileName)
}
return url
}
@discardableResult @discardableResult
func run( func run(
_ operation: (CurrentVersionContainer) async throws -> Void _ operation: (CurrentVersionContainer) async throws -> Void
@@ -39,12 +15,12 @@ public extension CliClient.SharedOptions {
} operation: { } operation: {
@Dependency(\.logger) var logger @Dependency(\.logger) var logger
let targetUrl = try await parseTargetUrl() let targetUrl = try configuration.targetUrl(gitDirectory: gitDirectory)
logger.debug("Target: \(targetUrl.cleanFilePath)") logger.debug("Target: \(targetUrl.cleanFilePath)")
try await operation( try await operation(
versionStrategy.currentVersion( configuration.currentVersion(
file: targetUrl, targetUrl: targetUrl,
gitDirectory: gitDirectory gitDirectory: gitDirectory
) )
) )
@@ -124,9 +100,11 @@ extension CliClient.SharedOptions {
switch container.version { switch container.version {
case .string: // When we did not parse a semVar, just write whatever we parsed for the current version. case .string: // When we did not parse a semVar, just write whatever we parsed for the current version.
logger.debug("Failed to parse semvar, but got current version string.")
try await write(container) try await write(container)
case let .semVar(semVar, usesOptionalType: usesOptionalType): case let .semVar(semVar, usesOptionalType: usesOptionalType):
logger.debug("Semvar prior to bumping: \(semVar)")
let bumped = semVar.bump(type, preRelease: nil) // preRelease is already set on semVar. let bumped = semVar.bump(type, preRelease: nil) // preRelease is already set on semVar.
let version = bumped.versionString(withPreReleaseTag: allowPreReleaseTag) let version = bumped.versionString(withPreReleaseTag: allowPreReleaseTag)
logger.debug("Bumped version: \(version)") logger.debug("Bumped version: \(version)")

View File

@@ -37,16 +37,30 @@ public struct SemVar: CustomStringConvertible, Equatable, Sendable {
} }
public init?(string: String) { public init?(string: String) {
@Dependency(\.logger) var logger
logger.trace("Parsing semvar from: \(string)")
let parts = string.split(separator: ".") let parts = string.split(separator: ".")
logger.trace("parts: \(parts)")
guard parts.count >= 3 else { guard parts.count >= 3 else {
return nil return nil
} }
let major = Int(String(parts[0].replacingOccurrences(of: "\"", with: "")))
let minor = Int(String(parts[1]))
let patchParts = parts[2].split(separator: "-") let major = Int(String(parts[0].replacingOccurrences(of: "\"", with: "")))
logger.trace("major: \(String(describing: major))")
let minor = Int(String(parts[1]))
logger.trace("minor: \(String(describing: minor))")
let patchParts = parts[2].replacingOccurrences(of: "\"", with: "").split(separator: "-")
logger.trace("patchParts: \(String(describing: patchParts))")
let patch = Int(patchParts.first ?? "0") let patch = Int(patchParts.first ?? "0")
logger.trace("patch: \(String(describing: patch))")
let preRelease = String(patchParts.dropFirst().joined(separator: "-")) let preRelease = String(patchParts.dropFirst().joined(separator: "-"))
logger.trace("preRelease: \(String(describing: preRelease))")
self.init( self.init(
major: major ?? 0, major: major ?? 0,

View File

@@ -1,104 +1,104 @@
import ConfigurationClient // import ConfigurationClient
import Dependencies // import Dependencies
import FileClient // import FileClient
import struct Foundation.URL // import struct Foundation.URL
import GitClient // import GitClient
//
@_spi(Internal) // @_spi(Internal)
public extension CliClient.PreReleaseStrategy { // public extension CliClient.PreReleaseStrategy {
//
func preReleaseString(gitDirectory: String?) async throws -> String { // func preReleaseString(gitDirectory: String?) async throws -> String {
@Dependency(\.gitClient) var gitClient // @Dependency(\.gitClient) var gitClient
switch self { // switch self {
case let .custom(string, child): // case let .custom(string, child):
guard let child else { return string } // guard let child else { return string }
return try await "\(string)-\(child.preReleaseString(gitDirectory: gitDirectory))" // return try await "\(string)-\(child.preReleaseString(gitDirectory: gitDirectory))"
case .tag: // case .tag:
return try await gitClient.version(.init( // return try await gitClient.version(.init(
gitDirectory: gitDirectory, // gitDirectory: gitDirectory,
style: .tag(exactMatch: false) // style: .tag(exactMatch: false)
)).description // )).description
case .branchAndCommit: // case .branchAndCommit:
return try await gitClient.version(.init( // return try await gitClient.version(.init(
gitDirectory: gitDirectory, // gitDirectory: gitDirectory,
style: .branch(commitSha: true) // style: .branch(commitSha: true)
)).description // )).description
} // }
} // }
} // }
//
@_spi(Internal) // @_spi(Internal)
public extension CliClient.VersionStrategy.SemVarOptions { // public extension CliClient.VersionStrategy.SemVarOptions {
//
private func applyingPreRelease(_ semVar: SemVar, _ gitDirectory: String?) async throws -> SemVar { // private func applyingPreRelease(_ semVar: SemVar, _ gitDirectory: String?) async throws -> SemVar {
guard let preReleaseStrategy else { return semVar } // guard let preReleaseStrategy else { return semVar }
let preRelease = try await preReleaseStrategy.preReleaseString(gitDirectory: gitDirectory) // let preRelease = try await preReleaseStrategy.preReleaseString(gitDirectory: gitDirectory)
return semVar.applyingPreRelease(preRelease) // return semVar.applyingPreRelease(preRelease)
} // }
//
func currentVersion(file: URL, gitDirectory: String? = nil) async throws -> CurrentVersionContainer.Version { // func currentVersion(file: URL, gitDirectory: String? = nil) async throws -> CurrentVersionContainer.Version {
@Dependency(\.fileClient) var fileClient // @Dependency(\.fileClient) var fileClient
@Dependency(\.gitClient) var gitClient // @Dependency(\.gitClient) var gitClient
//
let fileOutput = try? await fileClient.semVar(file: file, gitDirectory: gitDirectory) // let fileOutput = try? await fileClient.semVar(file: file, gitDirectory: gitDirectory)
var semVar = fileOutput?.semVar // var semVar = fileOutput?.semVar
let usesOptionalType = fileOutput?.usesOptionalType // let usesOptionalType = fileOutput?.usesOptionalType
//
if requireExistingFile { // if requireExistingFile {
guard let semVar else { // guard let semVar else {
throw CliClientError.fileDoesNotExist(path: file.cleanFilePath) // throw CliClientError.fileDoesNotExist(path: file.cleanFilePath)
} // }
return try await .semVar( // return try await .semVar(
applyingPreRelease(semVar, gitDirectory), // applyingPreRelease(semVar, gitDirectory),
usesOptionalType: usesOptionalType ?? false // usesOptionalType: usesOptionalType ?? false
) // )
} // }
//
// Didn't have existing semVar loaded from file, so check for git-tag. // // Didn't have existing semVar loaded from file, so check for git-tag.
//
semVar = try await gitClient.version(.init( // semVar = try await gitClient.version(.init(
gitDirectory: gitDirectory, // gitDirectory: gitDirectory,
style: .tag(exactMatch: false) // style: .tag(exactMatch: false)
)).semVar // )).semVar
if requireExistingSemVar { // if requireExistingSemVar {
guard let semVar else { // guard let semVar else {
fatalError() // fatalError()
} // }
return try await .semVar( // return try await .semVar(
applyingPreRelease(semVar, gitDirectory), // applyingPreRelease(semVar, gitDirectory),
usesOptionalType: usesOptionalType ?? false // usesOptionalType: usesOptionalType ?? false
) // )
} // }
//
return try await .semVar( // return try await .semVar(
applyingPreRelease(.init(), gitDirectory), // applyingPreRelease(.init(), gitDirectory),
usesOptionalType: usesOptionalType ?? false // usesOptionalType: usesOptionalType ?? false
) // )
} // }
} // }
//
@_spi(Internal) // @_spi(Internal)
public extension CliClient.VersionStrategy { // public extension CliClient.VersionStrategy {
//
func currentVersion(file: URL, gitDirectory: String?) async throws -> CurrentVersionContainer { // func currentVersion(file: URL, gitDirectory: String?) async throws -> CurrentVersionContainer {
@Dependency(\.gitClient) var gitClient // @Dependency(\.gitClient) var gitClient
//
switch self { // switch self {
case .branchAndCommit: // case .branchAndCommit:
return try await .init( // return try await .init(
targetUrl: file, // targetUrl: file,
version: .string( // version: .string(
gitClient.version(.init( // gitClient.version(.init(
gitDirectory: gitDirectory, // gitDirectory: gitDirectory,
style: .branch(commitSha: true) // style: .branch(commitSha: true)
)).description // )).description
) // )
) // )
case let .semVar(options): // case let .semVar(options):
return try await .init( // return try await .init(
targetUrl: file, // targetUrl: file,
version: options.currentVersion(file: file, gitDirectory: gitDirectory) // version: options.currentVersion(file: file, gitDirectory: gitDirectory)
) // )
} // }
} // }
} // }

View File

@@ -0,0 +1,61 @@
import ConfigurationClient
import Dependencies
import FileClient
import Foundation
extension Configuration {
func mergingTarget(_ otherTarget: Configuration.Target?) -> Self {
.init(
target: otherTarget ?? target,
strategy: strategy
)
}
func mergingStrategy(_ otherStrategy: Configuration.VersionStrategy?) -> Self {
.init(
target: target,
strategy: strategy?.merging(otherStrategy)
)
}
}
extension Configuration.Branch {
func merging(_ other: Self?) -> Self {
return .init(includeCommitSha: other?.includeCommitSha ?? includeCommitSha)
}
}
extension Configuration.SemVar {
func merging(_ other: Self?) -> Self {
.init(
preRelease: other?.preRelease ?? preRelease,
requireExistingFile: other?.requireExistingFile ?? requireExistingFile,
requireExistingSemVar: other?.requireExistingSemVar ?? requireExistingSemVar
)
}
}
extension Configuration.VersionStrategy {
func merging(_ other: Self?) -> Self {
guard let branch else {
guard let semvar else { return self }
return .init(semvar: semvar.merging(other?.semvar))
}
return .init(branch: branch.merging(other?.branch))
}
}
@discardableResult
func withConfiguration<T>(
path: String?,
_ operation: (Configuration) async throws -> T
) async throws -> T {
@Dependency(\.configurationClient) var configurationClient
let configuration = try await configurationClient.findAndLoad(
path != nil ? URL(filePath: path!) : nil
)
return try await operation(configuration)
}

View File

@@ -7,6 +7,12 @@ import Rainbow
struct GlobalOptions<Child: ParsableArguments>: ParsableArguments { struct GlobalOptions<Child: ParsableArguments>: ParsableArguments {
@Option(
name: .shortAndLong,
help: "Specify the path to a configuration file."
)
var configurationFile: String?
@OptionGroup var targetOptions: TargetOptions @OptionGroup var targetOptions: TargetOptions
@OptionGroup var child: Child @OptionGroup var child: Child
@@ -71,7 +77,7 @@ struct PreReleaseOptions: ParsableArguments {
var useTagAsPreRelease: Bool = false var useTagAsPreRelease: Bool = false
@Option( @Option(
name: .shortAndLong, name: .long,
help: """ help: """
Apply custom pre-release suffix, can also use branch or tag along with this Apply custom pre-release suffix, can also use branch or tag along with this
option as a prefix, used if branch is not set. (example: \"rc\") option as a prefix, used if branch is not set. (example: \"rc\")
@@ -103,14 +109,18 @@ typealias GlobalSemVarOptions = GlobalOptions<SemVarOptions>
typealias GlobalBranchOptions = GlobalOptions<Empty> typealias GlobalBranchOptions = GlobalOptions<Empty>
extension GlobalSemVarOptions { extension GlobalSemVarOptions {
func shared() throws -> CliClient.SharedOptions { func shared() async throws -> CliClient.SharedOptions {
try shared(.semVar(child.semVarOptions())) try await withConfiguration(path: configurationFile) { configuration in
try shared(configuration.mergingStrategy(.init(semvar: child.configSemVarOptions())))
}
} }
} }
extension GlobalBranchOptions { extension GlobalBranchOptions {
func shared() throws -> CliClient.SharedOptions { func shared() async throws -> CliClient.SharedOptions {
try shared(.branchAndCommit) try await withConfiguration(path: configurationFile) { configuration in
try shared(configuration.mergingStrategy(.init(branch: .init())))
}
} }
} }
@@ -146,13 +156,12 @@ extension CliClient.SharedOptions {
extension GlobalOptions { extension GlobalOptions {
func shared(_ versionStrategy: CliClient.VersionStrategy) throws -> CliClient.SharedOptions { func shared(_ configuration: Configuration) throws -> CliClient.SharedOptions {
try .init( .init(
dryRun: dryRun, dryRun: dryRun,
gitDirectory: gitDirectory, gitDirectory: gitDirectory,
logLevel: .init(verbose: verbose), logLevel: .init(verbose: verbose),
target: targetOptions.target(), configuration: configuration
versionStrategy: versionStrategy
) )
} }
@@ -188,26 +197,6 @@ private extension TargetOptions {
extension PreReleaseOptions { extension PreReleaseOptions {
func preReleaseStrategy() throws -> CliClient.PreReleaseStrategy? {
guard let custom else {
if useBranchAsPreRelease {
return .branchAndCommit
} else if useTagAsPreRelease {
return .tag
} else {
return nil
}
}
if useBranchAsPreRelease {
return .custom(custom, .branchAndCommit)
} else if useTagAsPreRelease {
return .custom(custom, .tag)
} else {
return .custom(custom, nil)
}
}
func configPreReleaseStrategy() throws -> Configuration.PreReleaseStrategy? { func configPreReleaseStrategy() throws -> Configuration.PreReleaseStrategy? {
guard let custom else { guard let custom else {
if useBranchAsPreRelease { if useBranchAsPreRelease {
@@ -230,13 +219,6 @@ extension PreReleaseOptions {
} }
extension SemVarOptions { extension SemVarOptions {
func semVarOptions() throws -> CliClient.VersionStrategy.SemVarOptions {
try .init(
preReleaseStrategy: preRelease.preReleaseStrategy(),
requireExistingFile: requireExistingFile,
requireExistingSemVar: requireExistingSemvar
)
}
func configSemVarOptions() throws -> Configuration.SemVar { func configSemVarOptions() throws -> Configuration.SemVar {
try .init( try .init(

View File

@@ -1,4 +1,5 @@
@_spi(Internal) import CliClient @_spi(Internal) import CliClient
import ConfigurationClient
import Dependencies import Dependencies
import FileClient import FileClient
import Foundation import Foundation
@@ -20,7 +21,7 @@ struct CliClientTests {
@Dependency(\.cliClient) var client @Dependency(\.cliClient) var client
let output = try await client.build(.testOptions( let output = try await client.build(.testOptions(
target: target, target: target,
versionStrategy: .semVar(.init(requireExistingFile: false)) versionStrategy: .init(semvar: .init(requireExistingFile: false))
)) ))
#expect(output == "/baz/Sources/bar/Version.swift") #expect(output == "/baz/Sources/bar/Version.swift")
} }
@@ -65,7 +66,7 @@ struct CliClientTests {
@Dependency(\.cliClient) var client @Dependency(\.cliClient) var client
let output = try await client.build(.testOptions( let output = try await client.build(.testOptions(
target: target, target: target,
versionStrategy: .semVar(.init(requireExistingFile: false)) versionStrategy: .init(semvar: .init(requireExistingFile: false))
)) ))
#expect(output == "/baz/Sources/bar/Version.swift") #expect(output == "/baz/Sources/bar/Version.swift")
} }
@@ -113,7 +114,7 @@ struct CliClientTests {
} }
enum TestArguments { enum TestArguments {
static let testCases = ["bar", "Sources/bar", "/Sources/bar", "./Sources/bar"] static let testCases = ["bar", "Sources/bar", "./Sources/bar"]
static let bumpCases = CliClient.BumpOption.allCases.reduce(into: [(CliClient.BumpOption, Bool)]()) { static let bumpCases = CliClient.BumpOption.allCases.reduce(into: [(CliClient.BumpOption, Bool)]()) {
$0.append(($1, true)) $0.append(($1, true))
$0.append(($1, false)) $0.append(($1, false))
@@ -130,14 +131,16 @@ extension CliClient.SharedOptions {
dryRun: Bool = false, dryRun: Bool = false,
target: String = "bar", target: String = "bar",
logLevel: Logger.Level = .trace, logLevel: Logger.Level = .trace,
versionStrategy: CliClient.VersionStrategy = .semVar(.init()) versionStrategy: Configuration.VersionStrategy = .init(semvar: .init())
) -> Self { ) -> Self {
.init( .init(
dryRun: dryRun, dryRun: dryRun,
gitDirectory: gitDirectory, gitDirectory: gitDirectory,
logLevel: logLevel, logLevel: logLevel,
target: target, configuration: .init(
versionStrategy: versionStrategy target: .init(module: .init(target)),
strategy: versionStrategy
)
) )
} }
} }