feat: Updates internal version container used to derive next version in cli-client.
This commit is contained in:
@@ -12,174 +12,6 @@ extension Configuration {
|
||||
}
|
||||
return try target.url(gitDirectory: gitDirectory)
|
||||
}
|
||||
|
||||
func currentVersion(targetUrl: URL, gitDirectory: String?) async throws -> CurrentVersionContainer {
|
||||
guard let strategy else {
|
||||
throw ConfigurationParsingError.versionStrategyNotFound
|
||||
}
|
||||
return try await strategy.currentVersion(
|
||||
targetUrl: targetUrl,
|
||||
gitDirectory: gitDirectory
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private extension Configuration.SemVar.Strategy {
|
||||
|
||||
func getSemvar(gitDirectory: String? = nil) async throws -> SemVar {
|
||||
@Dependency(\.asyncShellClient) var asyncShellClient
|
||||
@Dependency(\.gitClient) var gitClient
|
||||
@Dependency(\.logger) var logger
|
||||
|
||||
let semvar: SemVar?
|
||||
|
||||
switch self {
|
||||
case let .command(arguments: arguments):
|
||||
logger.trace("Using custom command strategy with: \(arguments)")
|
||||
semvar = try await SemVar(string: asyncShellClient.background(.init(arguments)))
|
||||
case let .gitTag(exactMatch: exactMatch):
|
||||
logger.trace("Using gitTag strategy.")
|
||||
semvar = try await gitClient.version(.init(
|
||||
gitDirectory: gitDirectory,
|
||||
style: .tag(exactMatch: exactMatch ?? false)
|
||||
)).semVar
|
||||
}
|
||||
|
||||
guard let semvar else {
|
||||
throw CliClientError.semVarNotFound
|
||||
}
|
||||
|
||||
return semvar
|
||||
}
|
||||
}
|
||||
|
||||
@_spi(Internal)
|
||||
public extension Configuration.SemVar {
|
||||
|
||||
// TODO: Need to handle custom command semvar strategy.
|
||||
|
||||
func currentVersion(file: URL, gitDirectory: String? = nil) async throws -> CurrentVersionContainer.Version {
|
||||
@Dependency(\.fileClient) var fileClient
|
||||
@Dependency(\.gitClient) var gitClient
|
||||
@Dependency(\.logger) var logger
|
||||
|
||||
let fileOutput = try? await fileClient.semvar(file: file, gitDirectory: gitDirectory)
|
||||
var semVar = fileOutput?.semVar
|
||||
|
||||
logger.trace("file output semvar: \(String(describing: semVar))")
|
||||
|
||||
let usesOptionalType = fileOutput?.usesOptionalType
|
||||
|
||||
// We parsed a semvar from the existing file, use it.
|
||||
if semVar != nil {
|
||||
let semvarWithPreRelease = try await applyingPreRelease(semVar!, gitDirectory)
|
||||
|
||||
return .semvar(
|
||||
semvarWithPreRelease,
|
||||
usesOptionalType: usesOptionalType ?? false,
|
||||
hasChanges: semvarWithPreRelease != semVar
|
||||
)
|
||||
}
|
||||
|
||||
if requireExistingFile == true {
|
||||
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.")
|
||||
|
||||
// TODO: Is this what we want to do here? Seems that the strategy should be set by the client / configuration.
|
||||
|
||||
// Didn't have existing semVar loaded from file, so check for git-tag.
|
||||
semVar = try await gitClient.version(.init(
|
||||
gitDirectory: gitDirectory,
|
||||
style: .tag(exactMatch: false)
|
||||
)).semVar
|
||||
|
||||
if semVar != nil {
|
||||
let semvarWithPreRelease = try await applyingPreRelease(semVar!, gitDirectory)
|
||||
return .semvar(
|
||||
semvarWithPreRelease,
|
||||
usesOptionalType: usesOptionalType ?? false,
|
||||
hasChanges: semvarWithPreRelease != semVar
|
||||
)
|
||||
}
|
||||
|
||||
if requireExistingSemVar == true {
|
||||
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(
|
||||
applyingPreRelease(.init(), gitDirectory),
|
||||
usesOptionalType: usesOptionalType ?? false,
|
||||
hasChanges: true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension Configuration.VersionStrategy {
|
||||
|
||||
func loadNextVersion(gitDirectory: String?) async throws -> CurrentVersionContainer.Version {
|
||||
@Dependency(\.gitClient) var gitClient
|
||||
@Dependency(\.logger) var logger
|
||||
|
||||
switch self {
|
||||
case let .branch(includeCommitSha: includeCommitSha):
|
||||
logger.trace("Loading next version for branch strategy...")
|
||||
let next = try await gitClient.version(includeCommitSha: includeCommitSha, gitDirectory: gitDirectory)
|
||||
logger.trace("Next version: \(next)")
|
||||
return .string(next)
|
||||
case .semvar:
|
||||
logger.trace("Loading next version for semvar strategy...")
|
||||
let semvar = semvar!
|
||||
guard let strategy = semvar.strategy else {
|
||||
// TODO: Error here.
|
||||
fatalError()
|
||||
}
|
||||
let next = try await strategy.getSemvar(gitDirectory: gitDirectory)
|
||||
var nextString = ""
|
||||
customDump(next, to: &nextString)
|
||||
logger.trace("Next version:\n\(nextString)")
|
||||
|
||||
// TODO: Need to check for pre-release and load it here.
|
||||
|
||||
// TODO: Fix optional type / has changes.
|
||||
return .semvar(next, usesOptionalType: true, hasChanges: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension Configuration.VersionStrategy {
|
||||
|
||||
// TODO: This should just load the `nextVersion`, and should probably live on CurrentVersionContainer.
|
||||
|
||||
// FIX: Fix what's passed to current verions here.
|
||||
func currentVersion(targetUrl: URL, gitDirectory: String?) async throws -> CurrentVersionContainer {
|
||||
@Dependency(\.gitClient) var gitClient
|
||||
|
||||
guard let branch else {
|
||||
guard let semvar else {
|
||||
throw ConfigurationParsingError.versionStrategyError(
|
||||
message: "Neither branch nor semvar set on configuration."
|
||||
)
|
||||
}
|
||||
return try await .init(
|
||||
targetUrl: targetUrl,
|
||||
currentVersion: nil,
|
||||
version: semvar.currentVersion(file: targetUrl, gitDirectory: gitDirectory)
|
||||
)
|
||||
}
|
||||
return try await .init(
|
||||
targetUrl: targetUrl,
|
||||
currentVersion: nil,
|
||||
version: .string(
|
||||
gitClient.version(includeCommitSha: branch.includeCommitSha, gitDirectory: gitDirectory)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private extension Configuration.Target {
|
||||
@@ -217,101 +49,6 @@ private extension Configuration.Target {
|
||||
}
|
||||
}
|
||||
|
||||
private extension GitClient {
|
||||
func version(includeCommitSha: Bool, gitDirectory: String?) async throws -> String {
|
||||
@Dependency(\.gitClient) var gitClient
|
||||
|
||||
return try await gitClient.version(.init(
|
||||
gitDirectory: gitDirectory,
|
||||
style: .branch(commitSha: includeCommitSha)
|
||||
)).description
|
||||
}
|
||||
}
|
||||
|
||||
private extension Configuration.PreRelease {
|
||||
|
||||
func preReleaseString(gitDirectory: String?) async throws -> PreReleaseString? {
|
||||
guard let strategy else { return nil }
|
||||
|
||||
@Dependency(\.asyncShellClient) var asyncShellClient
|
||||
@Dependency(\.gitClient) var gitClient
|
||||
@Dependency(\.logger) var logger
|
||||
|
||||
var preReleaseString: String
|
||||
var suffix = true
|
||||
var allowsPrefix = true
|
||||
|
||||
switch strategy {
|
||||
case let .branch(includeCommitSha: includeCommitSha):
|
||||
logger.trace("Branch pre-release strategy, includeCommitSha: \(includeCommitSha).")
|
||||
preReleaseString = try await gitClient.version(
|
||||
includeCommitSha: includeCommitSha,
|
||||
gitDirectory: gitDirectory
|
||||
)
|
||||
case let .command(arguments: arguments, allowPrefix: allowPrefix):
|
||||
logger.trace("Command pre-release strategy, arguments: \(arguments).")
|
||||
preReleaseString = try await asyncShellClient.background(.init(arguments))
|
||||
allowsPrefix = allowPrefix ?? false
|
||||
case .gitTag:
|
||||
logger.trace("Git tag pre-release strategy.")
|
||||
logger.trace("This will ignore any set prefix.")
|
||||
suffix = false
|
||||
allowsPrefix = false
|
||||
preReleaseString = try await gitClient.version(.init(
|
||||
gitDirectory: gitDirectory,
|
||||
style: .tag(exactMatch: false)
|
||||
)).description
|
||||
}
|
||||
|
||||
if let prefix, allowsPrefix {
|
||||
preReleaseString = "\(prefix)-\(preReleaseString)"
|
||||
}
|
||||
|
||||
guard suffix else { return .semvar(preReleaseString) }
|
||||
return .suffix(preReleaseString)
|
||||
}
|
||||
|
||||
enum PreReleaseString: Sendable {
|
||||
case suffix(String)
|
||||
case semvar(String)
|
||||
}
|
||||
}
|
||||
|
||||
private extension Configuration.SemVar {
|
||||
|
||||
// TODO: Move this to SemVar, not Configuration.SemVar
|
||||
func applyingPreRelease(_ semvar: SemVar, _ gitDirectory: String?) async throws -> SemVar {
|
||||
@Dependency(\.logger) var logger
|
||||
logger.trace("Start apply pre-release to: \(semvar)")
|
||||
|
||||
guard let preReleaseStrategy = self.preRelease,
|
||||
let preRelease = try await preReleaseStrategy.preReleaseString(gitDirectory: gitDirectory)
|
||||
else {
|
||||
logger.trace("No pre-release strategy, returning original semvar.")
|
||||
return semvar
|
||||
}
|
||||
|
||||
logger.trace("Pre-release string: \(preRelease)")
|
||||
|
||||
switch preRelease {
|
||||
case let .suffix(string):
|
||||
return semvar.applyingPreRelease(string)
|
||||
case let .semvar(string):
|
||||
guard let semvar = SemVar(string: string) else {
|
||||
throw CliClientError.preReleaseParsingError(string)
|
||||
}
|
||||
if let prefix = self.preRelease?.prefix {
|
||||
var prefixString = prefix
|
||||
if let preReleaseString = semvar.preRelease {
|
||||
prefixString = "\(prefix)-\(preReleaseString)"
|
||||
}
|
||||
return semvar.applyingPreRelease(prefixString)
|
||||
}
|
||||
return semvar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum ConfigurationParsingError: Error {
|
||||
case targetNotFound
|
||||
case pathOrModuleNotSet
|
||||
|
||||
Reference in New Issue
Block a user