Skip to content

Commit

Permalink
Support Executable Targets (#2)
Browse files Browse the repository at this point in the history
* Refactor extractCommand()

* Add documentation

* Add documentation to the generated type

* Add support for executable targets

* Revert extractCommand changes

* Improve readability of verbose message

* More readability improvements
  • Loading branch information
mgacy authored Dec 6, 2023
1 parent b5bb65e commit b1f5cee
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 4 deletions.
23 changes: 23 additions & 0 deletions Plugins/VersionFile/Extensions/PackagePlugin+Utils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// PackagePlugin+Utils.swift
//
//
// Created by Mathew Gacy on 12/3/23.
//

import Foundation
import PackagePlugin

extension PackagePlugin.Target {
var debugDescription: String {
if let sourceModuleTarget = self as? SourceModuleTarget {
return """
SourceModuleTarget(id: "\(id)", name: "\(name)", moduleName: "\(sourceModuleTarget.moduleName)", kind: ModuleKind.\(sourceModuleTarget.kind))
"""
} else {
return """
Target(id: "\(id)", name: "\(name)", directory: \(directory))
"""
}
}
}
59 changes: 55 additions & 4 deletions Plugins/VersionFile/VersionFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,37 @@
import Foundation
import PackagePlugin

/// Constants used by the VersionFile plugin.
enum Constants {
/// The name of the version file.
static let versionFile = "Version.swift"
/// A regular expression pattern for a semantic version number.
static let versionPattern = #"([0-9]+\.*)+"#
}

/// A semantic version release type.
enum Release: String, CaseIterable {
/// Increment the patch version.
case patch
/// Increment the minor version.
case minor
/// Increment the major version.
case major
/// Increment the pre-release version.
case release
/// Increment the pre-release version.
case prerelease = "prerel"
}

/// A VersionFile plugin command.
enum Command {
/// Bump a VersionFile with the given release type.
case bump(Release)
/// Create a VersionFile with the given version string.
case create(String)
}

/// The entry point of the VersionFile plugin.
@main
struct VersionFile: CommandPlugin {
/// This entry point is called when operating on a Swift package.
Expand All @@ -34,7 +47,9 @@ struct VersionFile: CommandPlugin {
arguments: [String]
) async throws {
if arguments.contains("--verbose") {
print("Command plugin execution with arguments \(arguments.description) for Swift package \(context.package.displayName). All target information: \(context.package.targets.description)")
let targetsDescription = context.package.targets.map(\.debugDescription).joined(separator: "\n - ")
let packageDescription = "`\(context.package.displayName)`.\nTargets:\n - \(targetsDescription)"
print("\nCommand plugin execution with arguments `\(arguments.description)` for Swift package \(packageDescription)\n")
}

var argExtractor = ArgumentExtractor(arguments)
Expand Down Expand Up @@ -68,6 +83,10 @@ struct VersionFile: CommandPlugin {
}

private extension VersionFile {
/// Extracts a ``Command`` from the given argument extractor and returns it.
///
/// - Parameter argExtractor: The argument extractor.
/// - Returns: The extracted command.
func extractCommand(from argExtractor: inout ArgumentExtractor) throws -> Command {
if let releaseString = argExtractor.extractOption(named: "bump").first {
guard let release = Release(rawValue: releaseString) else {
Expand All @@ -83,21 +102,36 @@ private extension VersionFile {
}
}

/// Returns the targets to process in the given package.
///
/// - Parameters:
/// - package: The package to process.
/// - selectedTargets: The names of the targets to process.
/// - Returns: The targets to process.
func targetsToProcess(in package: Package, selectedTargets: [String]) -> [SourceModuleTarget] {
var targetsToProcess: [Target] = package.targets
if selectedTargets.isEmpty == false {
targetsToProcess = package.targets.filter { selectedTargets.contains($0.name) }.map { $0 }
targetsToProcess = package.targets.filter { selectedTargets.contains($0.name) }
}

return targetsToProcess.compactMap { target in
guard let target = target as? SourceModuleTarget, case .generic = target.kind else {
guard let target = target as? SourceModuleTarget else {
return nil
}

return target
switch target.kind {
case .generic, .executable:
return target
case .test:
return nil
}
}
}

/// Returns the current version number from the version file at the given path.
///
/// - Parameter path: The path to the version file.
/// - Returns: The current version number.
func currentVersion(path: Path) throws -> String {
let fileContents = try String(contentsOfFile: path.string)

Expand All @@ -109,21 +143,38 @@ private extension VersionFile {
return versionString
}

/// Returns the contents of a version file for the given version number.
///
/// - Parameter version: The version number.
/// - Returns: The version file contents
func makeVersion(_ version: String) -> String {
"""
// This file was generated by the `VersionFile` package plugin.
/// Namespace for the current version of the target in which this file is contained.
enum Version {
/// The current version number.
static let number = "\(version)"
}
"""
}

/// Writes a version file with the given version number to the given path.
///
/// - Parameters:
/// - version: The version number.
/// - path: The path to the version file.
func writeVersionFile(_ version: String, in path: Path) throws {
let fileContents = makeVersion(version)
try fileContents.write(toFile: path.string, atomically: true, encoding: .utf8)
}

/// Runs the given tool with the given arguments and returns the output.
///
/// - Parameters:
/// - tool: The tool to run.
/// - arguments: The arguments to pass to the tool.
/// - Returns: The output of the tool.
func run(tool: PluginContext.Tool, with arguments: [String]) throws -> String {
let outputPipe = Pipe()

Expand Down

0 comments on commit b1f5cee

Please sign in to comment.