feat: Updating command options.
This commit is contained in:
@@ -6,7 +6,6 @@
|
|||||||
},
|
},
|
||||||
"target" : {
|
"target" : {
|
||||||
"module" : {
|
"module" : {
|
||||||
"fileName" : "Version.swift",
|
|
||||||
"name" : "cli-version"
|
"name" : "cli-version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ let package = Package(
|
|||||||
],
|
],
|
||||||
products: [
|
products: [
|
||||||
.library(name: "CliClient", targets: ["CliClient"]),
|
.library(name: "CliClient", targets: ["CliClient"]),
|
||||||
|
.library(name: "ConfigurationClient", targets: ["ConfigurationClient"]),
|
||||||
|
.library(name: "FileClient", targets: ["FileClient"]),
|
||||||
|
.library(name: "GitClient", targets: ["GitClient"]),
|
||||||
.plugin(name: "BuildWithVersionPlugin", targets: ["BuildWithVersionPlugin"]),
|
.plugin(name: "BuildWithVersionPlugin", targets: ["BuildWithVersionPlugin"]),
|
||||||
.plugin(name: "GenerateVersionPlugin", targets: ["GenerateVersionPlugin"]),
|
.plugin(name: "GenerateVersionPlugin", targets: ["GenerateVersionPlugin"]),
|
||||||
.plugin(name: "UpdateVersionPlugin", targets: ["UpdateVersionPlugin"])
|
.plugin(name: "UpdateVersionPlugin", targets: ["UpdateVersionPlugin"])
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ import Foundation
|
|||||||
import GitClient
|
import GitClient
|
||||||
import ShellClient
|
import ShellClient
|
||||||
|
|
||||||
// TODO: Integrate ConfigurationClient
|
|
||||||
|
|
||||||
public extension DependencyValues {
|
public extension DependencyValues {
|
||||||
|
|
||||||
var cliClient: CliClient {
|
var cliClient: CliClient {
|
||||||
@@ -35,26 +33,55 @@ public struct CliClient: Sendable {
|
|||||||
|
|
||||||
public struct SharedOptions: Equatable, Sendable {
|
public struct SharedOptions: Equatable, Sendable {
|
||||||
|
|
||||||
|
let allowPreReleaseTag: Bool
|
||||||
let dryRun: Bool
|
let dryRun: Bool
|
||||||
let gitDirectory: String?
|
let gitDirectory: String?
|
||||||
let logLevel: Logger.Level
|
let logLevel: Logger.Level
|
||||||
let configuration: Configuration
|
let target: Configuration.Target?
|
||||||
|
let branch: Configuration.Branch?
|
||||||
|
let semvar: Configuration.SemVar?
|
||||||
|
let configurationFile: String?
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
|
allowPreReleaseTag: Bool = true,
|
||||||
dryRun: Bool = false,
|
dryRun: Bool = false,
|
||||||
gitDirectory: String? = nil,
|
gitDirectory: String? = nil,
|
||||||
logLevel: Logger.Level = .debug,
|
logLevel: Logger.Level = .debug,
|
||||||
configuration: Configuration
|
target: Configuration.Target? = nil,
|
||||||
|
branch: Configuration.Branch? = nil,
|
||||||
|
semvar: Configuration.SemVar? = nil,
|
||||||
|
configurationFile: String? = nil
|
||||||
) {
|
) {
|
||||||
|
self.allowPreReleaseTag = allowPreReleaseTag
|
||||||
self.dryRun = dryRun
|
self.dryRun = dryRun
|
||||||
self.gitDirectory = gitDirectory
|
self.gitDirectory = gitDirectory
|
||||||
self.logLevel = logLevel
|
self.logLevel = logLevel
|
||||||
self.configuration = configuration
|
self.target = target
|
||||||
|
self.branch = branch
|
||||||
|
self.semvar = semvar
|
||||||
|
self.configurationFile = configurationFile
|
||||||
}
|
}
|
||||||
|
|
||||||
var allowPreReleaseTag: Bool {
|
public init(
|
||||||
guard let semvar = configuration.strategy?.semvar else { return false }
|
allowPreReleaseTag: Bool = true,
|
||||||
return semvar.preRelease != nil
|
dryRun: Bool = false,
|
||||||
|
gitDirectory: String? = nil,
|
||||||
|
verbose: Int,
|
||||||
|
target: Configuration.Target? = nil,
|
||||||
|
branch: Configuration.Branch? = nil,
|
||||||
|
semvar: Configuration.SemVar? = nil,
|
||||||
|
configurationFile: String? = nil
|
||||||
|
) {
|
||||||
|
self.init(
|
||||||
|
allowPreReleaseTag: allowPreReleaseTag,
|
||||||
|
dryRun: dryRun,
|
||||||
|
gitDirectory: gitDirectory,
|
||||||
|
logLevel: .init(verbose: verbose),
|
||||||
|
target: target,
|
||||||
|
branch: branch,
|
||||||
|
semvar: semvar,
|
||||||
|
configurationFile: configurationFile
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
70
Sources/CliClient/Internal/Configuration+merging.swift
Normal file
70
Sources/CliClient/Internal/Configuration+merging.swift
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
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 .semvar(semvar.merging(other?.semvar))
|
||||||
|
}
|
||||||
|
return .branch(branch.merging(other?.branch))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Configuration {
|
||||||
|
func merging(_ other: Self?) -> Self {
|
||||||
|
var output = self
|
||||||
|
output = output.mergingTarget(other?.target)
|
||||||
|
output = output.mergingStrategy(other?.strategy)
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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)
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import ConfigurationClient
|
||||||
import Dependencies
|
import Dependencies
|
||||||
import FileClient
|
import FileClient
|
||||||
import Foundation
|
import Foundation
|
||||||
@@ -13,19 +14,37 @@ public extension CliClient.SharedOptions {
|
|||||||
try await withDependencies {
|
try await withDependencies {
|
||||||
$0.logger.logLevel = logLevel
|
$0.logger.logLevel = logLevel
|
||||||
} operation: {
|
} operation: {
|
||||||
@Dependency(\.logger) var logger
|
// Load the default configuration, if it exists.
|
||||||
|
try await withConfiguration(path: configurationFile) { configuration in
|
||||||
|
@Dependency(\.logger) var logger
|
||||||
|
|
||||||
let targetUrl = try configuration.targetUrl(gitDirectory: gitDirectory)
|
// Merge any configuration set from caller into default configuration.
|
||||||
logger.debug("Target: \(targetUrl.cleanFilePath)")
|
var configuration = configuration
|
||||||
|
configuration = configuration.mergingTarget(target)
|
||||||
|
|
||||||
try await operation(
|
if configuration.strategy?.branch != nil, let branch {
|
||||||
configuration.currentVersion(
|
configuration = configuration.mergingStrategy(.branch(branch))
|
||||||
targetUrl: targetUrl,
|
} else if let semvar {
|
||||||
gitDirectory: gitDirectory
|
configuration = configuration.mergingStrategy(.semvar(semvar))
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("Configuration: \(configuration)")
|
||||||
|
|
||||||
|
// This will fail if the target url is not set properly.
|
||||||
|
let targetUrl = try configuration.targetUrl(gitDirectory: gitDirectory)
|
||||||
|
logger.debug("Target: \(targetUrl.cleanFilePath)")
|
||||||
|
|
||||||
|
// Perform the operation, which generates the new version and writes it.
|
||||||
|
try await operation(
|
||||||
|
configuration.currentVersion(
|
||||||
|
targetUrl: targetUrl,
|
||||||
|
gitDirectory: gitDirectory
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
return targetUrl.cleanFilePath
|
// Return the file path we wrote the version to.
|
||||||
|
return targetUrl.cleanFilePath
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
// import ConfigurationClient
|
|
||||||
// import Dependencies
|
|
||||||
// import FileClient
|
|
||||||
// import struct Foundation.URL
|
|
||||||
// import GitClient
|
|
||||||
//
|
|
||||||
// @_spi(Internal)
|
|
||||||
// public extension CliClient.PreReleaseStrategy {
|
|
||||||
//
|
|
||||||
// func preReleaseString(gitDirectory: String?) async throws -> String {
|
|
||||||
// @Dependency(\.gitClient) var gitClient
|
|
||||||
// switch self {
|
|
||||||
// case let .custom(string, child):
|
|
||||||
// guard let child else { return string }
|
|
||||||
// return try await "\(string)-\(child.preReleaseString(gitDirectory: gitDirectory))"
|
|
||||||
// case .tag:
|
|
||||||
// return try await gitClient.version(.init(
|
|
||||||
// gitDirectory: gitDirectory,
|
|
||||||
// style: .tag(exactMatch: false)
|
|
||||||
// )).description
|
|
||||||
// case .branchAndCommit:
|
|
||||||
// return try await gitClient.version(.init(
|
|
||||||
// gitDirectory: gitDirectory,
|
|
||||||
// style: .branch(commitSha: true)
|
|
||||||
// )).description
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @_spi(Internal)
|
|
||||||
// public extension CliClient.VersionStrategy.SemVarOptions {
|
|
||||||
//
|
|
||||||
// private func applyingPreRelease(_ semVar: SemVar, _ gitDirectory: String?) async throws -> SemVar {
|
|
||||||
// guard let preReleaseStrategy else { return semVar }
|
|
||||||
// let preRelease = try await preReleaseStrategy.preReleaseString(gitDirectory: gitDirectory)
|
|
||||||
// return semVar.applyingPreRelease(preRelease)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// func currentVersion(file: URL, gitDirectory: String? = nil) async throws -> CurrentVersionContainer.Version {
|
|
||||||
// @Dependency(\.fileClient) var fileClient
|
|
||||||
// @Dependency(\.gitClient) var gitClient
|
|
||||||
//
|
|
||||||
// let fileOutput = try? await fileClient.semVar(file: file, gitDirectory: gitDirectory)
|
|
||||||
// var semVar = fileOutput?.semVar
|
|
||||||
// let usesOptionalType = fileOutput?.usesOptionalType
|
|
||||||
//
|
|
||||||
// if requireExistingFile {
|
|
||||||
// guard let semVar else {
|
|
||||||
// throw CliClientError.fileDoesNotExist(path: file.cleanFilePath)
|
|
||||||
// }
|
|
||||||
// return try await .semVar(
|
|
||||||
// applyingPreRelease(semVar, gitDirectory),
|
|
||||||
// usesOptionalType: usesOptionalType ?? false
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 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 requireExistingSemVar {
|
|
||||||
// guard let semVar else {
|
|
||||||
// fatalError()
|
|
||||||
// }
|
|
||||||
// return try await .semVar(
|
|
||||||
// applyingPreRelease(semVar, gitDirectory),
|
|
||||||
// usesOptionalType: usesOptionalType ?? false
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return try await .semVar(
|
|
||||||
// applyingPreRelease(.init(), gitDirectory),
|
|
||||||
// usesOptionalType: usesOptionalType ?? false
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @_spi(Internal)
|
|
||||||
// public extension CliClient.VersionStrategy {
|
|
||||||
//
|
|
||||||
// func currentVersion(file: URL, gitDirectory: String?) async throws -> CurrentVersionContainer {
|
|
||||||
// @Dependency(\.gitClient) var gitClient
|
|
||||||
//
|
|
||||||
// switch self {
|
|
||||||
// case .branchAndCommit:
|
|
||||||
// return try await .init(
|
|
||||||
// targetUrl: file,
|
|
||||||
// version: .string(
|
|
||||||
// gitClient.version(.init(
|
|
||||||
// gitDirectory: gitDirectory,
|
|
||||||
// style: .branch(commitSha: true)
|
|
||||||
// )).description
|
|
||||||
// )
|
|
||||||
// )
|
|
||||||
// case let .semVar(options):
|
|
||||||
// return try await .init(
|
|
||||||
// targetUrl: file,
|
|
||||||
// version: options.currentVersion(file: file, gitDirectory: gitDirectory)
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
@@ -7,38 +7,10 @@ extension CliVersionCommand {
|
|||||||
struct Build: AsyncParsableCommand {
|
struct Build: AsyncParsableCommand {
|
||||||
static let configuration: CommandConfiguration = .init(
|
static let configuration: CommandConfiguration = .init(
|
||||||
abstract: "Used for the build with version plugin.",
|
abstract: "Used for the build with version plugin.",
|
||||||
discussion: "This should generally not be interacted with directly, outside of the build plugin.",
|
discussion: "This should generally not be interacted with directly, outside of the build plugin."
|
||||||
subcommands: [BranchStyle.self, SemVarStyle.self],
|
|
||||||
defaultSubcommand: SemVarStyle.self
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension CliVersionCommand.Build {
|
|
||||||
struct BranchStyle: AsyncParsableCommand {
|
|
||||||
|
|
||||||
static let configuration: CommandConfiguration = .init(
|
|
||||||
commandName: "branch",
|
|
||||||
abstract: "Build using branch and commit sha as the version.",
|
|
||||||
discussion: "This should generally not be interacted with directly, outside of the plugin usage context."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@OptionGroup var globals: GlobalBranchOptions
|
@OptionGroup var globals: GlobalOptions
|
||||||
|
|
||||||
func run() async throws {
|
|
||||||
try await globals.shared().run(\.build)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SemVarStyle: AsyncParsableCommand {
|
|
||||||
|
|
||||||
static let configuration: CommandConfiguration = .init(
|
|
||||||
commandName: "semvar",
|
|
||||||
abstract: "Generates a version file with SemVar style.",
|
|
||||||
discussion: "This should generally not be interacted with directly, outside of the plugin usage context."
|
|
||||||
)
|
|
||||||
|
|
||||||
@OptionGroup var globals: GlobalSemVarOptions
|
|
||||||
|
|
||||||
func run() async throws {
|
func run() async throws {
|
||||||
try await globals.shared().run(\.build)
|
try await globals.shared().run(\.build)
|
||||||
|
|||||||
@@ -7,49 +7,15 @@ extension CliVersionCommand {
|
|||||||
|
|
||||||
static let configuration = CommandConfiguration(
|
static let configuration = CommandConfiguration(
|
||||||
commandName: "bump",
|
commandName: "bump",
|
||||||
abstract: "Bump version of a command-line tool.",
|
abstract: "Bump version of a command-line tool."
|
||||||
subcommands: [
|
|
||||||
SemVarStyle.self,
|
|
||||||
BranchStyle.self
|
|
||||||
],
|
|
||||||
defaultSubcommand: SemVarStyle.self
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension CliVersionCommand.Bump {
|
|
||||||
|
|
||||||
struct BranchStyle: AsyncParsableCommand {
|
|
||||||
|
|
||||||
static let configuration = CommandConfiguration(
|
|
||||||
commandName: "branch",
|
|
||||||
abstract: "Bump using the current branch and commit sha."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@OptionGroup var globals: GlobalBranchOptions
|
@OptionGroup var globals: GlobalOptions
|
||||||
|
|
||||||
func run() async throws {
|
func run() async throws {
|
||||||
try await globals.shared().run(\.bump, args: nil)
|
try await globals.shared().run(\.bump, args: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SemVarStyle: AsyncParsableCommand {
|
|
||||||
|
|
||||||
static let configuration = CommandConfiguration(
|
|
||||||
commandName: "semvar",
|
|
||||||
abstract: "Bump using semvar style options."
|
|
||||||
)
|
|
||||||
|
|
||||||
@OptionGroup var globals: GlobalSemVarOptions
|
|
||||||
|
|
||||||
@Flag
|
|
||||||
var bumpOption: CliClient.BumpOption = .patch
|
|
||||||
|
|
||||||
func run() async throws {
|
|
||||||
try await globals.shared().run(\.bump, args: bumpOption)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension CliClient.BumpOption: EnumerableFlag {}
|
extension CliClient.BumpOption: EnumerableFlag {}
|
||||||
|
|||||||
@@ -1,61 +1,61 @@
|
|||||||
import ConfigurationClient
|
// import ConfigurationClient
|
||||||
import Dependencies
|
// import Dependencies
|
||||||
import FileClient
|
// import FileClient
|
||||||
import Foundation
|
// import Foundation
|
||||||
|
//
|
||||||
extension Configuration {
|
// extension Configuration {
|
||||||
|
//
|
||||||
func mergingTarget(_ otherTarget: Configuration.Target?) -> Self {
|
// func mergingTarget(_ otherTarget: Configuration.Target?) -> Self {
|
||||||
.init(
|
// .init(
|
||||||
target: otherTarget ?? target,
|
// target: otherTarget ?? target,
|
||||||
strategy: strategy
|
// strategy: strategy
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
func mergingStrategy(_ otherStrategy: Configuration.VersionStrategy?) -> Self {
|
// func mergingStrategy(_ otherStrategy: Configuration.VersionStrategy?) -> Self {
|
||||||
.init(
|
// .init(
|
||||||
target: target,
|
// target: target,
|
||||||
strategy: strategy?.merging(otherStrategy)
|
// strategy: strategy?.merging(otherStrategy)
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
extension Configuration.Branch {
|
// extension Configuration.Branch {
|
||||||
func merging(_ other: Self?) -> Self {
|
// func merging(_ other: Self?) -> Self {
|
||||||
return .init(includeCommitSha: other?.includeCommitSha ?? includeCommitSha)
|
// return .init(includeCommitSha: other?.includeCommitSha ?? includeCommitSha)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
extension Configuration.SemVar {
|
// extension Configuration.SemVar {
|
||||||
func merging(_ other: Self?) -> Self {
|
// func merging(_ other: Self?) -> Self {
|
||||||
.init(
|
// .init(
|
||||||
preRelease: other?.preRelease ?? preRelease,
|
// preRelease: other?.preRelease ?? preRelease,
|
||||||
requireExistingFile: other?.requireExistingFile ?? requireExistingFile,
|
// requireExistingFile: other?.requireExistingFile ?? requireExistingFile,
|
||||||
requireExistingSemVar: other?.requireExistingSemVar ?? requireExistingSemVar
|
// requireExistingSemVar: other?.requireExistingSemVar ?? requireExistingSemVar
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
extension Configuration.VersionStrategy {
|
// extension Configuration.VersionStrategy {
|
||||||
func merging(_ other: Self?) -> Self {
|
// func merging(_ other: Self?) -> Self {
|
||||||
guard let branch else {
|
// guard let branch else {
|
||||||
guard let semvar else { return self }
|
// guard let semvar else { return self }
|
||||||
return .semvar(semvar.merging(other?.semvar))
|
// return .semvar(semvar.merging(other?.semvar))
|
||||||
}
|
// }
|
||||||
return .branch(branch.merging(other?.branch))
|
// return .branch(branch.merging(other?.branch))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@discardableResult
|
// @discardableResult
|
||||||
func withConfiguration<T>(
|
// func withConfiguration<T>(
|
||||||
path: String?,
|
// path: String?,
|
||||||
_ operation: (Configuration) async throws -> T
|
// _ operation: (Configuration) async throws -> T
|
||||||
) async throws -> T {
|
// ) async throws -> T {
|
||||||
@Dependency(\.configurationClient) var configurationClient
|
// @Dependency(\.configurationClient) var configurationClient
|
||||||
|
//
|
||||||
let configuration = try await configurationClient.findAndLoad(
|
// let configuration = try await configurationClient.findAndLoad(
|
||||||
path != nil ? URL(filePath: path!) : nil
|
// path != nil ? URL(filePath: path!) : nil
|
||||||
)
|
// )
|
||||||
|
//
|
||||||
return try await operation(configuration)
|
// return try await operation(configuration)
|
||||||
}
|
// }
|
||||||
|
|||||||
@@ -8,45 +8,13 @@ extension CliVersionCommand {
|
|||||||
struct Generate: AsyncParsableCommand {
|
struct Generate: AsyncParsableCommand {
|
||||||
static let configuration: CommandConfiguration = .init(
|
static let configuration: CommandConfiguration = .init(
|
||||||
abstract: "Generates a version file in a command line tool that can be set via the git tag or git sha.",
|
abstract: "Generates a version file in a command line tool that can be set via the git tag or git sha.",
|
||||||
discussion: "This command can be interacted with directly, outside of the plugin usage context.",
|
|
||||||
subcommands: [BranchStyle.self, SemVarStyle.self],
|
|
||||||
defaultSubcommand: SemVarStyle.self
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension CliVersionCommand.Generate {
|
|
||||||
struct BranchStyle: AsyncParsableCommand {
|
|
||||||
|
|
||||||
static let configuration: CommandConfiguration = .init(
|
|
||||||
commandName: "branch",
|
|
||||||
abstract: "Generates a version file with branch and commit sha as the version.",
|
|
||||||
discussion: "This command can be interacted with directly, outside of the plugin usage context."
|
discussion: "This command can be interacted with directly, outside of the plugin usage context."
|
||||||
)
|
)
|
||||||
|
|
||||||
@OptionGroup var globals: GlobalBranchOptions
|
@OptionGroup var globals: GlobalOptions
|
||||||
|
|
||||||
func run() async throws {
|
|
||||||
try await globals.shared().run(\.generate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SemVarStyle: AsyncParsableCommand {
|
|
||||||
|
|
||||||
static let configuration: CommandConfiguration = .init(
|
|
||||||
commandName: "semvar",
|
|
||||||
abstract: "Generates a version file with SemVar style.",
|
|
||||||
discussion: "This command can be interacted with directly, outside of the plugin usage context."
|
|
||||||
)
|
|
||||||
|
|
||||||
@OptionGroup var globals: GlobalSemVarOptions
|
|
||||||
|
|
||||||
func run() async throws {
|
func run() async throws {
|
||||||
try await globals.shared().run(\.generate)
|
try await globals.shared().run(\.generate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum GenerationError: Error {
|
|
||||||
case fileExists(path: String)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Dependencies
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Rainbow
|
import Rainbow
|
||||||
|
|
||||||
struct GlobalOptions<Child: ParsableArguments>: ParsableArguments {
|
struct GlobalOptions: ParsableArguments {
|
||||||
|
|
||||||
@Option(
|
@Option(
|
||||||
name: .shortAndLong,
|
name: .shortAndLong,
|
||||||
@@ -14,7 +14,17 @@ struct GlobalOptions<Child: ParsableArguments>: ParsableArguments {
|
|||||||
var configurationFile: String?
|
var configurationFile: String?
|
||||||
|
|
||||||
@OptionGroup var targetOptions: TargetOptions
|
@OptionGroup var targetOptions: TargetOptions
|
||||||
@OptionGroup var child: Child
|
|
||||||
|
@OptionGroup var semvarOptions: SemVarOptions
|
||||||
|
|
||||||
|
@Flag(
|
||||||
|
name: .long,
|
||||||
|
inversion: .prefixedNo,
|
||||||
|
help: """
|
||||||
|
Include the short commit sha in version or pre-release branch style output.
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
var commitSha: Bool = true
|
||||||
|
|
||||||
@Option(
|
@Option(
|
||||||
name: .customLong("git-directory"),
|
name: .customLong("git-directory"),
|
||||||
@@ -36,8 +46,6 @@ struct GlobalOptions<Child: ParsableArguments>: ParsableArguments {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Empty: ParsableArguments {}
|
|
||||||
|
|
||||||
struct TargetOptions: ParsableArguments {
|
struct TargetOptions: ParsableArguments {
|
||||||
@Option(
|
@Option(
|
||||||
name: .shortAndLong,
|
name: .shortAndLong,
|
||||||
@@ -59,7 +67,16 @@ struct TargetOptions: ParsableArguments {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Need to be able to pass in arguments for custom command pre-release option.
|
||||||
|
|
||||||
struct PreReleaseOptions: ParsableArguments {
|
struct PreReleaseOptions: ParsableArguments {
|
||||||
|
|
||||||
|
@Flag(
|
||||||
|
name: .shortAndLong,
|
||||||
|
help: ""
|
||||||
|
)
|
||||||
|
var disablePreRelease: Bool = false
|
||||||
|
|
||||||
@Flag(
|
@Flag(
|
||||||
name: [.customShort("s"), .customLong("pre-release-branch-style")],
|
name: [.customShort("s"), .customLong("pre-release-branch-style")],
|
||||||
help: """
|
help: """
|
||||||
@@ -76,6 +93,14 @@ struct PreReleaseOptions: ParsableArguments {
|
|||||||
)
|
)
|
||||||
var useTagAsPreRelease: Bool = false
|
var useTagAsPreRelease: Bool = false
|
||||||
|
|
||||||
|
@Option(
|
||||||
|
name: .long,
|
||||||
|
help: """
|
||||||
|
Add / use a pre-release prefix string.
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
var preReleasePrefix: String?
|
||||||
|
|
||||||
@Option(
|
@Option(
|
||||||
name: .long,
|
name: .long,
|
||||||
help: """
|
help: """
|
||||||
@@ -84,6 +109,7 @@ struct PreReleaseOptions: ParsableArguments {
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
var custom: String?
|
var custom: String?
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SemVarOptions: ParsableArguments {
|
struct SemVarOptions: ParsableArguments {
|
||||||
@@ -105,25 +131,7 @@ struct SemVarOptions: ParsableArguments {
|
|||||||
@OptionGroup var preRelease: PreReleaseOptions
|
@OptionGroup var preRelease: PreReleaseOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
typealias GlobalSemVarOptions = GlobalOptions<SemVarOptions>
|
// TODO: Move these to global options.
|
||||||
typealias GlobalBranchOptions = GlobalOptions<Empty>
|
|
||||||
|
|
||||||
extension GlobalSemVarOptions {
|
|
||||||
func shared() async throws -> CliClient.SharedOptions {
|
|
||||||
try await withConfiguration(path: configurationFile) { configuration in
|
|
||||||
try shared(configuration.mergingStrategy(.semvar(child.configSemVarOptions())))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension GlobalBranchOptions {
|
|
||||||
func shared() async throws -> CliClient.SharedOptions {
|
|
||||||
try await withConfiguration(path: configurationFile) { configuration in
|
|
||||||
try shared(configuration.mergingStrategy(.branch()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension CliClient.SharedOptions {
|
extension CliClient.SharedOptions {
|
||||||
|
|
||||||
func run(_ keyPath: KeyPath<CliClient, @Sendable (Self) async throws -> String>) async throws {
|
func run(_ keyPath: KeyPath<CliClient, @Sendable (Self) async throws -> String>) async throws {
|
||||||
@@ -156,12 +164,16 @@ extension CliClient.SharedOptions {
|
|||||||
|
|
||||||
extension GlobalOptions {
|
extension GlobalOptions {
|
||||||
|
|
||||||
func shared(_ configuration: Configuration) throws -> CliClient.SharedOptions {
|
func shared() throws -> CliClient.SharedOptions {
|
||||||
.init(
|
try .init(
|
||||||
|
allowPreReleaseTag: !semvarOptions.preRelease.disablePreRelease,
|
||||||
dryRun: dryRun,
|
dryRun: dryRun,
|
||||||
gitDirectory: gitDirectory,
|
gitDirectory: gitDirectory,
|
||||||
logLevel: .init(verbose: verbose),
|
verbose: verbose,
|
||||||
configuration: configuration
|
target: targetOptions.configTarget(),
|
||||||
|
branch: .init(includeCommitSha: commitSha),
|
||||||
|
semvar: semvarOptions.configSemVarOptions(),
|
||||||
|
configurationFile: configurationFile
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,20 +182,6 @@ extension GlobalOptions {
|
|||||||
// MARK: - Helpers
|
// MARK: - Helpers
|
||||||
|
|
||||||
private extension TargetOptions {
|
private extension TargetOptions {
|
||||||
func target() throws -> String {
|
|
||||||
guard let path else {
|
|
||||||
guard let module else {
|
|
||||||
print("Neither target path or module was set.")
|
|
||||||
throw InvalidTargetOption()
|
|
||||||
}
|
|
||||||
|
|
||||||
return "\(module)/\(fileName)"
|
|
||||||
}
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
struct InvalidTargetOption: Error {}
|
|
||||||
|
|
||||||
func configTarget() throws -> Configuration.Target? {
|
func configTarget() throws -> Configuration.Target? {
|
||||||
guard let path else {
|
guard let path else {
|
||||||
guard let module else {
|
guard let module else {
|
||||||
|
|||||||
@@ -133,14 +133,17 @@ extension CliClient.SharedOptions {
|
|||||||
logLevel: Logger.Level = .trace,
|
logLevel: Logger.Level = .trace,
|
||||||
versionStrategy: Configuration.VersionStrategy = .semvar(.init())
|
versionStrategy: Configuration.VersionStrategy = .semvar(.init())
|
||||||
) -> Self {
|
) -> Self {
|
||||||
.init(
|
return .init(
|
||||||
dryRun: dryRun,
|
dryRun: dryRun,
|
||||||
gitDirectory: gitDirectory,
|
gitDirectory: gitDirectory,
|
||||||
logLevel: logLevel,
|
logLevel: logLevel,
|
||||||
configuration: .init(
|
target: .init(module: .init(target)),
|
||||||
target: .init(module: .init(target)),
|
branch: versionStrategy.branch,
|
||||||
strategy: versionStrategy
|
semvar: versionStrategy.semvar
|
||||||
)
|
// configuration: .init(
|
||||||
|
// target: .init(module: .init(target)),
|
||||||
|
// strategy: versionStrategy
|
||||||
|
// )
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user