Compare commits
4 Commits
f1eb883b93
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
016f0d6c3f
|
|||
|
147f6df1b3
|
|||
|
5c22250a63
|
|||
|
9dd30a1745
|
@@ -55,6 +55,7 @@ let package = Package(
|
|||||||
name: "ConfigurationClient",
|
name: "ConfigurationClient",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
"FileClient",
|
"FileClient",
|
||||||
|
"LoggingExtensions",
|
||||||
.product(name: "CustomDump", package: "swift-custom-dump"),
|
.product(name: "CustomDump", package: "swift-custom-dump"),
|
||||||
.product(name: "Dependencies", package: "swift-dependencies"),
|
.product(name: "Dependencies", package: "swift-dependencies"),
|
||||||
.product(name: "DependenciesMacros", package: "swift-dependencies")
|
.product(name: "DependenciesMacros", package: "swift-dependencies")
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ extension ConfigCommand {
|
|||||||
@OptionGroup var globals: ConfigCommandOptions
|
@OptionGroup var globals: ConfigCommandOptions
|
||||||
|
|
||||||
func run() async throws {
|
func run() async throws {
|
||||||
|
@Dependency(\.logger) var logger
|
||||||
let configuration = try await globals
|
let configuration = try await globals
|
||||||
.shared(command: Self.commandName)
|
.shared(command: Self.commandName)
|
||||||
.runClient(\.parsedConfiguration)
|
.runClient(\.parsedConfiguration)
|
||||||
@@ -183,7 +184,11 @@ private extension ConfigCommand.DumpConfig {
|
|||||||
private extension ConfigCommand.ConfigCommandOptions {
|
private extension ConfigCommand.ConfigCommandOptions {
|
||||||
|
|
||||||
func shared(command: String) throws -> CliClient.SharedOptions {
|
func shared(command: String) throws -> CliClient.SharedOptions {
|
||||||
try configOptions.shared(command: command, extraOptions: extraOptions, verbose: verbose)
|
try configOptions.shared(
|
||||||
|
command: command,
|
||||||
|
extraOptions: extraOptions,
|
||||||
|
verbose: verbose
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handlePrintJson(_ configuration: Configuration) throws {
|
func handlePrintJson(_ configuration: Configuration) throws {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ of their usage.
|
|||||||
### Configuration Options
|
### Configuration Options
|
||||||
|
|
||||||
| Short | Long | Argument | Description |
|
| Short | Long | Argument | Description |
|
||||||
| ----- | ---------------------------------- | ----------- | ---------------------------------------------------------------------------------- |
|
| ----- | ---------------------------------- | ------------ | ----------------------------------------------------------------------------------- |
|
||||||
| -f | --configuration-file | <path> | The path to the configuration to use. |
|
| -f | --configuration-file | <path> | The path to the configuration to use. |
|
||||||
| -m | --target-module | <name> | The target module name inside your project |
|
| -m | --target-module | <name> | The target module name inside your project |
|
||||||
| -n | --target-file-name | <name> | The file name for the version to be found inside the module |
|
| -n | --target-file-name | <name> | The file name for the version to be found inside the module |
|
||||||
@@ -31,6 +31,12 @@ of their usage.
|
|||||||
| -c | --custom-command | <arguments> | Use a custom command strategy for the version (any options need to proceed a '--') |
|
| -c | --custom-command | <arguments> | Use a custom command strategy for the version (any options need to proceed a '--') |
|
||||||
| N/A | --commit-sha/--no-commit-sha | N/A | Use the commit sha with branch version or pre-release strategy |
|
| N/A | --commit-sha/--no-commit-sha | N/A | Use the commit sha with branch version or pre-release strategy |
|
||||||
| N/A | --require-configuration | N/A | Fail if a configuration file is not found |
|
| N/A | --require-configuration | N/A | Fail if a configuration file is not found |
|
||||||
|
| N/A | --precedence | <precedence> | The precedence for when a file exists (values: ['file', 'strategy'], default: file) |
|
||||||
|
|
||||||
|
> Note: Precedence is used as tie breaker if the version in the file does not agree with the version
|
||||||
|
> from the configured strategy. This can happen if a file was edited / bumped manually or the value
|
||||||
|
> returned from the external command is not similar to the version in the file. By default the file
|
||||||
|
> will take precedence over what is returned from the strategy.
|
||||||
|
|
||||||
#### Pre-Release Options
|
#### Pre-Release Options
|
||||||
|
|
||||||
|
|||||||
@@ -173,5 +173,19 @@ struct SemVarOptions: ParsableArguments {
|
|||||||
)
|
)
|
||||||
var customCommand: Bool = false
|
var customCommand: Bool = false
|
||||||
|
|
||||||
|
@Option(
|
||||||
|
name: .long,
|
||||||
|
help: """
|
||||||
|
Set the precence to prefer version from file or strategy.
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
var precedence: Configuration.SemVar.Precedence?
|
||||||
|
|
||||||
@OptionGroup var preRelease: PreReleaseOptions
|
@OptionGroup var preRelease: PreReleaseOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension Configuration.SemVar.Precedence: ExpressibleByArgument {
|
||||||
|
public init?(argument: String) {
|
||||||
|
self.init(rawValue: argument)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -136,8 +136,11 @@ extension SemVarOptions {
|
|||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.trace("precedence: \(String(describing: precedence))")
|
||||||
|
|
||||||
return try .init(
|
return try .init(
|
||||||
allowPreRelease: !preRelease.disablePreRelease,
|
allowPreRelease: !preRelease.disablePreRelease,
|
||||||
|
precedence: precedence,
|
||||||
preRelease: customCommand ? nil : preRelease.configPreReleaseStrategy(
|
preRelease: customCommand ? nil : preRelease.configPreReleaseStrategy(
|
||||||
includeCommitSha: includeCommitSha,
|
includeCommitSha: includeCommitSha,
|
||||||
extraOptions: extraOptions
|
extraOptions: extraOptions
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public struct CliClient: Sendable {
|
|||||||
public var build: @Sendable (SharedOptions) async throws -> String
|
public var build: @Sendable (SharedOptions) async throws -> String
|
||||||
|
|
||||||
/// Bump the existing version.
|
/// Bump the existing version.
|
||||||
public var bump: @Sendable (BumpOption?, SharedOptions) async throws -> String
|
public var bump: @Sendable (BumpOption, SharedOptions) async throws -> String
|
||||||
|
|
||||||
/// Generate a version file with an optional version that can be set manually.
|
/// Generate a version file with an optional version that can be set manually.
|
||||||
public var generate: @Sendable (SharedOptions) async throws -> String
|
public var generate: @Sendable (SharedOptions) async throws -> String
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ extension CliClient.SharedOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This will fail if the target url is not set properly.
|
// This will fail if the target url is not set properly.
|
||||||
let targetUrl = try configuration.targetUrl(gitDirectory: projectDirectory)
|
let targetUrl = try configuration.targetUrl(projectDirectory: projectDirectory)
|
||||||
logger.debug("Target: \(targetUrl.cleanFilePath)")
|
logger.debug("Target: \(targetUrl.cleanFilePath)")
|
||||||
|
|
||||||
// Perform the operation, which generates the new version and writes it.
|
// Perform the operation, which generates the new version and writes it.
|
||||||
@@ -82,19 +82,19 @@ extension CliClient.SharedOptions {
|
|||||||
@Dependency(\.logger) var logger
|
@Dependency(\.logger) var logger
|
||||||
logger.trace("Begin writing version.")
|
logger.trace("Begin writing version.")
|
||||||
|
|
||||||
let hasChanges: Bool
|
// let hasChanges: Bool
|
||||||
let targetUrl: URL
|
let targetUrl: URL
|
||||||
let usesOptionalType: Bool
|
let usesOptionalType: Bool
|
||||||
let versionString: String?
|
let versionString: String?
|
||||||
|
|
||||||
switch currentVersion {
|
switch currentVersion {
|
||||||
case let .branch(branch):
|
case let .branch(branch):
|
||||||
hasChanges = branch.hasChanges
|
// hasChanges = branch.hasChanges
|
||||||
targetUrl = branch.targetUrl
|
targetUrl = branch.targetUrl
|
||||||
usesOptionalType = branch.usesOptionalType
|
usesOptionalType = branch.usesOptionalType
|
||||||
versionString = branch.versionString
|
versionString = branch.versionString
|
||||||
case let .semvar(semvar):
|
case let .semvar(semvar):
|
||||||
hasChanges = semvar.hasChanges
|
// hasChanges = semvar.hasChanges
|
||||||
targetUrl = semvar.targetUrl
|
targetUrl = semvar.targetUrl
|
||||||
usesOptionalType = semvar.usesOptionalType
|
usesOptionalType = semvar.usesOptionalType
|
||||||
versionString = semvar.versionString(withPreRelease: allowPreReleaseTag)
|
versionString = semvar.versionString(withPreRelease: allowPreReleaseTag)
|
||||||
@@ -132,11 +132,7 @@ extension CliClient.SharedOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func bump(_ type: CliClient.BumpOption?) async throws -> String {
|
func bump(_ type: CliClient.BumpOption) async throws -> String {
|
||||||
guard let type else {
|
|
||||||
return try await generate()
|
|
||||||
}
|
|
||||||
|
|
||||||
return try await run { container in
|
return try await run { container in
|
||||||
|
|
||||||
@Dependency(\.logger) var logger
|
@Dependency(\.logger) var logger
|
||||||
@@ -175,3 +171,15 @@ extension CliClient.SharedOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private extension CurrentVersionContainer where Version == SemVar {
|
||||||
|
func withUpdateNextVersion(_ next: SemVar) -> Self {
|
||||||
|
.init(
|
||||||
|
targetUrl: targetUrl,
|
||||||
|
usesOptionalType: usesOptionalType,
|
||||||
|
loadedVersion: loadedVersion,
|
||||||
|
precedence: .strategy, // make sure to use the next version, since it was specified, as this is called from `bump`.
|
||||||
|
strategyVersion: next
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,16 +6,16 @@ import GitClient
|
|||||||
import ShellClient
|
import ShellClient
|
||||||
|
|
||||||
extension Configuration {
|
extension Configuration {
|
||||||
func targetUrl(gitDirectory: String?) throws -> URL {
|
func targetUrl(projectDirectory: String?) throws -> URL {
|
||||||
guard let target else {
|
guard let target else {
|
||||||
throw ConfigurationParsingError.targetNotFound
|
throw ConfigurationParsingError.targetNotFound
|
||||||
}
|
}
|
||||||
return try target.url(gitDirectory: gitDirectory)
|
return try target.url(projectDirectory: projectDirectory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension Configuration.Target {
|
private extension Configuration.Target {
|
||||||
func url(gitDirectory: String?) throws -> URL {
|
func url(projectDirectory: String?) throws -> URL {
|
||||||
@Dependency(\.logger) var logger
|
@Dependency(\.logger) var logger
|
||||||
|
|
||||||
let filePath: String
|
let filePath: String
|
||||||
@@ -42,8 +42,8 @@ private extension Configuration.Target {
|
|||||||
filePath = "\(path)/\(module.fileNameOrDefault)"
|
filePath = "\(path)/\(module.fileNameOrDefault)"
|
||||||
}
|
}
|
||||||
|
|
||||||
if let gitDirectory {
|
if let projectDirectory {
|
||||||
return URL(filePath: "\(gitDirectory)/\(filePath)")
|
return URL(filePath: "\(projectDirectory)/\(filePath)")
|
||||||
}
|
}
|
||||||
return URL(filePath: filePath)
|
return URL(filePath: filePath)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import GitClient
|
|||||||
public extension FileClient {
|
public extension FileClient {
|
||||||
func branch(
|
func branch(
|
||||||
file: URL,
|
file: URL,
|
||||||
gitDirectory: String?,
|
projectDirectory: String?,
|
||||||
requireExistingFile: Bool
|
requireExistingFile: Bool
|
||||||
) async throws -> (string: String, usesOptionalType: Bool)? {
|
) async throws -> (string: String, usesOptionalType: Bool)? {
|
||||||
let loaded = try? await getVersionString(fileUrl: file, gitDirectory: gitDirectory)
|
let loaded = try? await getVersionString(fileUrl: file, projectDirectory: projectDirectory)
|
||||||
guard let loaded else {
|
guard let loaded else {
|
||||||
if requireExistingFile {
|
if requireExistingFile {
|
||||||
throw CliClientError.fileDoesNotExist(path: file.cleanFilePath)
|
throw CliClientError.fileDoesNotExist(path: file.cleanFilePath)
|
||||||
@@ -22,10 +22,10 @@ public extension FileClient {
|
|||||||
|
|
||||||
func semvar(
|
func semvar(
|
||||||
file: URL,
|
file: URL,
|
||||||
gitDirectory: String?,
|
projectDirectory: String?,
|
||||||
requireExistingFile: Bool
|
requireExistingFile: Bool
|
||||||
) async throws -> (semVar: SemVar?, usesOptionalType: Bool)? {
|
) async throws -> (semVar: SemVar?, usesOptionalType: Bool)? {
|
||||||
let loaded = try? await getVersionString(fileUrl: file, gitDirectory: gitDirectory)
|
let loaded = try? await getVersionString(fileUrl: file, projectDirectory: projectDirectory)
|
||||||
guard let loaded else {
|
guard let loaded else {
|
||||||
if requireExistingFile {
|
if requireExistingFile {
|
||||||
throw CliClientError.fileDoesNotExist(path: file.cleanFilePath)
|
throw CliClientError.fileDoesNotExist(path: file.cleanFilePath)
|
||||||
@@ -38,7 +38,7 @@ public extension FileClient {
|
|||||||
|
|
||||||
private func getVersionString(
|
private func getVersionString(
|
||||||
fileUrl: URL,
|
fileUrl: URL,
|
||||||
gitDirectory: String?
|
projectDirectory: String?
|
||||||
) async throws -> (version: String, usesOptionalType: Bool) {
|
) async throws -> (version: String, usesOptionalType: Bool) {
|
||||||
@Dependency(\.gitClient) var gitClient
|
@Dependency(\.gitClient) var gitClient
|
||||||
@Dependency(\.logger) var logger
|
@Dependency(\.logger) var logger
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ enum VersionContainer: Sendable {
|
|||||||
case let .branch(includeCommitSha: includeCommitSha):
|
case let .branch(includeCommitSha: includeCommitSha):
|
||||||
return try await .branch(.load(
|
return try await .branch(.load(
|
||||||
branch: .init(includeCommitSha: includeCommitSha),
|
branch: .init(includeCommitSha: includeCommitSha),
|
||||||
gitDirectory: projectDirectory,
|
projectDirectory: projectDirectory,
|
||||||
url: url
|
url: url
|
||||||
))
|
))
|
||||||
case .semvar:
|
case .semvar:
|
||||||
return try await .semvar(.load(
|
return try await .semvar(.load(
|
||||||
semvar: strategy.semvar!,
|
semvar: strategy.semvar!,
|
||||||
gitDirectory: projectDirectory,
|
projectDirectory: projectDirectory,
|
||||||
url: url
|
url: url
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ extension CurrentVersionContainer where Version == String {
|
|||||||
|
|
||||||
static func load(
|
static func load(
|
||||||
branch: Configuration.Branch,
|
branch: Configuration.Branch,
|
||||||
gitDirectory: String?,
|
projectDirectory: String?,
|
||||||
url: URL
|
url: URL
|
||||||
) async throws -> Self {
|
) async throws -> Self {
|
||||||
@Dependency(\.fileClient) var fileClient
|
@Dependency(\.fileClient) var fileClient
|
||||||
@@ -70,12 +70,12 @@ extension CurrentVersionContainer where Version == String {
|
|||||||
|
|
||||||
let loaded = try await fileClient.branch(
|
let loaded = try await fileClient.branch(
|
||||||
file: url,
|
file: url,
|
||||||
gitDirectory: gitDirectory,
|
projectDirectory: projectDirectory,
|
||||||
requireExistingFile: false
|
requireExistingFile: false
|
||||||
)
|
)
|
||||||
|
|
||||||
let next = try await gitClient.version(.init(
|
let next = try await gitClient.version(.init(
|
||||||
gitDirectory: gitDirectory,
|
gitDirectory: projectDirectory,
|
||||||
style: .branch(commitSha: branch.includeCommitSha)
|
style: .branch(commitSha: branch.includeCommitSha)
|
||||||
))
|
))
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ extension CurrentVersionContainer where Version == String {
|
|||||||
extension CurrentVersionContainer where Version == SemVar {
|
extension CurrentVersionContainer where Version == SemVar {
|
||||||
|
|
||||||
// TODO: Update to use precedence and not fetch `nextVersion` if we loaded a file version.
|
// TODO: Update to use precedence and not fetch `nextVersion` if we loaded a file version.
|
||||||
static func load(semvar: Configuration.SemVar, gitDirectory: String?, url: URL) async throws -> Self {
|
static func load(semvar: Configuration.SemVar, projectDirectory: String?, url: URL) async throws -> Self {
|
||||||
@Dependency(\.fileClient) var fileClient
|
@Dependency(\.fileClient) var fileClient
|
||||||
@Dependency(\.logger) var logger
|
@Dependency(\.logger) var logger
|
||||||
|
|
||||||
@@ -104,10 +104,10 @@ extension CurrentVersionContainer where Version == SemVar {
|
|||||||
|
|
||||||
async let (loaded, usesOptionalType) = try await loadCurrentVersion(
|
async let (loaded, usesOptionalType) = try await loadCurrentVersion(
|
||||||
semvar: semvar,
|
semvar: semvar,
|
||||||
gitDirectory: gitDirectory,
|
projectDirectory: projectDirectory,
|
||||||
url: url
|
url: url
|
||||||
)
|
)
|
||||||
async let next = try await loadNextVersion(semvar: semvar, projectDirectory: gitDirectory)
|
async let next = try await loadNextVersion(semvar: semvar, projectDirectory: projectDirectory)
|
||||||
|
|
||||||
return try await .init(
|
return try await .init(
|
||||||
targetUrl: url,
|
targetUrl: url,
|
||||||
@@ -120,7 +120,7 @@ extension CurrentVersionContainer where Version == SemVar {
|
|||||||
|
|
||||||
static func loadCurrentVersion(
|
static func loadCurrentVersion(
|
||||||
semvar: Configuration.SemVar,
|
semvar: Configuration.SemVar,
|
||||||
gitDirectory: String?,
|
projectDirectory: String?,
|
||||||
url: URL
|
url: URL
|
||||||
) async throws -> (SemVar?, Bool) {
|
) async throws -> (SemVar?, Bool) {
|
||||||
@Dependency(\.fileClient) var fileClient
|
@Dependency(\.fileClient) var fileClient
|
||||||
@@ -130,7 +130,7 @@ extension CurrentVersionContainer where Version == SemVar {
|
|||||||
|
|
||||||
let loadedOptional = try await fileClient.semvar(
|
let loadedOptional = try await fileClient.semvar(
|
||||||
file: url,
|
file: url,
|
||||||
gitDirectory: gitDirectory,
|
projectDirectory: projectDirectory,
|
||||||
requireExistingFile: semvar.requireExistingFile ?? false
|
requireExistingFile: semvar.requireExistingFile ?? false
|
||||||
)
|
)
|
||||||
guard let loadedStrong = loadedOptional else {
|
guard let loadedStrong = loadedOptional else {
|
||||||
@@ -169,14 +169,4 @@ extension CurrentVersionContainer where Version == SemVar {
|
|||||||
return version?.versionString(withPreReleaseTag: withPreRelease)
|
return version?.versionString(withPreReleaseTag: withPreRelease)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Move to where `bump` is declared and make fileprivate.
|
|
||||||
func withUpdateNextVersion(_ next: SemVar) -> Self {
|
|
||||||
.init(
|
|
||||||
targetUrl: targetUrl,
|
|
||||||
usesOptionalType: usesOptionalType,
|
|
||||||
loadedVersion: loadedVersion,
|
|
||||||
precedence: .strategy, // make sure to use the next version, since it was specified, as this is called from `bump`.
|
|
||||||
strategyVersion: next
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import Dependencies
|
import Dependencies
|
||||||
import FileClient
|
import FileClient
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import LoggingExtensions
|
||||||
|
|
||||||
@_spi(Internal)
|
@_spi(Internal)
|
||||||
public extension Configuration {
|
public extension Configuration {
|
||||||
@@ -44,8 +45,12 @@ public extension Configuration.Branch {
|
|||||||
@_spi(Internal)
|
@_spi(Internal)
|
||||||
public extension Configuration.SemVar {
|
public extension Configuration.SemVar {
|
||||||
func merging(_ other: Self?) -> Self {
|
func merging(_ other: Self?) -> Self {
|
||||||
.init(
|
@Dependency(\.logger) var logger
|
||||||
|
logger.dump(other, level: .trace) { "Merging semvar:\n\($0)" }
|
||||||
|
|
||||||
|
return .init(
|
||||||
allowPreRelease: other?.allowPreRelease ?? allowPreRelease,
|
allowPreRelease: other?.allowPreRelease ?? allowPreRelease,
|
||||||
|
precedence: other?.precedence ?? precedence,
|
||||||
preRelease: preRelease == nil ? other?.preRelease : preRelease!.merging(other?.preRelease),
|
preRelease: preRelease == nil ? other?.preRelease : preRelease!.merging(other?.preRelease),
|
||||||
requireExistingFile: other?.requireExistingFile ?? requireExistingFile,
|
requireExistingFile: other?.requireExistingFile ?? requireExistingFile,
|
||||||
requireExistingSemVar: other?.requireExistingSemVar ?? requireExistingSemVar,
|
requireExistingSemVar: other?.requireExistingSemVar ?? requireExistingSemVar,
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ public extension Configuration {
|
|||||||
|
|
||||||
case semvar(
|
case semvar(
|
||||||
allowPreRelease: Bool? = nil,
|
allowPreRelease: Bool? = nil,
|
||||||
|
precedence: SemVar.Precedence? = nil,
|
||||||
preRelease: PreRelease? = nil,
|
preRelease: PreRelease? = nil,
|
||||||
requireExistingFile: Bool? = nil,
|
requireExistingFile: Bool? = nil,
|
||||||
requireExistingSemVar: Bool? = nil,
|
requireExistingSemVar: Bool? = nil,
|
||||||
@@ -159,10 +160,16 @@ public extension Configuration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public var semvar: SemVar? {
|
public var semvar: SemVar? {
|
||||||
guard case let .semvar(allowPreRelease, preRelease, requireExistingFile, requireExistingSemVar, strategy) = self
|
guard case let .semvar(
|
||||||
|
allowPreRelease,
|
||||||
|
precedence,
|
||||||
|
preRelease,
|
||||||
|
requireExistingFile, requireExistingSemVar, strategy
|
||||||
|
) = self
|
||||||
else { return nil }
|
else { return nil }
|
||||||
return .init(
|
return .init(
|
||||||
allowPreRelease: allowPreRelease,
|
allowPreRelease: allowPreRelease,
|
||||||
|
precedence: precedence,
|
||||||
preRelease: preRelease,
|
preRelease: preRelease,
|
||||||
requireExistingFile: requireExistingFile ?? false,
|
requireExistingFile: requireExistingFile ?? false,
|
||||||
requireExistingSemVar: requireExistingSemVar ?? false,
|
requireExistingSemVar: requireExistingSemVar ?? false,
|
||||||
@@ -177,6 +184,7 @@ public extension Configuration {
|
|||||||
public static func semvar(_ value: SemVar) -> Self {
|
public static func semvar(_ value: SemVar) -> Self {
|
||||||
.semvar(
|
.semvar(
|
||||||
allowPreRelease: value.allowPreRelease,
|
allowPreRelease: value.allowPreRelease,
|
||||||
|
precedence: value.precedence,
|
||||||
preRelease: value.preRelease,
|
preRelease: value.preRelease,
|
||||||
requireExistingFile: value.requireExistingFile,
|
requireExistingFile: value.requireExistingFile,
|
||||||
requireExistingSemVar: value.requireExistingSemVar,
|
requireExistingSemVar: value.requireExistingSemVar,
|
||||||
@@ -249,8 +257,15 @@ public extension Configuration {
|
|||||||
///
|
///
|
||||||
struct SemVar: Codable, Equatable, Sendable {
|
struct SemVar: Codable, Equatable, Sendable {
|
||||||
|
|
||||||
|
/// Allow semvar to include a pre-release suffix.
|
||||||
public let allowPreRelease: Bool?
|
public let allowPreRelease: Bool?
|
||||||
|
|
||||||
|
/// Set the precedence of version loaded from file versus
|
||||||
|
/// the version returned by the strategy.
|
||||||
|
///
|
||||||
|
/// These can not always agree / reflect the same version,
|
||||||
|
/// so the default is to give the file version precedence over
|
||||||
|
/// the strategy.
|
||||||
public let precedence: Precedence?
|
public let precedence: Precedence?
|
||||||
|
|
||||||
/// Optional pre-releas suffix strategy.
|
/// Optional pre-releas suffix strategy.
|
||||||
@@ -262,11 +277,12 @@ public extension Configuration {
|
|||||||
/// Fail if an existing semvar is not parsed from the file or version generation strategy.
|
/// Fail if an existing semvar is not parsed from the file or version generation strategy.
|
||||||
public let requireExistingSemVar: Bool?
|
public let requireExistingSemVar: Bool?
|
||||||
|
|
||||||
|
/// The strategy used to derive a version for the project.
|
||||||
public let strategy: Strategy?
|
public let strategy: Strategy?
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
allowPreRelease: Bool? = true,
|
allowPreRelease: Bool? = true,
|
||||||
precedence: Precedence? = .default,
|
precedence: Precedence? = nil,
|
||||||
preRelease: PreRelease? = nil,
|
preRelease: PreRelease? = nil,
|
||||||
requireExistingFile: Bool? = false,
|
requireExistingFile: Bool? = false,
|
||||||
requireExistingSemVar: Bool? = false,
|
requireExistingSemVar: Bool? = false,
|
||||||
@@ -280,15 +296,31 @@ public extension Configuration {
|
|||||||
self.strategy = strategy
|
self.strategy = strategy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents a strategy to derive a version for a project.
|
||||||
public enum Strategy: Codable, Equatable, Sendable {
|
public enum Strategy: Codable, Equatable, Sendable {
|
||||||
|
/// A custom external command that should return a string that
|
||||||
|
/// can be parsed as a semvar.
|
||||||
case command(arguments: [String])
|
case command(arguments: [String])
|
||||||
|
|
||||||
|
/// Use `git describe --tags` optionally as an exact match.
|
||||||
case gitTag(exactMatch: Bool? = false)
|
case gitTag(exactMatch: Bool? = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Precedence: String, Codable, Equatable, Sendable {
|
/// Represents the precedence for which version to use when a file
|
||||||
|
/// exists, as they don't always agree. For example, a file could be edited
|
||||||
|
/// manually or the tag doesn't represent what is parsed from calling the
|
||||||
|
/// strategy.
|
||||||
|
///
|
||||||
|
/// The default is to defer to the file (if it exists) as having precedence over
|
||||||
|
/// the strategy.
|
||||||
|
public enum Precedence: String, CaseIterable, Codable, Equatable, Sendable {
|
||||||
|
|
||||||
|
/// Give the file precedence over the strategy.
|
||||||
case file
|
case file
|
||||||
|
/// Give the strategy precedence over the file.
|
||||||
case strategy
|
case strategy
|
||||||
|
|
||||||
|
/// The default precedence.
|
||||||
public static var `default`: Self { .file }
|
public static var `default`: Self { .file }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ struct CliClientTests {
|
|||||||
$0.fileClient.read = { @Sendable _ in template }
|
$0.fileClient.read = { @Sendable _ in template }
|
||||||
} operation: {
|
} operation: {
|
||||||
@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(requireExistingFile: false)
|
versionStrategy: .semvar(requireExistingFile: false)
|
||||||
|
|||||||
Reference in New Issue
Block a user