feat: Integrates cli-client dependency into cli-version executable
This commit is contained in:
@@ -22,7 +22,7 @@ struct GenerateVersionBuildPlugin: BuildToolPlugin {
|
|||||||
.buildCommand(
|
.buildCommand(
|
||||||
displayName: "Build With Version Plugin",
|
displayName: "Build With Version Plugin",
|
||||||
executable: tool.path,
|
executable: tool.path,
|
||||||
arguments: ["build", "--verbose", "--git-directory", gitDirectoryPath.string, outputPath.string],
|
arguments: ["build", "--verbose", "--git-directory", gitDirectoryPath.string, "--target", outputPath.string],
|
||||||
environment: [:],
|
environment: [:],
|
||||||
inputFiles: target.sourceFiles.map(\.path),
|
inputFiles: target.sourceFiles.map(\.path),
|
||||||
outputFiles: [outputFile]
|
outputFiles: [outputFile]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import PackagePlugin
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import PackagePlugin
|
||||||
|
|
||||||
@main
|
@main
|
||||||
struct GenerateVersionPlugin: CommandPlugin {
|
struct GenerateVersionPlugin: CommandPlugin {
|
||||||
@@ -27,4 +27,3 @@ struct GenerateVersionPlugin: CommandPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,26 +34,26 @@ public struct CliClient: Sendable {
|
|||||||
case major, minor, patch
|
case major, minor, patch
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Use Int for `verbose`.
|
|
||||||
public struct SharedOptions: Equatable, Sendable {
|
public struct SharedOptions: Equatable, Sendable {
|
||||||
let gitDirectory: String?
|
|
||||||
let dryRun: Bool
|
let dryRun: Bool
|
||||||
let fileName: String
|
let fileName: String
|
||||||
|
let gitDirectory: String?
|
||||||
|
let logLevel: Logger.Level
|
||||||
let target: String
|
let target: String
|
||||||
let verbose: Bool
|
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
gitDirectory: String? = nil,
|
gitDirectory: String? = nil,
|
||||||
dryRun: Bool = false,
|
dryRun: Bool = false,
|
||||||
fileName: String = "Version.swift",
|
fileName: String = "Version.swift",
|
||||||
target: String,
|
target: String,
|
||||||
verbose: Bool = true
|
logLevel: Logger.Level = .debug
|
||||||
) {
|
) {
|
||||||
self.gitDirectory = gitDirectory
|
self.gitDirectory = gitDirectory
|
||||||
self.dryRun = dryRun
|
self.dryRun = dryRun
|
||||||
self.fileName = fileName
|
self.fileName = fileName
|
||||||
self.target = target
|
self.target = target
|
||||||
self.verbose = verbose
|
self.logLevel = logLevel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ public extension CliClient.SharedOptions {
|
|||||||
_ operation: () async throws -> T
|
_ operation: () async throws -> T
|
||||||
) async rethrows -> T {
|
) async rethrows -> T {
|
||||||
try await withDependencies {
|
try await withDependencies {
|
||||||
$0.logger.logLevel = .init(verbose: verbose)
|
$0.logger.logLevel = logLevel
|
||||||
} operation: {
|
} operation: {
|
||||||
try await operation()
|
try await operation()
|
||||||
}
|
}
|
||||||
@@ -114,6 +114,7 @@ public extension CliClient.SharedOptions {
|
|||||||
try await fileClient.write(string: string, to: url)
|
try await fileClient.write(string: string, to: url)
|
||||||
} else {
|
} else {
|
||||||
logger.debug("Skipping, due to dry-run being passed.")
|
logger.debug("Skipping, due to dry-run being passed.")
|
||||||
|
logger.debug("\(string)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,7 +148,7 @@ private extension CliClient.SharedOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getVersionString() async throws -> (String, Bool) {
|
private func getVersionString() async throws -> (version: String, usesOptionalType: Bool) {
|
||||||
@Dependency(\.fileClient) var fileClient
|
@Dependency(\.fileClient) var fileClient
|
||||||
@Dependency(\.gitVersionClient) var gitVersionClient
|
@Dependency(\.gitVersionClient) var gitVersionClient
|
||||||
@Dependency(\.logger) var logger
|
@Dependency(\.logger) var logger
|
||||||
@@ -290,6 +291,10 @@ public struct Template: Sendable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static func build(_ version: String? = nil) -> String {
|
public static func build(_ version: String? = nil) -> String {
|
||||||
|
nonOptional(version)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func nonOptional(_ version: String? = nil) -> String {
|
||||||
Self(type: .string, version: version).value
|
Self(type: .string, version: version).value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,12 @@ import Logging
|
|||||||
@_spi(Internal)
|
@_spi(Internal)
|
||||||
public extension Logger.Level {
|
public extension Logger.Level {
|
||||||
|
|
||||||
init(verbose: Bool) {
|
init(verbose: Int) {
|
||||||
if verbose {
|
switch verbose {
|
||||||
self = .debug
|
case 1: self = .warning
|
||||||
} else {
|
case 2: self = .debug
|
||||||
self = .info
|
case 3...: self = .trace
|
||||||
|
default: self = .info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,40 +10,13 @@ extension CliVersionCommand {
|
|||||||
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."
|
||||||
)
|
)
|
||||||
|
|
||||||
@OptionGroup var shared: SharedOptions
|
@OptionGroup var globals: GlobalOptions
|
||||||
|
|
||||||
@Option(
|
|
||||||
name: .customLong("git-directory"),
|
|
||||||
help: "The git directory for the version."
|
|
||||||
)
|
|
||||||
var gitDirectory: String
|
|
||||||
|
|
||||||
// TODO: Use CliClient
|
|
||||||
func run() async throws {
|
func run() async throws {
|
||||||
try await withDependencies {
|
try await globals.run {
|
||||||
$0.logger.logLevel = .debug
|
@Dependency(\.cliClient) var cliClient
|
||||||
$0.fileClient = .liveValue
|
let output = try await cliClient.build(globals.shared)
|
||||||
$0.gitVersionClient = .liveValue
|
print(output)
|
||||||
} operation: {
|
|
||||||
@Dependency(\.gitVersionClient) var gitVersion
|
|
||||||
@Dependency(\.fileClient) var fileClient
|
|
||||||
@Dependency(\.logger) var logger: Logger
|
|
||||||
|
|
||||||
logger.info("Building with git-directory: \(gitDirectory)")
|
|
||||||
|
|
||||||
let fileUrl = URL(fileURLWithPath: shared.target)
|
|
||||||
.appendingPathComponent(shared.fileName)
|
|
||||||
|
|
||||||
let fileString = fileUrl.fileString()
|
|
||||||
logger.info("File Url: \(fileString)")
|
|
||||||
|
|
||||||
let currentVersion = try await gitVersion.currentVersion(in: gitDirectory)
|
|
||||||
|
|
||||||
let fileContents = buildTemplate
|
|
||||||
.replacingOccurrences(of: "nil", with: "\"\(currentVersion)\"")
|
|
||||||
|
|
||||||
try await fileClient.write(string: fileContents, to: fileUrl)
|
|
||||||
logger.info("Updated version file: \(fileString)")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
28
Sources/cli-version/BumpCommand.swift
Normal file
28
Sources/cli-version/BumpCommand.swift
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import ArgumentParser
|
||||||
|
import CliVersion
|
||||||
|
import Dependencies
|
||||||
|
|
||||||
|
extension CliVersionCommand {
|
||||||
|
struct Bump: AsyncParsableCommand {
|
||||||
|
|
||||||
|
static let configuration = CommandConfiguration(
|
||||||
|
commandName: "bump",
|
||||||
|
abstract: "Bump version of a command-line tool."
|
||||||
|
)
|
||||||
|
|
||||||
|
@OptionGroup var globals: GlobalOptions
|
||||||
|
|
||||||
|
@Flag
|
||||||
|
var bumpOption: CliClient.BumpOption = .patch
|
||||||
|
|
||||||
|
func run() async throws {
|
||||||
|
try await globals.run {
|
||||||
|
@Dependency(\.cliClient) var cliClient
|
||||||
|
let output = try await cliClient.bump(bumpOption, globals.shared)
|
||||||
|
print(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CliClient.BumpOption: EnumerableFlag {}
|
||||||
@@ -8,6 +8,7 @@ struct CliVersionCommand: AsyncParsableCommand {
|
|||||||
version: VERSION ?? "0.0.0",
|
version: VERSION ?? "0.0.0",
|
||||||
subcommands: [
|
subcommands: [
|
||||||
Build.self,
|
Build.self,
|
||||||
|
Bump.self,
|
||||||
Generate.self,
|
Generate.self,
|
||||||
Update.self
|
Update.self
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -12,28 +12,13 @@ extension CliVersionCommand {
|
|||||||
version: VERSION ?? "0.0.0"
|
version: VERSION ?? "0.0.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
@OptionGroup var shared: SharedOptions
|
@OptionGroup var globals: GlobalOptions
|
||||||
|
|
||||||
// TODO: Use CliClient
|
|
||||||
func run() async throws {
|
func run() async throws {
|
||||||
@Dependency(\.logger) var logger: Logger
|
try await globals.run {
|
||||||
@Dependency(\.fileClient) var fileClient
|
@Dependency(\.cliClient) var cliClient
|
||||||
|
let output = try await cliClient.generate(globals.shared)
|
||||||
let targetUrl = parseTarget(shared.target)
|
print(output)
|
||||||
let fileUrl = targetUrl.appendingPathComponent(shared.fileName)
|
|
||||||
|
|
||||||
let fileString = fileUrl.fileString()
|
|
||||||
|
|
||||||
guard !FileManager.default.fileExists(atPath: fileUrl.absoluteString) else {
|
|
||||||
logger.info("File already exists at path.")
|
|
||||||
throw GenerationError.fileExists(path: fileString)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !shared.dryRun {
|
|
||||||
try await fileClient.write(string: optionalTemplate, to: fileUrl)
|
|
||||||
logger.info("Generated file at: \(fileString)")
|
|
||||||
} else {
|
|
||||||
logger.info("Would generate file at: \(fileString)")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
88
Sources/cli-version/GlobalOptions.swift
Normal file
88
Sources/cli-version/GlobalOptions.swift
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
import ArgumentParser
|
||||||
|
@_spi(Internal) import CliVersion
|
||||||
|
import Dependencies
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
func parseTarget(_ target: String) -> URL {
|
||||||
|
let url = URL(fileURLWithPath: target)
|
||||||
|
let urlTest = url
|
||||||
|
.deletingLastPathComponent()
|
||||||
|
|
||||||
|
guard urlTest.lastPathComponent == "Sources" else {
|
||||||
|
return URL(fileURLWithPath: "Sources")
|
||||||
|
.appendingPathComponent(target)
|
||||||
|
}
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
||||||
|
extension URL {
|
||||||
|
func fileString() -> String {
|
||||||
|
absoluteString
|
||||||
|
.replacingOccurrences(of: "file://", with: "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let optionalTemplate = """
|
||||||
|
// Do not set this variable, it is set during the build process.
|
||||||
|
let VERSION: String? = nil
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
let buildTemplate = """
|
||||||
|
// Do not set this variable, it is set during the build process.
|
||||||
|
let VERSION: String = nil
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
struct GlobalOptions: ParsableArguments {
|
||||||
|
|
||||||
|
@Option(
|
||||||
|
name: .customLong("git-directory"),
|
||||||
|
help: "The git directory for the version (default: current directory)"
|
||||||
|
)
|
||||||
|
var gitDirectory: String?
|
||||||
|
|
||||||
|
@Option(
|
||||||
|
name: .shortAndLong,
|
||||||
|
help: "The target for the version file."
|
||||||
|
)
|
||||||
|
var target: String
|
||||||
|
|
||||||
|
@Option(
|
||||||
|
name: .customLong("filename"),
|
||||||
|
help: "Specify the file name for the version file in the target."
|
||||||
|
)
|
||||||
|
var fileName: String = "Version.swift"
|
||||||
|
|
||||||
|
@Flag(name: .customLong("dry-run"))
|
||||||
|
var dryRun: Bool = false
|
||||||
|
|
||||||
|
@Flag(
|
||||||
|
name: .shortAndLong,
|
||||||
|
help: "Increase logging level, can be passed multiple times (example: -vvv)."
|
||||||
|
)
|
||||||
|
var verbose: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
extension GlobalOptions {
|
||||||
|
|
||||||
|
var shared: CliClient.SharedOptions {
|
||||||
|
.init(
|
||||||
|
gitDirectory: gitDirectory,
|
||||||
|
dryRun: dryRun,
|
||||||
|
fileName: fileName,
|
||||||
|
target: target,
|
||||||
|
logLevel: .init(verbose: verbose)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(_ operation: () async throws -> Void) async throws {
|
||||||
|
try await withDependencies {
|
||||||
|
$0.fileClient = .liveValue
|
||||||
|
$0.gitVersionClient = .liveValue
|
||||||
|
$0.cliClient = .liveValue
|
||||||
|
} operation: {
|
||||||
|
try await operation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
import ArgumentParser
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
func parseTarget(_ target: String) -> URL {
|
|
||||||
let url = URL(fileURLWithPath: target)
|
|
||||||
let urlTest = url
|
|
||||||
.deletingLastPathComponent()
|
|
||||||
|
|
||||||
guard urlTest.lastPathComponent == "Sources" else {
|
|
||||||
return URL(fileURLWithPath: "Sources")
|
|
||||||
.appendingPathComponent(target)
|
|
||||||
}
|
|
||||||
return url
|
|
||||||
}
|
|
||||||
|
|
||||||
extension URL {
|
|
||||||
func fileString() -> String {
|
|
||||||
absoluteString
|
|
||||||
.replacingOccurrences(of: "file://", with: "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let optionalTemplate = """
|
|
||||||
// Do not set this variable, it is set during the build process.
|
|
||||||
let VERSION: String? = nil
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
let buildTemplate = """
|
|
||||||
// Do not set this variable, it is set during the build process.
|
|
||||||
let VERSION: String = nil
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
// TODO: Use Int for `verbose`.
|
|
||||||
struct SharedOptions: ParsableArguments {
|
|
||||||
|
|
||||||
@Argument(help: "The target for the version file.")
|
|
||||||
var target: String
|
|
||||||
|
|
||||||
@Option(
|
|
||||||
name: .customLong("filename"),
|
|
||||||
help: "Specify the file name for the version file."
|
|
||||||
)
|
|
||||||
var fileName: String = "Version.swift"
|
|
||||||
|
|
||||||
@Flag(name: .customLong("dry-run"))
|
|
||||||
var dryRun: Bool = false
|
|
||||||
|
|
||||||
@Flag(name: .long, help: "Increase logging level.")
|
|
||||||
var verbose: Bool = false
|
|
||||||
}
|
|
||||||
@@ -12,45 +12,13 @@ extension CliVersionCommand {
|
|||||||
discussion: "This command can be interacted with directly outside of the plugin context."
|
discussion: "This command can be interacted with directly outside of the plugin context."
|
||||||
)
|
)
|
||||||
|
|
||||||
@OptionGroup var shared: SharedOptions
|
@OptionGroup var globals: GlobalOptions
|
||||||
|
|
||||||
@Option(
|
|
||||||
name: .customLong("git-directory"),
|
|
||||||
help: "The git directory for the version."
|
|
||||||
)
|
|
||||||
var gitDirectory: String?
|
|
||||||
|
|
||||||
// TODO: Use CliClient
|
|
||||||
func run() async throws {
|
func run() async throws {
|
||||||
try await withDependencies {
|
try await globals.run {
|
||||||
$0.logger.logLevel = shared.verbose ? .debug : .info
|
@Dependency(\.cliClient) var cliClient
|
||||||
$0.fileClient = .liveValue
|
let output = try await cliClient.update(globals.shared)
|
||||||
$0.gitVersionClient = .liveValue
|
print(output)
|
||||||
$0.asyncShellClient = .liveValue
|
|
||||||
} operation: {
|
|
||||||
@Dependency(\.gitVersionClient) var gitVersion
|
|
||||||
@Dependency(\.fileClient) var fileClient
|
|
||||||
@Dependency(\.logger) var logger
|
|
||||||
@Dependency(\.asyncShellClient) var shell
|
|
||||||
|
|
||||||
let targetUrl = parseTarget(shared.target)
|
|
||||||
let fileUrl = targetUrl
|
|
||||||
.appendingPathComponent(shared.fileName)
|
|
||||||
|
|
||||||
let fileString = fileUrl.fileString()
|
|
||||||
|
|
||||||
let currentVersion = try await gitVersion.currentVersion(in: gitDirectory)
|
|
||||||
|
|
||||||
let fileContents = optionalTemplate
|
|
||||||
.replacingOccurrences(of: "nil", with: "\"\(currentVersion)\"")
|
|
||||||
|
|
||||||
if !shared.dryRun {
|
|
||||||
try await fileClient.write(string: fileContents, to: fileUrl)
|
|
||||||
logger.info("Updated version file: \(fileString)")
|
|
||||||
} else {
|
|
||||||
logger.info("Would update file contents to:")
|
|
||||||
logger.info("\(fileContents)")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
// Do not set this variable, it is set during the build process.
|
// Do not set this variable, it is set during the build process.
|
||||||
let VERSION: String? = "0.1.0"
|
let VERSION: String? = "0.1.1"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
@_spi(Internal) import CliVersion
|
@_spi(Internal) import CliVersion
|
||||||
import Dependencies
|
import Dependencies
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Logging
|
||||||
import Testing
|
import Testing
|
||||||
import TestSupport
|
import TestSupport
|
||||||
|
|
||||||
@@ -12,16 +13,8 @@ struct CliClientTests {
|
|||||||
)
|
)
|
||||||
func testBuild(target: String) async throws {
|
func testBuild(target: String) async throws {
|
||||||
try await run {
|
try await run {
|
||||||
let client = CliClient.liveValue
|
@Dependency(\.cliClient) var client
|
||||||
|
let output = try await client.build(.testOptions(target: target))
|
||||||
let output = try await client.build(.init(
|
|
||||||
gitDirectory: "/baz",
|
|
||||||
dryRun: false,
|
|
||||||
fileName: "foo",
|
|
||||||
target: target,
|
|
||||||
verbose: true
|
|
||||||
))
|
|
||||||
|
|
||||||
#expect(output == "/baz/Sources/bar/foo")
|
#expect(output == "/baz/Sources/bar/foo")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,27 +28,21 @@ struct CliClientTests {
|
|||||||
$0.fileClient.fileExists = { _ in true }
|
$0.fileClient.fileExists = { _ in true }
|
||||||
$0.fileClient.read = { @Sendable _ in template }
|
$0.fileClient.read = { @Sendable _ in template }
|
||||||
} operation: {
|
} operation: {
|
||||||
let client = CliClient.liveValue
|
@Dependency(\.cliClient) var client
|
||||||
let output = try await client.bump(
|
let output = try await client.bump(type, .testOptions())
|
||||||
type,
|
|
||||||
.init(
|
|
||||||
gitDirectory: "/baz",
|
|
||||||
dryRun: false,
|
|
||||||
fileName: "foo",
|
|
||||||
target: "bar",
|
|
||||||
verbose: true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
#expect(output == "/baz/Sources/bar/foo")
|
#expect(output == "/baz/Sources/bar/foo")
|
||||||
} assert: { string, _ in
|
} assert: { string, _ in
|
||||||
|
|
||||||
|
#expect(string != nil)
|
||||||
let typeString = optional ? "String?" : "String"
|
let typeString = optional ? "String?" : "String"
|
||||||
|
|
||||||
switch type {
|
switch type {
|
||||||
case .major:
|
case .major:
|
||||||
#expect(string.contains("let VERSION: \(typeString) = \"2.0.0\""))
|
#expect(string!.contains("let VERSION: \(typeString) = \"2.0.0\""))
|
||||||
case .minor:
|
case .minor:
|
||||||
#expect(string.contains("let VERSION: \(typeString) = \"1.1.0\""))
|
#expect(string!.contains("let VERSION: \(typeString) = \"1.1.0\""))
|
||||||
case .patch:
|
case .patch:
|
||||||
#expect(string.contains("let VERSION: \(typeString) = \"1.0.1\""))
|
#expect(string!.contains("let VERSION: \(typeString) = \"1.0.1\""))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,42 +51,34 @@ struct CliClientTests {
|
|||||||
arguments: TestArguments.testCases
|
arguments: TestArguments.testCases
|
||||||
)
|
)
|
||||||
func generate(target: String) async throws {
|
func generate(target: String) async throws {
|
||||||
// let (stream, continuation) = AsyncStream<Data>.makeStream()
|
|
||||||
try await run {
|
try await run {
|
||||||
let client = CliClient.liveValue
|
@Dependency(\.cliClient) var client
|
||||||
let output = try await client.generate(.init(
|
let output = try await client.generate(.testOptions(target: target))
|
||||||
gitDirectory: "/baz",
|
|
||||||
dryRun: false,
|
|
||||||
fileName: "foo",
|
|
||||||
target: target,
|
|
||||||
verbose: true
|
|
||||||
))
|
|
||||||
#expect(output == "/baz/Sources/bar/foo")
|
#expect(output == "/baz/Sources/bar/foo")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(
|
@Test(
|
||||||
arguments: TestArguments.testCases
|
arguments: TestArguments.updateCases
|
||||||
)
|
)
|
||||||
func update(target: String) async throws {
|
func update(target: String, dryRun: Bool) async throws {
|
||||||
// let (stream, continuation) = AsyncStream<Data>.makeStream()
|
|
||||||
try await run {
|
try await run {
|
||||||
let client = CliClient.liveValue
|
$0.fileClient.fileExists = { _ in false }
|
||||||
let output = try await client.update(.init(
|
} operation: {
|
||||||
gitDirectory: "/baz",
|
@Dependency(\.cliClient) var client
|
||||||
dryRun: false,
|
let output = try await client.update(.testOptions(dryRun: dryRun, target: target))
|
||||||
fileName: "foo",
|
|
||||||
target: target,
|
|
||||||
verbose: true
|
|
||||||
))
|
|
||||||
#expect(output == "/baz/Sources/bar/foo")
|
#expect(output == "/baz/Sources/bar/foo")
|
||||||
|
} assert: { string, _ in
|
||||||
|
if dryRun {
|
||||||
|
#expect(string == nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(
|
func run(
|
||||||
setupDependencies: @escaping (inout DependencyValues) -> Void = { _ in },
|
setupDependencies: @escaping (inout DependencyValues) -> Void = { _ in },
|
||||||
operation: @Sendable @escaping () async throws -> Void,
|
operation: @Sendable @escaping () async throws -> Void,
|
||||||
assert: @escaping (String, URL) -> Void = { _, _ in }
|
assert: @escaping (String?, URL?) -> Void = { _, _ in }
|
||||||
) async throws {
|
) async throws {
|
||||||
let captured = CapturingWrite()
|
let captured = CapturingWrite()
|
||||||
|
|
||||||
@@ -108,18 +87,17 @@ struct CliClientTests {
|
|||||||
$0.fileClient = .capturing(captured)
|
$0.fileClient = .capturing(captured)
|
||||||
$0.fileClient.fileExists = { _ in false }
|
$0.fileClient.fileExists = { _ in false }
|
||||||
$0.gitVersionClient = .init { _, _ in "1.0.0" }
|
$0.gitVersionClient = .init { _, _ in "1.0.0" }
|
||||||
|
$0.cliClient = .liveValue
|
||||||
setupDependencies(&$0)
|
setupDependencies(&$0)
|
||||||
} operation: {
|
} operation: {
|
||||||
try await operation()
|
try await operation()
|
||||||
}
|
}
|
||||||
let data = await captured.data
|
let data = await captured.data
|
||||||
let url = await captured.url
|
let url = await captured.url
|
||||||
|
var string: String?
|
||||||
|
|
||||||
guard let data,
|
if let data {
|
||||||
let string = String(bytes: data, encoding: .utf8),
|
string = String(bytes: data, encoding: .utf8)
|
||||||
let url
|
|
||||||
else {
|
|
||||||
throw TestError()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(string, url)
|
assert(string, url)
|
||||||
@@ -132,6 +110,26 @@ enum TestArguments {
|
|||||||
$0.append(($1, true))
|
$0.append(($1, true))
|
||||||
$0.append(($1, false))
|
$0.append(($1, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static let updateCases = testCases.map { ($0, Bool.random()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestError: Error {}
|
struct TestError: Error {}
|
||||||
|
|
||||||
|
extension CliClient.SharedOptions {
|
||||||
|
static func testOptions(
|
||||||
|
gitDirectory: String? = "/baz",
|
||||||
|
dryRun: Bool = false,
|
||||||
|
fileName: String = "foo",
|
||||||
|
target: String = "bar",
|
||||||
|
logLevel: Logger.Level = .trace
|
||||||
|
) -> Self {
|
||||||
|
.init(
|
||||||
|
gitDirectory: gitDirectory,
|
||||||
|
dryRun: dryRun,
|
||||||
|
fileName: fileName,
|
||||||
|
target: target,
|
||||||
|
logLevel: logLevel
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user