feat: Begin cleaning up cli-client for better separation for current and next versions.
All checks were successful
CI / Ubuntu (push) Successful in 2m33s
All checks were successful
CI / Ubuntu (push) Successful in 2m33s
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"originHash" : "3640b52c8069b868611efbfbd9b7545872526454802225747f7cd878062df1db",
|
"originHash" : "9fe004cf869b34d1fe07e8b58a90b044281e8e94805df6723d4604ba5a6400d9",
|
||||||
"pins" : [
|
"pins" : [
|
||||||
{
|
{
|
||||||
"identity" : "combine-schedulers",
|
"identity" : "combine-schedulers",
|
||||||
|
|||||||
@@ -96,10 +96,14 @@ public extension CliClient.SharedOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add optional property for currentVersion (loaded version from file)
|
||||||
|
// and rename version to nextVersion.
|
||||||
|
|
||||||
@_spi(Internal)
|
@_spi(Internal)
|
||||||
public struct CurrentVersionContainer: Sendable {
|
public struct CurrentVersionContainer: Sendable {
|
||||||
|
|
||||||
let targetUrl: URL
|
let targetUrl: URL
|
||||||
|
let currentVersion: CurrentVersion?
|
||||||
let version: Version
|
let version: Version
|
||||||
|
|
||||||
var usesOptionalType: Bool {
|
var usesOptionalType: Bool {
|
||||||
@@ -109,8 +113,15 @@ public struct CurrentVersionContainer: Sendable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum CurrentVersion: Sendable {
|
||||||
|
case branch(String, usesOptionalType: Bool)
|
||||||
|
case semvar(SemVar, usesOptionalType: Bool)
|
||||||
|
}
|
||||||
|
|
||||||
public enum Version: Sendable {
|
public enum Version: Sendable {
|
||||||
|
// TODO: Call this branch for consistency.
|
||||||
case string(String)
|
case string(String)
|
||||||
|
// TODO: Remove has changes when currentVersion/nextVersion is implemented.
|
||||||
case semvar(SemVar, usesOptionalType: Bool = true, hasChanges: Bool)
|
case semvar(SemVar, usesOptionalType: Bool = true, hasChanges: Bool)
|
||||||
|
|
||||||
func string(allowPreReleaseTag: Bool) throws -> String {
|
func string(allowPreReleaseTag: Bool) throws -> String {
|
||||||
|
|||||||
@@ -23,6 +23,35 @@ extension Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
@_spi(Internal)
|
||||||
public extension Configuration.SemVar {
|
public extension Configuration.SemVar {
|
||||||
|
|
||||||
@@ -92,6 +121,9 @@ public extension Configuration.SemVar {
|
|||||||
|
|
||||||
private extension Configuration.VersionStrategy {
|
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 {
|
func currentVersion(targetUrl: URL, gitDirectory: String?) async throws -> CurrentVersionContainer {
|
||||||
@Dependency(\.gitClient) var gitClient
|
@Dependency(\.gitClient) var gitClient
|
||||||
|
|
||||||
@@ -103,11 +135,13 @@ private extension Configuration.VersionStrategy {
|
|||||||
}
|
}
|
||||||
return try await .init(
|
return try await .init(
|
||||||
targetUrl: targetUrl,
|
targetUrl: targetUrl,
|
||||||
|
currentVersion: nil,
|
||||||
version: semvar.currentVersion(file: targetUrl, gitDirectory: gitDirectory)
|
version: semvar.currentVersion(file: targetUrl, gitDirectory: gitDirectory)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return try await .init(
|
return try await .init(
|
||||||
targetUrl: targetUrl,
|
targetUrl: targetUrl,
|
||||||
|
currentVersion: nil,
|
||||||
version: .string(
|
version: .string(
|
||||||
gitClient.version(includeCommitSha: branch.includeCommitSha, gitDirectory: gitDirectory)
|
gitClient.version(includeCommitSha: branch.includeCommitSha, gitDirectory: gitDirectory)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,6 +5,46 @@ import GitClient
|
|||||||
|
|
||||||
@_spi(Internal)
|
@_spi(Internal)
|
||||||
public extension FileClient {
|
public extension FileClient {
|
||||||
|
|
||||||
|
func loadCurrentVersion(
|
||||||
|
url: URL,
|
||||||
|
gitDirectory: String?,
|
||||||
|
expectsBranch: Bool
|
||||||
|
) async throws -> CurrentVersionContainer.CurrentVersion? {
|
||||||
|
@Dependency(\.logger) var logger
|
||||||
|
|
||||||
|
switch expectsBranch {
|
||||||
|
case true:
|
||||||
|
let (string, usesOptionalType) = try await branch(file: url, gitDirectory: gitDirectory)
|
||||||
|
logger.debug("Loaded branch: \(string)")
|
||||||
|
return .branch(string, usesOptionalType: usesOptionalType)
|
||||||
|
case false:
|
||||||
|
let (semvar, usesOptionalType) = try await semvar(file: url, gitDirectory: gitDirectory)
|
||||||
|
guard let semvar else { return nil }
|
||||||
|
logger.debug("Semvar: \(semvar)")
|
||||||
|
return .semvar(semvar, usesOptionalType: usesOptionalType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Make private.
|
||||||
|
func branch(
|
||||||
|
file: URL,
|
||||||
|
gitDirectory: String?
|
||||||
|
) async throws -> (string: String, usesOptionalType: Bool) {
|
||||||
|
let (string, usesOptionalType) = try await getVersionString(fileUrl: file, gitDirectory: gitDirectory)
|
||||||
|
return (string, usesOptionalType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Make private.
|
||||||
|
func semvar(
|
||||||
|
file: URL,
|
||||||
|
gitDirectory: String?
|
||||||
|
) async throws -> (semVar: SemVar?, usesOptionalType: Bool) {
|
||||||
|
let (string, usesOptionalType) = try await getVersionString(fileUrl: file, gitDirectory: gitDirectory)
|
||||||
|
let semvar = SemVar(string: string)
|
||||||
|
return (semvar, usesOptionalType)
|
||||||
|
}
|
||||||
|
|
||||||
private func getVersionString(
|
private func getVersionString(
|
||||||
fileUrl: URL,
|
fileUrl: URL,
|
||||||
gitDirectory: String?
|
gitDirectory: String?
|
||||||
@@ -38,15 +78,4 @@ public extension FileClient {
|
|||||||
return (String(versionString), isOptional)
|
return (String(versionString), isOptional)
|
||||||
}
|
}
|
||||||
|
|
||||||
func semvar(
|
|
||||||
file: URL,
|
|
||||||
gitDirectory: String?
|
|
||||||
) async throws -> (semVar: SemVar?, usesOptionalType: Bool) {
|
|
||||||
@Dependency(\.logger) var logger
|
|
||||||
let (string, usesOptionalType) = try await getVersionString(fileUrl: file, gitDirectory: gitDirectory)
|
|
||||||
let semvar = SemVar(string: string)
|
|
||||||
logger.debug("Semvar: \(String(describing: semvar))")
|
|
||||||
return (semvar, usesOptionalType)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,95 +44,6 @@ public struct Configuration: Codable, Equatable, Sendable {
|
|||||||
|
|
||||||
public extension Configuration {
|
public extension Configuration {
|
||||||
|
|
||||||
/// Represents a branch version or pre-release strategy.
|
|
||||||
///
|
|
||||||
/// This derives the version or pre-release suffix from the branch name and
|
|
||||||
/// optionally the short version of the commit sha.
|
|
||||||
struct Branch: Codable, Equatable, Sendable {
|
|
||||||
|
|
||||||
/// Include the commit sha in the output for this strategy.
|
|
||||||
public let includeCommitSha: Bool
|
|
||||||
|
|
||||||
/// Create a new branch strategy.
|
|
||||||
///
|
|
||||||
/// - Parameters:
|
|
||||||
/// - includeCommitSha: Whether to include the commit sha.
|
|
||||||
public init(includeCommitSha: Bool = true) {
|
|
||||||
self.includeCommitSha = includeCommitSha
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents version strategy for pre-release.
|
|
||||||
///
|
|
||||||
/// This appends a suffix to the version that get's generated from the version strategy.
|
|
||||||
/// For example: `1.0.0-rc-1`
|
|
||||||
///
|
|
||||||
struct PreRelease: Codable, Equatable, Sendable {
|
|
||||||
|
|
||||||
public let prefix: String?
|
|
||||||
public let strategy: Strategy?
|
|
||||||
|
|
||||||
public init(
|
|
||||||
prefix: String? = nil,
|
|
||||||
strategy: Strategy? = nil
|
|
||||||
) {
|
|
||||||
self.prefix = prefix
|
|
||||||
self.strategy = strategy
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Strategy: Codable, Equatable, Sendable {
|
|
||||||
case branch(includeCommitSha: Bool = true)
|
|
||||||
case command(arguments: [String], allowPrefix: Bool? = nil)
|
|
||||||
case gitTag
|
|
||||||
|
|
||||||
public var branch: Branch? {
|
|
||||||
guard case let .branch(includeCommitSha) = self
|
|
||||||
else { return nil }
|
|
||||||
return .init(includeCommitSha: includeCommitSha)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents a semvar version strategy.
|
|
||||||
///
|
|
||||||
/// ## Example: 1.0.0
|
|
||||||
///
|
|
||||||
struct SemVar: Codable, Equatable, Sendable {
|
|
||||||
|
|
||||||
public let allowPreRelease: Bool?
|
|
||||||
|
|
||||||
/// Optional pre-releas suffix strategy.
|
|
||||||
public let preRelease: PreRelease?
|
|
||||||
|
|
||||||
/// Fail if an existing version file does not exist in the target.
|
|
||||||
public let requireExistingFile: Bool?
|
|
||||||
|
|
||||||
/// Fail if an existing semvar is not parsed from the file or version generation strategy.
|
|
||||||
public let requireExistingSemVar: Bool?
|
|
||||||
|
|
||||||
public let strategy: Strategy?
|
|
||||||
|
|
||||||
public init(
|
|
||||||
allowPreRelease: Bool? = true,
|
|
||||||
preRelease: PreRelease? = nil,
|
|
||||||
requireExistingFile: Bool? = false,
|
|
||||||
requireExistingSemVar: Bool? = false,
|
|
||||||
strategy: Strategy? = nil
|
|
||||||
) {
|
|
||||||
self.allowPreRelease = allowPreRelease
|
|
||||||
self.preRelease = preRelease
|
|
||||||
self.requireExistingFile = requireExistingFile
|
|
||||||
self.requireExistingSemVar = requireExistingSemVar
|
|
||||||
self.strategy = strategy
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Strategy: Codable, Equatable, Sendable {
|
|
||||||
case command(arguments: [String])
|
|
||||||
case gitTag(exactMatch: Bool? = false)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents the target where we will bump the version in.
|
/// Represents the target where we will bump the version in.
|
||||||
///
|
///
|
||||||
/// This can either be a path to a version file or a module used to
|
/// This can either be a path to a version file or a module used to
|
||||||
@@ -283,4 +194,93 @@ public extension Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents a branch version or pre-release strategy.
|
||||||
|
///
|
||||||
|
/// This derives the version or pre-release suffix from the branch name and
|
||||||
|
/// optionally the short version of the commit sha.
|
||||||
|
struct Branch: Codable, Equatable, Sendable {
|
||||||
|
|
||||||
|
/// Include the commit sha in the output for this strategy.
|
||||||
|
public let includeCommitSha: Bool
|
||||||
|
|
||||||
|
/// Create a new branch strategy.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - includeCommitSha: Whether to include the commit sha.
|
||||||
|
public init(includeCommitSha: Bool = true) {
|
||||||
|
self.includeCommitSha = includeCommitSha
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents version strategy for pre-release.
|
||||||
|
///
|
||||||
|
/// This appends a suffix to the version that get's generated from the version strategy.
|
||||||
|
/// For example: `1.0.0-rc-1`
|
||||||
|
///
|
||||||
|
struct PreRelease: Codable, Equatable, Sendable {
|
||||||
|
|
||||||
|
public let prefix: String?
|
||||||
|
public let strategy: Strategy?
|
||||||
|
|
||||||
|
public init(
|
||||||
|
prefix: String? = nil,
|
||||||
|
strategy: Strategy? = nil
|
||||||
|
) {
|
||||||
|
self.prefix = prefix
|
||||||
|
self.strategy = strategy
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Strategy: Codable, Equatable, Sendable {
|
||||||
|
case branch(includeCommitSha: Bool = true)
|
||||||
|
case command(arguments: [String], allowPrefix: Bool? = nil)
|
||||||
|
case gitTag
|
||||||
|
|
||||||
|
public var branch: Branch? {
|
||||||
|
guard case let .branch(includeCommitSha) = self
|
||||||
|
else { return nil }
|
||||||
|
return .init(includeCommitSha: includeCommitSha)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents a semvar version strategy.
|
||||||
|
///
|
||||||
|
/// ## Example: 1.0.0
|
||||||
|
///
|
||||||
|
struct SemVar: Codable, Equatable, Sendable {
|
||||||
|
|
||||||
|
public let allowPreRelease: Bool?
|
||||||
|
|
||||||
|
/// Optional pre-releas suffix strategy.
|
||||||
|
public let preRelease: PreRelease?
|
||||||
|
|
||||||
|
/// Fail if an existing version file does not exist in the target.
|
||||||
|
public let requireExistingFile: Bool?
|
||||||
|
|
||||||
|
/// Fail if an existing semvar is not parsed from the file or version generation strategy.
|
||||||
|
public let requireExistingSemVar: Bool?
|
||||||
|
|
||||||
|
public let strategy: Strategy?
|
||||||
|
|
||||||
|
public init(
|
||||||
|
allowPreRelease: Bool? = true,
|
||||||
|
preRelease: PreRelease? = nil,
|
||||||
|
requireExistingFile: Bool? = false,
|
||||||
|
requireExistingSemVar: Bool? = false,
|
||||||
|
strategy: Strategy? = nil
|
||||||
|
) {
|
||||||
|
self.allowPreRelease = allowPreRelease
|
||||||
|
self.preRelease = preRelease
|
||||||
|
self.requireExistingFile = requireExistingFile
|
||||||
|
self.requireExistingSemVar = requireExistingSemVar
|
||||||
|
self.strategy = strategy
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Strategy: Codable, Equatable, Sendable {
|
||||||
|
case command(arguments: [String])
|
||||||
|
case gitTag(exactMatch: Bool? = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import DependenciesMacros
|
|||||||
import FileClient
|
import FileClient
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
// TODO: Add a method to get a semvar / handle a version strategy's ??
|
||||||
|
|
||||||
public extension DependencyValues {
|
public extension DependencyValues {
|
||||||
|
|
||||||
/// Perform operations with configuration files.
|
/// Perform operations with configuration files.
|
||||||
@@ -16,6 +18,12 @@ public extension DependencyValues {
|
|||||||
@DependencyClient
|
@DependencyClient
|
||||||
public struct ConfigurationClient: Sendable {
|
public struct ConfigurationClient: Sendable {
|
||||||
|
|
||||||
|
fileprivate enum Constants {
|
||||||
|
static let defaultFileNameWithoutExtension = ".bump-version"
|
||||||
|
static let defaultExtension = "json"
|
||||||
|
static var defaultFileName: String { "\(defaultFileNameWithoutExtension).\(defaultExtension)" }
|
||||||
|
}
|
||||||
|
|
||||||
/// The default file name for a configuration file.
|
/// The default file name for a configuration file.
|
||||||
public var defaultFileName: @Sendable () -> String = { "test.json" }
|
public var defaultFileName: @Sendable () -> String = { "test.json" }
|
||||||
|
|
||||||
@@ -89,15 +97,13 @@ extension ConfigurationClient: DependencyKey {
|
|||||||
private func findConfiguration(_ url: URL?) async throws -> URL? {
|
private func findConfiguration(_ url: URL?) async throws -> URL? {
|
||||||
@Dependency(\.fileClient) var fileClient
|
@Dependency(\.fileClient) var fileClient
|
||||||
|
|
||||||
let defaultFileName = ConfigurationClient.Constants.defaultFileNameWithoutExtension
|
|
||||||
|
|
||||||
var url: URL! = url
|
var url: URL! = url
|
||||||
if url == nil {
|
if url == nil {
|
||||||
url = try await URL(filePath: fileClient.currentDirectory())
|
url = try await URL(filePath: fileClient.currentDirectory())
|
||||||
}
|
}
|
||||||
|
|
||||||
if try await fileClient.isDirectory(url.cleanFilePath) {
|
if try await fileClient.isDirectory(url.cleanFilePath) {
|
||||||
url = url.appending(path: "\(defaultFileName).json")
|
url = url.appending(path: ConfigurationClient.Constants.defaultFileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if fileClient.fileExists(url) {
|
if fileClient.fileExists(url) {
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
extension ConfigurationClient {
|
extension ConfigurationClient {
|
||||||
enum Constants {
|
|
||||||
static let defaultFileNameWithoutExtension = ".bump-version"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user