feat: Updates configuration commands and parsing strategy.
All checks were successful
CI / Ubuntu (push) Successful in 2m59s
All checks were successful
CI / Ubuntu (push) Successful in 2m59s
This commit is contained in:
@@ -1,14 +1,10 @@
|
||||
{
|
||||
"target" : {
|
||||
"module" : { "name" : "cli-version" }
|
||||
},
|
||||
"strategy" : {
|
||||
"semvar" : {
|
||||
"preRelease" : {
|
||||
"strategy" : { "gitTag" : {} }
|
||||
}
|
||||
}
|
||||
},
|
||||
"target" : {
|
||||
"module" : {
|
||||
"name" : "bump-version"
|
||||
"strategy" : { "gitTag": { "exactMatch": false } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,11 +36,14 @@ extension Configuration.Branch {
|
||||
}
|
||||
|
||||
extension Configuration.SemVar {
|
||||
// TODO: Merge strategy ??
|
||||
func merging(_ other: Self?) -> Self {
|
||||
.init(
|
||||
allowPreRelease: other?.allowPreRelease ?? allowPreRelease,
|
||||
preRelease: preRelease?.merging(other?.preRelease),
|
||||
requireExistingFile: other?.requireExistingFile ?? requireExistingFile,
|
||||
requireExistingSemVar: other?.requireExistingSemVar ?? requireExistingSemVar
|
||||
requireExistingSemVar: other?.requireExistingSemVar ?? requireExistingSemVar,
|
||||
strategy: other?.strategy ?? strategy
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ public extension Configuration.SemVar {
|
||||
)
|
||||
}
|
||||
|
||||
if requireExistingFile {
|
||||
if requireExistingFile == true {
|
||||
logger.debug("Failed to parse existing file, and caller requires it.")
|
||||
throw CliClientError.fileDoesNotExist(path: file.cleanFilePath)
|
||||
}
|
||||
@@ -195,7 +195,7 @@ public extension Configuration.SemVar {
|
||||
)
|
||||
}
|
||||
|
||||
if requireExistingSemVar {
|
||||
if requireExistingSemVar == true {
|
||||
logger.trace("Caller requires existing semvar and it was not found in file or git-tag.")
|
||||
throw CliClientError.semVarNotFound
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public struct Configuration: Codable, Equatable, Sendable {
|
||||
public static func mock(module: String = "cli-version") -> Self {
|
||||
.init(
|
||||
target: .init(module: .init(module)),
|
||||
strategy: .semvar(.init())
|
||||
strategy: .semvar(.init(strategy: .gitTag(exactMatch: false)))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -99,28 +99,36 @@ public extension Configuration {
|
||||
///
|
||||
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
|
||||
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 requireExistingSemVar: Bool?
|
||||
|
||||
public let strategy: Strategy?
|
||||
|
||||
public init(
|
||||
allowPreRelease: Bool? = true,
|
||||
preRelease: PreRelease? = nil,
|
||||
requireExistingFile: Bool = true,
|
||||
requireExistingSemVar: Bool = true
|
||||
requireExistingFile: Bool? = true,
|
||||
requireExistingSemVar: Bool? = true,
|
||||
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)
|
||||
case gitTag(exactMatch: Bool? = false)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -172,7 +180,7 @@ public extension Configuration {
|
||||
/// - fileName: The file name located in the module directory.
|
||||
public init(
|
||||
_ name: String,
|
||||
fileName: String? = "Version.swift"
|
||||
fileName: String? = nil
|
||||
) {
|
||||
self.name = name
|
||||
self.fileName = fileName
|
||||
@@ -225,9 +233,11 @@ public extension Configuration {
|
||||
case branch(includeCommitSha: Bool = true)
|
||||
|
||||
case semvar(
|
||||
allowPreRelease: Bool? = nil,
|
||||
preRelease: PreRelease? = nil,
|
||||
requireExistingFile: Bool? = nil,
|
||||
requireExistingSemVar: Bool? = nil
|
||||
requireExistingSemVar: Bool? = nil,
|
||||
strategy: SemVar.Strategy? = nil
|
||||
)
|
||||
|
||||
public var branch: Branch? {
|
||||
@@ -238,12 +248,14 @@ public extension Configuration {
|
||||
}
|
||||
|
||||
public var semvar: SemVar? {
|
||||
guard case let .semvar(preRelease, requireExistingFile, requireExistingSemVar) = self
|
||||
guard case let .semvar(allowPreRelease, preRelease, requireExistingFile, requireExistingSemVar, strategy) = self
|
||||
else { return nil }
|
||||
return .init(
|
||||
allowPreRelease: allowPreRelease,
|
||||
preRelease: preRelease,
|
||||
requireExistingFile: requireExistingFile ?? false,
|
||||
requireExistingSemVar: requireExistingSemVar ?? false
|
||||
requireExistingSemVar: requireExistingSemVar ?? false,
|
||||
strategy: strategy
|
||||
)
|
||||
}
|
||||
|
||||
@@ -253,9 +265,11 @@ public extension Configuration {
|
||||
|
||||
public static func semvar(_ value: SemVar) -> Self {
|
||||
.semvar(
|
||||
allowPreRelease: value.allowPreRelease,
|
||||
preRelease: value.preRelease,
|
||||
requireExistingFile: value.requireExistingFile,
|
||||
requireExistingSemVar: value.requireExistingSemVar
|
||||
requireExistingSemVar: value.requireExistingSemVar,
|
||||
strategy: value.strategy
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ struct Application: AsyncParsableCommand {
|
||||
BuildCommand.self,
|
||||
BumpCommand.self,
|
||||
GenerateCommand.self,
|
||||
UtilsCommand.self
|
||||
ConfigCommand.self
|
||||
],
|
||||
defaultSubcommand: BumpCommand.self
|
||||
)
|
||||
|
||||
171
Sources/bump-version/Commands/ConfigCommand.swift
Normal file
171
Sources/bump-version/Commands/ConfigCommand.swift
Normal file
@@ -0,0 +1,171 @@
|
||||
import ArgumentParser
|
||||
import CliClient
|
||||
import ConfigurationClient
|
||||
import CustomDump
|
||||
import Dependencies
|
||||
import FileClient
|
||||
import Foundation
|
||||
|
||||
struct ConfigCommand: AsyncParsableCommand {
|
||||
static let configuration = CommandConfiguration(
|
||||
commandName: "config",
|
||||
abstract: "Configuration commands",
|
||||
subcommands: [
|
||||
DumpConfig.self,
|
||||
GenerateConfig.self
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
extension ConfigCommand {
|
||||
|
||||
struct DumpConfig: AsyncParsableCommand {
|
||||
static let commandName = "dump"
|
||||
|
||||
static let configuration = CommandConfiguration(
|
||||
commandName: Self.commandName,
|
||||
abstract: "Inspect the parsed configuration.",
|
||||
discussion: """
|
||||
This will load any configuration and merge the options passed in. Then print it to stdout.
|
||||
The default style is to print the output in `swift`, however you can use the `--print` flag to
|
||||
print the output in `json`.
|
||||
""",
|
||||
aliases: ["d"]
|
||||
)
|
||||
|
||||
@OptionGroup var globals: ConfigCommandOptions
|
||||
|
||||
func run() async throws {
|
||||
let configuration = try await globals
|
||||
.shared(command: Self.commandName)
|
||||
.runClient(\.parsedConfiguration)
|
||||
|
||||
try globals.printConfiguration(configuration)
|
||||
}
|
||||
}
|
||||
|
||||
struct GenerateConfig: AsyncParsableCommand {
|
||||
static let configuration: CommandConfiguration = .init(
|
||||
commandName: "generate",
|
||||
abstract: "Generate a configuration file.",
|
||||
aliases: ["g"]
|
||||
)
|
||||
|
||||
@Flag(
|
||||
help: "The style of the configuration."
|
||||
)
|
||||
var style: ConfigCommand.Style = .semvar
|
||||
|
||||
@OptionGroup var globals: ConfigCommandOptions
|
||||
|
||||
func run() async throws {
|
||||
try await withSetupDependencies {
|
||||
@Dependency(\.configurationClient) var configurationClient
|
||||
|
||||
let configuration = try style.parseConfiguration(
|
||||
configOptions: globals.configOptions,
|
||||
extraOptions: globals.extraOptions
|
||||
)
|
||||
|
||||
switch globals.printJson {
|
||||
case true:
|
||||
try globals.handlePrintJson(configuration)
|
||||
case false:
|
||||
let url = globals.configFileUrl
|
||||
try await configurationClient.write(configuration, url)
|
||||
print(url.cleanFilePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
extension ConfigCommand {
|
||||
enum Style: EnumerableFlag {
|
||||
case branch, semvar
|
||||
|
||||
func parseConfiguration(
|
||||
configOptions: ConfigurationOptions,
|
||||
extraOptions: [String]
|
||||
) throws -> Configuration {
|
||||
let strategy: Configuration.VersionStrategy
|
||||
|
||||
switch self {
|
||||
case .branch:
|
||||
strategy = .branch(includeCommitSha: configOptions.commitSha)
|
||||
case .semvar:
|
||||
strategy = try .semvar(configOptions.semvarOptions(extraOptions: extraOptions))
|
||||
}
|
||||
|
||||
return try Configuration(
|
||||
target: configOptions.target(),
|
||||
strategy: strategy
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@dynamicMemberLookup
|
||||
struct ConfigCommandOptions: ParsableArguments {
|
||||
|
||||
@Flag(
|
||||
name: .customLong("print"),
|
||||
help: "Print style to stdout."
|
||||
)
|
||||
var printJson: Bool = false
|
||||
|
||||
@OptionGroup var configOptions: ConfigurationOptions
|
||||
|
||||
@Argument(
|
||||
help: """
|
||||
Arguments / options used for custom pre-release, options / flags must proceed a '--' in
|
||||
the command. These are ignored if the `--custom-command` or `--custom-pre-release` flag is not set.
|
||||
"""
|
||||
)
|
||||
var extraOptions: [String] = []
|
||||
|
||||
subscript<T>(dynamicMember keyPath: KeyPath<ConfigurationOptions, T>) -> T {
|
||||
configOptions[keyPath: keyPath]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension ConfigCommand.ConfigCommandOptions {
|
||||
|
||||
func shared(command: String) throws -> CliClient.SharedOptions {
|
||||
try configOptions.shared(command: command, extraOptions: extraOptions)
|
||||
}
|
||||
|
||||
func handlePrintJson(_ configuration: Configuration) throws {
|
||||
@Dependency(\.coders) var coders
|
||||
@Dependency(\.logger) var logger
|
||||
|
||||
let data = try coders.jsonEncoder().encode(configuration)
|
||||
guard let string = String(bytes: data, encoding: .utf8) else {
|
||||
logger.error("Error encoding configuration to json.")
|
||||
throw ConfigurationEncodingError()
|
||||
}
|
||||
print(string)
|
||||
}
|
||||
|
||||
func printConfiguration(_ configuration: Configuration) throws {
|
||||
guard printJson else {
|
||||
customDump(configuration)
|
||||
return
|
||||
}
|
||||
try handlePrintJson(configuration)
|
||||
}
|
||||
}
|
||||
|
||||
private extension ConfigurationOptions {
|
||||
var configFileUrl: URL {
|
||||
switch configurationFile {
|
||||
case let .some(path):
|
||||
return URL(filePath: path)
|
||||
case .none:
|
||||
return URL(filePath: ".bump-version.json")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ConfigurationEncodingError: Error {}
|
||||
@@ -1,97 +0,0 @@
|
||||
import ArgumentParser
|
||||
import ConfigurationClient
|
||||
import CustomDump
|
||||
import Dependencies
|
||||
import FileClient
|
||||
import Foundation
|
||||
|
||||
struct UtilsCommand: AsyncParsableCommand {
|
||||
static let configuration = CommandConfiguration(
|
||||
commandName: "utils",
|
||||
abstract: "Utility commands",
|
||||
subcommands: [
|
||||
DumpConfig.self,
|
||||
GenerateConfig.self
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
extension UtilsCommand {
|
||||
struct DumpConfig: AsyncParsableCommand {
|
||||
static let commandName = "dump-config"
|
||||
|
||||
static let configuration = CommandConfiguration(
|
||||
commandName: Self.commandName,
|
||||
abstract: "Show the parsed configuration.",
|
||||
aliases: ["dc"]
|
||||
)
|
||||
|
||||
@OptionGroup var globals: GlobalOptions
|
||||
|
||||
func run() async throws {
|
||||
let configuration = try await globals.runClient(\.parsedConfiguration, command: Self.commandName)
|
||||
customDump(configuration)
|
||||
}
|
||||
}
|
||||
|
||||
struct GenerateConfig: AsyncParsableCommand {
|
||||
static let configuration: CommandConfiguration = .init(
|
||||
commandName: "generate-config",
|
||||
abstract: "Generate a configuration file.",
|
||||
aliases: ["gc"]
|
||||
)
|
||||
|
||||
@OptionGroup var configOptions: ConfigurationOptions
|
||||
|
||||
@Flag(
|
||||
help: "The style of the configuration."
|
||||
)
|
||||
var style: Style = .semvar
|
||||
|
||||
@Argument(
|
||||
help: """
|
||||
Arguments / options used for custom pre-release, options / flags must proceed a '--' in
|
||||
the command. These are ignored if the `--custom` flag is not set.
|
||||
"""
|
||||
)
|
||||
var extraOptions: [String] = []
|
||||
|
||||
func run() async throws {
|
||||
try await withSetupDependencies {
|
||||
@Dependency(\.configurationClient) var configurationClient
|
||||
|
||||
let strategy: Configuration.VersionStrategy
|
||||
|
||||
switch style {
|
||||
case .branch:
|
||||
strategy = .branch(includeCommitSha: configOptions.commitSha)
|
||||
case .semvar:
|
||||
strategy = try .semvar(configOptions.semvarOptions(extraOptions: extraOptions))
|
||||
}
|
||||
|
||||
let configuration = try Configuration(
|
||||
target: configOptions.target(),
|
||||
strategy: strategy
|
||||
)
|
||||
|
||||
let url: URL
|
||||
switch configOptions.configurationFile {
|
||||
case let .some(path):
|
||||
url = URL(filePath: path)
|
||||
case .none:
|
||||
url = URL(filePath: ".bump-version.json")
|
||||
}
|
||||
|
||||
try await configurationClient.write(configuration, url)
|
||||
|
||||
print(url.cleanFilePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension UtilsCommand.GenerateConfig {
|
||||
enum Style: EnumerableFlag {
|
||||
case branch, semvar
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ struct GlobalOptions: ParsableArguments {
|
||||
@Argument(
|
||||
help: """
|
||||
Arguments / options used for custom pre-release, options / flags must proceed a '--' in
|
||||
the command. These are ignored if the `--custom` flag is not set.
|
||||
the command. These are ignored if the `--custom` or `--custom-pre-release` flag is not set.
|
||||
"""
|
||||
)
|
||||
var extraOptions: [String] = []
|
||||
@@ -40,7 +40,7 @@ struct GlobalOptions: ParsableArguments {
|
||||
|
||||
struct ConfigurationOptions: ParsableArguments {
|
||||
@Option(
|
||||
name: .shortAndLong,
|
||||
name: [.customShort("f"), .long],
|
||||
help: "Specify the path to a configuration file.",
|
||||
completion: .file(extensions: ["json"])
|
||||
)
|
||||
@@ -63,22 +63,22 @@ struct ConfigurationOptions: ParsableArguments {
|
||||
|
||||
struct TargetOptions: ParsableArguments {
|
||||
@Option(
|
||||
name: .shortAndLong,
|
||||
name: [.customShort("p"), .long],
|
||||
help: "Path to the version file, not required if module is set."
|
||||
)
|
||||
var path: String?
|
||||
var targetFilePath: String?
|
||||
|
||||
@Option(
|
||||
name: .shortAndLong,
|
||||
name: [.customShort("m"), .long],
|
||||
help: "The target module name or directory path, not required if path is set."
|
||||
)
|
||||
var module: String?
|
||||
var targetModule: String?
|
||||
|
||||
@Option(
|
||||
name: [.customShort("n"), .long],
|
||||
help: "The file name inside the target module, required if module is set."
|
||||
help: "The file name inside the target module. (defaults to: \"Version.swift\")."
|
||||
)
|
||||
var fileName: String = "Version.swift"
|
||||
var targetFileName: String?
|
||||
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ struct PreReleaseOptions: ParsableArguments {
|
||||
var disablePreRelease: Bool = false
|
||||
|
||||
@Flag(
|
||||
name: [.customShort("s"), .customLong("pre-release-branch-style")],
|
||||
name: [.customShort("b"), .customLong("pre-release-branch-style")],
|
||||
help: """
|
||||
Use branch name and commit sha for pre-release suffix, ignored if branch is set.
|
||||
"""
|
||||
@@ -124,8 +124,22 @@ struct PreReleaseOptions: ParsableArguments {
|
||||
|
||||
}
|
||||
|
||||
// TODO: Add custom command strategy.
|
||||
struct SemVarOptions: ParsableArguments {
|
||||
|
||||
@Flag(
|
||||
name: .long,
|
||||
inversion: .prefixedEnableDisable,
|
||||
help: "Use git-tag strategy for semvar."
|
||||
)
|
||||
var gitTag: Bool = true
|
||||
|
||||
@Flag(
|
||||
name: .long,
|
||||
help: "Require exact match for git tag strategy."
|
||||
)
|
||||
var requireExactMatch: Bool = false
|
||||
|
||||
@Flag(
|
||||
name: .long,
|
||||
help: """
|
||||
@@ -136,9 +150,18 @@ struct SemVarOptions: ParsableArguments {
|
||||
|
||||
@Flag(
|
||||
name: .long,
|
||||
help: "Fail if a sem-var is not parsed from existing file or git tag, used if branch is not set."
|
||||
help: "Fail if a semvar is not parsed from existing file or git tag, used if branch is not set."
|
||||
)
|
||||
var requireExistingSemvar: Bool = false
|
||||
|
||||
@Flag(
|
||||
name: .shortAndLong,
|
||||
help: """
|
||||
Custom command strategy, uses extra-options to call an external command.
|
||||
The external command should return a semvar that is used.
|
||||
"""
|
||||
)
|
||||
var customCommand: Bool = false
|
||||
|
||||
@OptionGroup var preRelease: PreReleaseOptions
|
||||
}
|
||||
|
||||
@@ -18,34 +18,35 @@ func withSetupDependencies<T>(
|
||||
}
|
||||
}
|
||||
|
||||
extension GlobalOptions {
|
||||
|
||||
extension CliClient.SharedOptions {
|
||||
func runClient<T>(
|
||||
_ keyPath: KeyPath<CliClient, @Sendable (CliClient.SharedOptions) async throws -> T>,
|
||||
command: String
|
||||
_ keyPath: KeyPath<CliClient, @Sendable (Self) async throws -> T>
|
||||
) async throws -> T {
|
||||
try await withSetupDependencies {
|
||||
@Dependency(\.cliClient) var cliClient
|
||||
return try await cliClient[keyPath: keyPath](shared(command: command))
|
||||
return try await cliClient[keyPath: keyPath](self)
|
||||
}
|
||||
}
|
||||
|
||||
func runClient<A, T>(
|
||||
_ keyPath: KeyPath<CliClient, @Sendable (A, CliClient.SharedOptions) async throws -> T>,
|
||||
command: String,
|
||||
_ keyPath: KeyPath<CliClient, @Sendable (A, Self) async throws -> T>,
|
||||
args: A
|
||||
) async throws -> T {
|
||||
try await withSetupDependencies {
|
||||
@Dependency(\.cliClient) var cliClient
|
||||
return try await cliClient[keyPath: keyPath](args, shared(command: command))
|
||||
return try await cliClient[keyPath: keyPath](args, self)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension GlobalOptions {
|
||||
|
||||
func run(
|
||||
_ keyPath: KeyPath<CliClient, @Sendable (CliClient.SharedOptions) async throws -> String>,
|
||||
command: String
|
||||
) async throws {
|
||||
let output = try await runClient(keyPath, command: command)
|
||||
let output = try await shared(command: command).runClient(keyPath)
|
||||
print(output)
|
||||
}
|
||||
|
||||
@@ -54,40 +55,39 @@ extension GlobalOptions {
|
||||
command: String,
|
||||
args: T
|
||||
) async throws {
|
||||
let output = try await runClient(keyPath, command: command, args: args)
|
||||
let output = try await shared(command: command).runClient(keyPath, args: args)
|
||||
print(output)
|
||||
}
|
||||
|
||||
func shared(command: String) throws -> CliClient.SharedOptions {
|
||||
try .init(
|
||||
allowPreReleaseTag: !configOptions.semvarOptions.preRelease.disablePreRelease,
|
||||
try configOptions.shared(
|
||||
command: command,
|
||||
dryRun: dryRun,
|
||||
extraOptions: extraOptions,
|
||||
gitDirectory: gitDirectory,
|
||||
loggingOptions: .init(command: command, verbose: verbose),
|
||||
target: configOptions.target(),
|
||||
branch: .init(includeCommitSha: configOptions.commitSha),
|
||||
semvar: configOptions.semvarOptions(extraOptions: extraOptions),
|
||||
configurationFile: configOptions.configurationFile
|
||||
verbose: verbose
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private extension TargetOptions {
|
||||
func configTarget() throws -> Configuration.Target? {
|
||||
guard let path else {
|
||||
guard let module else {
|
||||
guard let targetFilePath else {
|
||||
guard let targetModule else {
|
||||
return nil
|
||||
}
|
||||
return .init(module: .init(module, fileName: fileName))
|
||||
return .init(module: .init(targetModule, fileName: targetFileName))
|
||||
}
|
||||
return .init(path: path)
|
||||
return .init(path: targetFilePath)
|
||||
}
|
||||
}
|
||||
|
||||
extension PreReleaseOptions {
|
||||
|
||||
func configPreReleaseStrategy(includeCommitSha: Bool, extraOptions: [String]) throws -> Configuration.PreRelease? {
|
||||
func configPreReleaseStrategy(
|
||||
includeCommitSha: Bool,
|
||||
extraOptions: [String]
|
||||
) throws -> Configuration.PreRelease? {
|
||||
if useBranchAsPreRelease {
|
||||
return .init(prefix: preReleasePrefix, strategy: .branch(includeCommitSha: includeCommitSha))
|
||||
} else if useTagAsPreRelease {
|
||||
@@ -106,11 +106,48 @@ extension PreReleaseOptions {
|
||||
|
||||
extension SemVarOptions {
|
||||
|
||||
func configSemVarOptions(includeCommitSha: Bool, extraOptions: [String]) throws -> Configuration.SemVar {
|
||||
try .init(
|
||||
preRelease: preRelease.configPreReleaseStrategy(includeCommitSha: includeCommitSha, extraOptions: extraOptions),
|
||||
requireExistingFile: requireExistingFile,
|
||||
requireExistingSemVar: requireExistingSemvar
|
||||
func parseStrategy(extraOptions: [String]) throws -> Configuration.SemVar.Strategy? {
|
||||
@Dependency(\.logger) var logger
|
||||
|
||||
guard customCommand else {
|
||||
guard gitTag else { return nil }
|
||||
return .gitTag(exactMatch: requireExactMatch)
|
||||
}
|
||||
guard extraOptions.count > 0 else {
|
||||
logger.error("""
|
||||
Extra options are empty, this does not make sense when using a custom command
|
||||
strategy.
|
||||
""")
|
||||
throw ExtraOptionsEmpty()
|
||||
}
|
||||
return .command(arguments: extraOptions)
|
||||
}
|
||||
|
||||
func configSemVarOptions(
|
||||
includeCommitSha: Bool,
|
||||
extraOptions: [String]
|
||||
) throws -> Configuration.SemVar {
|
||||
@Dependency(\.logger) var logger
|
||||
|
||||
// TODO: Update when / if there's an update config command.
|
||||
if customCommand && preRelease.customPreRelease {
|
||||
logger.warning("""
|
||||
Custom pre-release can not be used at same time as custom command.
|
||||
Ignoring pre-release...
|
||||
""")
|
||||
}
|
||||
|
||||
return try .init(
|
||||
allowPreRelease: !preRelease.disablePreRelease,
|
||||
preRelease: customCommand ? nil : preRelease.configPreReleaseStrategy(
|
||||
includeCommitSha: includeCommitSha,
|
||||
extraOptions: extraOptions
|
||||
),
|
||||
// Use nil here if false, which makes them not get used in json / file output, which makes
|
||||
// user config smaller.
|
||||
requireExistingFile: requireExistingFile ? true : nil,
|
||||
requireExistingSemVar: requireExistingSemvar ? true : nil,
|
||||
strategy: parseStrategy(extraOptions: extraOptions)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -121,8 +158,32 @@ extension ConfigurationOptions {
|
||||
try targetOptions.configTarget()
|
||||
}
|
||||
|
||||
func semvarOptions(extraOptions: [String]) throws -> Configuration.SemVar {
|
||||
try semvarOptions.configSemVarOptions(includeCommitSha: commitSha, extraOptions: extraOptions)
|
||||
func semvarOptions(
|
||||
extraOptions: [String]
|
||||
) throws -> Configuration.SemVar {
|
||||
try semvarOptions.configSemVarOptions(
|
||||
includeCommitSha: commitSha,
|
||||
extraOptions: extraOptions
|
||||
)
|
||||
}
|
||||
|
||||
func shared(
|
||||
command: String,
|
||||
dryRun: Bool = true,
|
||||
extraOptions: [String] = [],
|
||||
gitDirectory: String? = nil,
|
||||
verbose: Int = 0
|
||||
) throws -> CliClient.SharedOptions {
|
||||
try .init(
|
||||
allowPreReleaseTag: !semvarOptions.preRelease.disablePreRelease,
|
||||
dryRun: dryRun,
|
||||
gitDirectory: gitDirectory,
|
||||
loggingOptions: .init(command: command, verbose: verbose),
|
||||
target: target(),
|
||||
branch: .init(includeCommitSha: commitSha),
|
||||
semvar: semvarOptions(extraOptions: extraOptions),
|
||||
configurationFile: configurationFile
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ struct CliClientTests {
|
||||
if type != .preRelease {
|
||||
#expect(string != nil)
|
||||
}
|
||||
|
||||
let typeString = optional ? "String?" : "String"
|
||||
|
||||
switch type {
|
||||
|
||||
Reference in New Issue
Block a user