wip
This commit is contained in:
@@ -9,7 +9,8 @@ let package = Package(
|
|||||||
],
|
],
|
||||||
products: [
|
products: [
|
||||||
.library(name: "GitVersion", targets: ["GitVersion"]),
|
.library(name: "GitVersion", targets: ["GitVersion"]),
|
||||||
.plugin(name: "GenerateVersionPlugin", targets: ["GenerateVersionPlugin"])
|
.plugin(name: "GenerateVersionPlugin", targets: ["GenerateVersionPlugin"]),
|
||||||
|
.plugin(name: "UpdateVersionPlugin", targets: ["UpdateVersionPlugin"])
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.package(url: "https://github.com/m-housh/swift-shell-client.git", from: "0.1.0"),
|
.package(url: "https://github.com/m-housh/swift-shell-client.git", from: "0.1.0"),
|
||||||
@@ -48,6 +49,21 @@ let package = Package(
|
|||||||
dependencies: [
|
dependencies: [
|
||||||
"git-version"
|
"git-version"
|
||||||
]
|
]
|
||||||
|
),
|
||||||
|
.plugin(
|
||||||
|
name: "UpdateVersionPlugin",
|
||||||
|
capability: .command(
|
||||||
|
intent: .custom(
|
||||||
|
verb: "update-version",
|
||||||
|
description: "Updates a version file in the given target."
|
||||||
|
),
|
||||||
|
permissions: [
|
||||||
|
.writeToPackageDirectory(reason: "Update a version file in the target's directory.")
|
||||||
|
]
|
||||||
|
),
|
||||||
|
dependencies: [
|
||||||
|
"git-version"
|
||||||
|
]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ struct GenerateVersionPlugin: CommandPlugin {
|
|||||||
func performCommand(context: PluginContext, arguments: [String]) async throws {
|
func performCommand(context: PluginContext, arguments: [String]) async throws {
|
||||||
let gitVersion = try context.tool(named: "git-version")
|
let gitVersion = try context.tool(named: "git-version")
|
||||||
|
|
||||||
var arguments = ["generate"] + arguments
|
let arguments = ["generate"] + arguments
|
||||||
|
|
||||||
for target in context.package.targets {
|
for target in context.package.targets {
|
||||||
guard let target = target as? SourceModuleTarget,
|
guard let target = target as? SourceModuleTarget,
|
||||||
|
|||||||
29
Plugins/UpdateVersionPlugin/UpdateVersionPlugin.swift
Normal file
29
Plugins/UpdateVersionPlugin/UpdateVersionPlugin.swift
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import PackagePlugin
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct UpdateVersionPlugin: CommandPlugin {
|
||||||
|
|
||||||
|
func performCommand(context: PluginContext, arguments: [String]) async throws {
|
||||||
|
let gitVersion = try context.tool(named: "git-version")
|
||||||
|
|
||||||
|
let arguments = ["update"] + arguments
|
||||||
|
|
||||||
|
for target in context.package.targets {
|
||||||
|
guard let target = target as? SourceModuleTarget,
|
||||||
|
arguments.first(where: { $0.contains(target.name) }) != nil
|
||||||
|
else { continue }
|
||||||
|
|
||||||
|
let process = Process()
|
||||||
|
process.executableURL = URL(fileURLWithPath: gitVersion.path.string)
|
||||||
|
process.arguments = arguments
|
||||||
|
try process.run()
|
||||||
|
process.waitUntilExit()
|
||||||
|
|
||||||
|
guard process.terminationReason == .exit && process.terminationStatus == 0 else {
|
||||||
|
Diagnostics.error("Reason: \(process.terminationReason), status: \(process.terminationStatus)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -116,7 +116,7 @@ fileprivate struct GitVersion {
|
|||||||
.init(
|
.init(
|
||||||
shell: .env,
|
shell: .env,
|
||||||
environment: nil,
|
environment: nil,
|
||||||
in: workingDirectory,
|
in: workingDirectory ?? FileManager.default.currentDirectoryPath,
|
||||||
argument.arguments
|
argument.arguments
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,90 +100,92 @@ public struct SwiftBuild {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ShellClient {
|
//extension ShellClient {
|
||||||
|
//
|
||||||
/// Reads contents at the given file path, then allows the caller to act on the
|
// /// Reads contents at the given file path, then allows the caller to act on the
|
||||||
/// results after "nil" has been replaced with the current version string.
|
// /// results after "nil" has been replaced with the current version string.
|
||||||
///
|
// ///
|
||||||
/// - Parameters:
|
// /// - Parameters:
|
||||||
/// - filePath: The file path to replace nil in.
|
// /// - filePath: The file path to replace nil in.
|
||||||
/// - workingDirectory: Customize the working directory for the command.
|
// /// - workingDirectory: Customize the working directory for the command.
|
||||||
/// - closure: The closure to run with the updated file content string.
|
// /// - closure: The closure to run with the updated file content string.
|
||||||
public func replacingNilWithVersionString(
|
// public func replacingNilWithVersionString(
|
||||||
in filePath: String,
|
// in filePath: String,
|
||||||
from workingDirectory: String? = nil,
|
// from workingDirectory: String? = nil,
|
||||||
_ closure: @escaping (String) throws -> Void
|
// _ closure: @escaping (String) throws -> Void
|
||||||
) throws {
|
// ) throws {
|
||||||
@Dependency(\.fileClient) var fileClient: FileClient
|
// @Dependency(\.fileClient) var fileClient: FileClient
|
||||||
@Dependency(\.gitVersionClient) var gitClient: GitVersionClient
|
// @Dependency(\.gitVersionClient) var gitClient: GitVersionClient
|
||||||
@Dependency(\.logger) var logger: Logger
|
// @Dependency(\.logger) var logger: Logger
|
||||||
|
//
|
||||||
let currentVersion = try gitClient.currentVersion(in: workingDirectory)
|
// let currentVersion = try gitClient.currentVersion(in: workingDirectory)
|
||||||
let originalContents = try fileClient.readAsString(path: filePath)
|
// let originalContents = try fileClient.readAsString(path: filePath)
|
||||||
|
//
|
||||||
logger.debug("Setting version: \(currentVersion)")
|
// logger.debug("Setting version: \(currentVersion)")
|
||||||
|
//
|
||||||
let updatedContents = originalContents
|
// let updatedContents = originalContents
|
||||||
.replacingOccurrences(of: "nil", with: "\"\(currentVersion)\"")
|
// .replacingOccurrences(of: "nil", with: "\"\(currentVersion)\"")
|
||||||
|
//
|
||||||
logger.debug("Set version")
|
// logger.debug("Set version")
|
||||||
|
// logger.debug("Updated contents:")
|
||||||
try closure(updatedContents)
|
// logger.debug("\(updatedContents)")
|
||||||
}
|
//
|
||||||
|
// try closure(updatedContents)
|
||||||
|
// }
|
||||||
/// Replace nil in the given file path and then run the given closure.
|
//
|
||||||
///
|
//
|
||||||
/// > Note: The file contents will be reset back to nil after the closure operation.
|
// /// Replace nil in the given file path and then run the given closure.
|
||||||
///
|
// ///
|
||||||
/// - Parameters:
|
// /// > Note: The file contents will be reset back to nil after the closure operation.
|
||||||
/// - filePath: The file path to replace nil in.
|
// ///
|
||||||
/// - workingDirectory: Customize the working directory for the command.
|
// /// - Parameters:
|
||||||
/// - build: The swift builder to use.
|
// /// - filePath: The file path to replace nil in.
|
||||||
public func replacingNilWithVersionString(
|
// /// - workingDirectory: Customize the working directory for the command.
|
||||||
in filePath: String,
|
// /// - build: The swift builder to use.
|
||||||
from workingDirectory: String? = nil,
|
// public func replacingNilWithVersionString(
|
||||||
_ closure: @escaping () throws -> Void
|
// in filePath: String,
|
||||||
) throws {
|
// from workingDirectory: String? = nil,
|
||||||
@Dependency(\.fileClient) var fileClient: FileClient
|
// _ closure: @escaping () throws -> Void
|
||||||
@Dependency(\.logger) var logger: Logger
|
// ) throws {
|
||||||
|
// @Dependency(\.fileClient) var fileClient: FileClient
|
||||||
// grab the original contents, to set it back when done.
|
// @Dependency(\.logger) var logger: Logger
|
||||||
let originalContents = try fileClient.readAsString(path: filePath)
|
//
|
||||||
|
// // grab the original contents, to set it back when done.
|
||||||
try self.replacingNilWithVersionString(
|
// let originalContents = try fileClient.readAsString(path: filePath)
|
||||||
in: filePath,
|
//
|
||||||
from: workingDirectory
|
// try self.replacingNilWithVersionString(
|
||||||
) { update in
|
// in: filePath,
|
||||||
try fileClient.write(string: update, to: filePath)
|
// from: workingDirectory
|
||||||
defer { try! fileClient.write(string: originalContents, to: filePath) }
|
// ) { update in
|
||||||
|
// try fileClient.write(string: update, to: filePath)
|
||||||
try closure()
|
// defer { try! fileClient.write(string: originalContents, to: filePath) }
|
||||||
}
|
//
|
||||||
|
// try closure()
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/// Replace nil in the given file path and then build the project, using the
|
// }
|
||||||
/// given builder.
|
//
|
||||||
///
|
// /// Replace nil in the given file path and then build the project, using the
|
||||||
/// > Note: The file contents will be reset back to nil after the build operation.
|
// /// given builder.
|
||||||
///
|
// ///
|
||||||
/// - Parameters:
|
// /// > Note: The file contents will be reset back to nil after the build operation.
|
||||||
/// - filePath: The file path to replace nil in.
|
// ///
|
||||||
/// - workingDirectory: Customize the working directory for the command.
|
// /// - Parameters:
|
||||||
/// - build: The swift builder to use.
|
// /// - filePath: The file path to replace nil in.
|
||||||
public func replacingNilWithVersionString(
|
// /// - workingDirectory: Customize the working directory for the command.
|
||||||
in filePath: String,
|
// /// - build: The swift builder to use.
|
||||||
from workingDirectory: String? = nil,
|
// public func replacingNilWithVersionString(
|
||||||
build: SwiftBuild
|
// in filePath: String,
|
||||||
) throws {
|
// from workingDirectory: String? = nil,
|
||||||
try replacingNilWithVersionString(
|
// build: SwiftBuild
|
||||||
in: filePath,
|
// ) throws {
|
||||||
from: workingDirectory,
|
// try replacingNilWithVersionString(
|
||||||
build.run
|
// in: filePath,
|
||||||
)
|
// from: workingDirectory,
|
||||||
}
|
// build.run
|
||||||
}
|
// )
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
fileprivate extension Array where Element == SwiftBuild.Argument {
|
fileprivate extension Array where Element == SwiftBuild.Argument {
|
||||||
|
|
||||||
|
|||||||
@@ -42,8 +42,3 @@ fileprivate enum GenerationError: Error {
|
|||||||
case fileExists(path: String)
|
case fileExists(path: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate let template = """
|
|
||||||
// Do not set this variable, it is set during the build process.
|
|
||||||
let VERSION: String? = nil
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|||||||
@@ -14,17 +14,3 @@ struct GitVersionCommand: ParsableCommand {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import ArgumentParser
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
func parseTarget(_ target: String) -> URL {
|
func parseTarget(_ target: String) -> URL {
|
||||||
@@ -18,3 +19,27 @@ extension URL {
|
|||||||
.replacingOccurrences(of: "file://", with: "")
|
.replacingOccurrences(of: "file://", with: "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let template = """
|
||||||
|
// Do not set this variable, it is set during the build process.
|
||||||
|
let VERSION: String? = nil
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,43 +19,35 @@ extension GitVersionCommand {
|
|||||||
var gitDirectory: String? = nil
|
var gitDirectory: String? = nil
|
||||||
|
|
||||||
func run() throws {
|
func run() throws {
|
||||||
@Dependency(\.logger) var logger: Logger
|
try withDependencies {
|
||||||
@Dependency(\.fileClient) var fileClient: FileClient
|
$0.logger.logLevel = shared.verbose ? .debug : .info
|
||||||
|
$0.fileClient = .liveValue
|
||||||
|
$0.gitVersionClient = .liveValue
|
||||||
|
$0.shellClient = .liveValue
|
||||||
|
} operation: {
|
||||||
@Dependency(\.gitVersionClient) var gitVersion
|
@Dependency(\.gitVersionClient) var gitVersion
|
||||||
|
@Dependency(\.fileClient) var fileClient
|
||||||
|
@Dependency(\.logger) var logger
|
||||||
@Dependency(\.shellClient) var shell
|
@Dependency(\.shellClient) var shell
|
||||||
|
|
||||||
let targetUrl = parseTarget(shared.target)
|
let targetUrl = parseTarget(shared.target)
|
||||||
let fileUrl = targetUrl.appendingPathComponent(shared.fileName)
|
let fileUrl = targetUrl
|
||||||
|
.appendingPathComponent(shared.fileName)
|
||||||
|
|
||||||
let fileString = fileUrl.fileString()
|
let fileString = fileUrl.fileString()
|
||||||
|
|
||||||
// guard FileManager.default.fileExists(atPath: fileUrl.absoluteString) else {
|
let currentVersion = try gitVersion.currentVersion(in: gitDirectory)
|
||||||
// logger.info("Version file does not exist.")
|
|
||||||
// throw UpdateError.versionFileDoesNotExist(path: fileString)
|
|
||||||
// }
|
|
||||||
|
|
||||||
let currentVersion = try gitVersion.currentVersion()
|
let fileContents = template
|
||||||
let cwd = FileManager.default.currentDirectoryPath
|
.replacingOccurrences(of: "nil", with: "\"\(currentVersion)\"")
|
||||||
logger.info("CWD: \(cwd)")
|
|
||||||
logger.info("Git version: \(currentVersion)")
|
|
||||||
|
|
||||||
var updatedContents: String = ""
|
|
||||||
try withDependencies({
|
|
||||||
$0.logger.logLevel = .debug
|
|
||||||
}, operation: {
|
|
||||||
try shell.replacingNilWithVersionString(
|
|
||||||
in: fileString
|
|
||||||
// from: gitDirectory
|
|
||||||
) {
|
|
||||||
updatedContents = $0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if !shared.dryRun {
|
if !shared.dryRun {
|
||||||
try fileClient.write(string: updatedContents, to: fileUrl)
|
try fileClient.write(string: fileContents, to: fileUrl)
|
||||||
logger.info("Updated version file: \(fileString)")
|
logger.info("Updated version file: \(fileString)")
|
||||||
} else {
|
} else {
|
||||||
logger.info("Would update file contents to:")
|
logger.info("Would update file contents to:")
|
||||||
logger.info("\(updatedContents)")
|
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? = ""
|
let VERSION: String? = nil
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ final class GitVersionTests: XCTestCase {
|
|||||||
// can't really have a predictable result for the live client.
|
// can't really have a predictable result for the live client.
|
||||||
XCTAssertNotEqual(version, "blob")
|
XCTAssertNotEqual(version, "blob")
|
||||||
|
|
||||||
|
// print(FileManager.default.currentDirectoryPath)
|
||||||
// let other = try versionClient.currentVersion()
|
// let other = try versionClient.currentVersion()
|
||||||
// XCTAssertEqual(version, other)
|
// XCTAssertEqual(version, other)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user