feat: Begin working on configuration client.
This commit is contained in:
144
Sources/CliClient/Internal/Internal.swift
Normal file
144
Sources/CliClient/Internal/Internal.swift
Normal file
@@ -0,0 +1,144 @@
|
||||
import Dependencies
|
||||
import FileClient
|
||||
import Foundation
|
||||
import GitClient
|
||||
|
||||
@_spi(Internal)
|
||||
public extension CliClient.SharedOptions {
|
||||
|
||||
func parseTargetUrl() async throws -> URL {
|
||||
@Dependency(\.fileClient) var fileClient
|
||||
|
||||
let target = target.hasPrefix(".") ? String(target.dropFirst()) : target
|
||||
let targetHasSources = target.hasPrefix("Sources") || target.hasPrefix("/Sources")
|
||||
|
||||
var url = url(for: gitDirectory ?? (targetHasSources ? target : "Sources"))
|
||||
|
||||
if gitDirectory != nil {
|
||||
if !targetHasSources {
|
||||
url.appendPathComponent("Sources")
|
||||
}
|
||||
url.appendPathComponent(target)
|
||||
}
|
||||
|
||||
let isDirectory = try await fileClient.isDirectory(url.cleanFilePath)
|
||||
|
||||
if isDirectory {
|
||||
url.appendPathComponent(Constants.defaultFileName)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func run(
|
||||
_ operation: (CurrentVersionContainer) async throws -> Void
|
||||
) async rethrows -> String {
|
||||
try await withDependencies {
|
||||
$0.logger.logLevel = logLevel
|
||||
} operation: {
|
||||
@Dependency(\.logger) var logger
|
||||
|
||||
let targetUrl = try await parseTargetUrl()
|
||||
logger.debug("Target: \(targetUrl.cleanFilePath)")
|
||||
|
||||
try await operation(
|
||||
versionStrategy.currentVersion(
|
||||
file: targetUrl,
|
||||
gitDirectory: gitDirectory
|
||||
)
|
||||
)
|
||||
|
||||
return targetUrl.cleanFilePath
|
||||
}
|
||||
}
|
||||
|
||||
func write(_ string: String, to url: URL) async throws {
|
||||
@Dependency(\.fileClient) var fileClient
|
||||
@Dependency(\.logger) var logger
|
||||
if !dryRun {
|
||||
try await fileClient.write(string: string, to: url)
|
||||
} else {
|
||||
logger.debug("Skipping, due to dry-run being passed.")
|
||||
logger.debug("\(string)")
|
||||
}
|
||||
}
|
||||
|
||||
func write(_ currentVersion: CurrentVersionContainer) async throws {
|
||||
@Dependency(\.logger) var logger
|
||||
|
||||
let version = try currentVersion.version.string(allowPreReleaseTag: allowPreReleaseTag)
|
||||
logger.debug("Version: \(version)")
|
||||
|
||||
let template = currentVersion.usesOptionalType ? Template.optional(version) : Template.nonOptional(version)
|
||||
logger.trace("Template string: \(template)")
|
||||
|
||||
try await write(template, to: currentVersion.targetUrl)
|
||||
}
|
||||
}
|
||||
|
||||
@_spi(Internal)
|
||||
public struct CurrentVersionContainer: Sendable {
|
||||
|
||||
let targetUrl: URL
|
||||
let version: Version
|
||||
|
||||
var usesOptionalType: Bool {
|
||||
switch version {
|
||||
case .string: return false
|
||||
case let .semVar(_, usesOptionalType): return usesOptionalType
|
||||
}
|
||||
}
|
||||
|
||||
public enum Version: Sendable {
|
||||
case string(String)
|
||||
case semVar(SemVar, usesOptionalType: Bool = true)
|
||||
|
||||
func string(allowPreReleaseTag: Bool) throws -> String {
|
||||
switch self {
|
||||
case let .string(string):
|
||||
return string
|
||||
case let .semVar(semVar, usesOptionalType: _):
|
||||
return semVar.versionString(withPreReleaseTag: allowPreReleaseTag)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension CliClient.SharedOptions {
|
||||
|
||||
func build(_ environment: [String: String]) async throws -> String {
|
||||
try await run { currentVersion in
|
||||
try await write(currentVersion)
|
||||
}
|
||||
}
|
||||
|
||||
func bump(_ type: CliClient.BumpOption?) async throws -> String {
|
||||
guard let type else {
|
||||
return try await generate()
|
||||
}
|
||||
|
||||
return try await run { container in
|
||||
|
||||
@Dependency(\.logger) var logger
|
||||
|
||||
switch container.version {
|
||||
case .string: // When we did not parse a semVar, just write whatever we parsed for the current version.
|
||||
try await write(container)
|
||||
|
||||
case let .semVar(semVar, usesOptionalType: usesOptionalType):
|
||||
let bumped = semVar.bump(type, preRelease: nil) // preRelease is already set on semVar.
|
||||
let version = bumped.versionString(withPreReleaseTag: allowPreReleaseTag)
|
||||
logger.debug("Bumped version: \(version)")
|
||||
let template = usesOptionalType ? Template.optional(version) : Template.build(version)
|
||||
try await write(template, to: container.targetUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func generate() async throws -> String {
|
||||
try await run { currentVersion in
|
||||
try await write(currentVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user