Skip to content

Commit

Permalink
Add RunXCResourcePlugin
Browse files Browse the repository at this point in the history
  • Loading branch information
nearfri committed Mar 3, 2024
1 parent 5f2214b commit ff4b8f8
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 374 deletions.
20 changes: 17 additions & 3 deletions Package.swift
Expand Up @@ -6,9 +6,9 @@ import Foundation

let package = Package(
name: "XCResource",
defaultLocalization: "en",
platforms: [.macOS(.v13)],
products: [
.plugin(name: "RunXCResource", targets: ["RunXCResource"]),
.executable(name: "xcresource-bin", targets: ["xcresource"]),
.executable(name: "xcresource", targets: ["XCResourceCLI"]),
.library(name: "XCResourceCommand", targets: ["XCResourceCommand"]),
Expand All @@ -34,13 +34,27 @@ let package = Package(
checksum: "282d450a5c22d7f61b11f955aeacf651db60ddf574746eb4960409e5df9c0e5f"
),

// MARK: - Plugins

.plugin(
name: "RunXCResource",
capability: .command(
intent: .custom(
verb: "run-xcresource",
description: "Run XCResource to generate symbols for assets or strings."),
permissions: [
.writeToPackageDirectory(
reason: "Write symbol files in the package direcotry")
]),
dependencies: ["xcresource"]),

// MARK: - Executables

.executableTarget(
name: "XCResourceCLI",
dependencies: ["XCResourceCommand"]),

// MARK: - Command Library
// MARK: - Command Module

.target(
name: "XCResourceCommand",
Expand All @@ -55,7 +69,7 @@ let package = Package(
.product(name: "ArgumentParser", package: "swift-argument-parser"),
]),

// MARK: - Core Libraries
// MARK: - Core Modules

.target(
name: "AssetKeyGen",
Expand Down
59 changes: 59 additions & 0 deletions Plugins/RunXCResource/PluginContext.Tool+.swift
@@ -0,0 +1,59 @@
import Foundation
import PackagePlugin

extension PluginContext.Tool {
func execute(arguments: [String]) async throws {
let process = Process()
process.executableURL = URL(fileURLWithPath: path.string)
process.arguments = arguments

try await withTaskCancellationHandler {
try await withCheckedThrowingContinuation { continuation in
DispatchQueue.global(qos: .userInitiated).async {
do {
try process.run()
process.waitUntilExit()
try process.validateTermination()

continuation.resume()
} catch {
continuation.resume(throwing: error)
}
}
}
} onCancel: {
process.terminate()
}
}
}

private extension Process {
func validateTermination() throws {
guard let toolName = executableURL?.lastPathComponent else { preconditionFailure() }

guard terminationReason == .exit, terminationStatus == 0 else {
throw PluginError.toolRunFailed(
name: toolName,
reason: terminationReason,
status: terminationStatus)
}
}
}

enum PluginError: LocalizedError, CustomStringConvertible {
case toolRunFailed(name: String, reason: Process.TerminationReason, status: Int32)

var description: String {
switch self {
case let .toolRunFailed(name, reason, status):
return """
'\(name)' invocation failed with exit code '\(status)' \
and reason '\(reason.rawValue)'.
"""
}
}

var errorDescription: String? {
return description
}
}
55 changes: 55 additions & 0 deletions Plugins/RunXCResource/RunXCResourcePlugin.swift
@@ -0,0 +1,55 @@
import Foundation
import PackagePlugin

private enum OptionName {
static let manifestPath: String = "manifest-path"
}

@main
struct RunXCResourcePlugin: CommandPlugin {
func performCommand(context: PluginContext, arguments: [String]) async throws {
let tool = try context.tool(named: "xcresource")

let toolArguments = toolArguments(context: context, pluginArguments: arguments)

try await tool.execute(arguments: toolArguments)
}

private func toolArguments(context: PluginContext, pluginArguments: [String]) -> [String] {
var result: [String] = []

var argExtractor = ArgumentExtractor(pluginArguments)

func appendManifestPath(_ manifestPath: String) {
result.append(contentsOf: ["--\(OptionName.manifestPath)", manifestPath])
}

if let manifestPath = argExtractor.extractOption(named: OptionName.manifestPath).first {
appendManifestPath(manifestPath)
} else if let manifestPath = manifestPath(inDirectory: context.package.directory) {
appendManifestPath(manifestPath)
}

return result
}

private func manifestPath(inDirectory directory: Path) -> String? {
let filename = "xcresource.json"

let candidates: [String] = [
"Configs/\(filename)",
"Scripts/\(filename)",
]

for candidate in candidates {
let path = directory.appending(subpath: candidate)
let url = URL(fileURLWithPath: path.string)

if (try? url.checkResourceIsReachable()) ?? false {
return path.string
}
}

return nil
}
}
@@ -0,0 +1,41 @@
{
"pins" : [
{
"identity" : "strix",
"kind" : "remoteSourceControl",
"location" : "https://github.com/nearfri/Strix",
"state" : {
"revision" : "2e309dbea51da14c4ba74b3abb3debb8ea4a7529",
"version" : "2.4.5"
}
},
{
"identity" : "swift-argument-parser",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser",
"state" : {
"revision" : "c8ed701b513cf5177118a175d85fbbbcd707ab41",
"version" : "1.3.0"
}
},
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections",
"state" : {
"revision" : "94cf62b3ba8d4bed62680a282d4c25f9c63c2efb",
"version" : "1.1.0"
}
},
{
"identity" : "swift-syntax",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-syntax",
"state" : {
"revision" : "64889f0c732f210a935a0ad7cda38f77f876262d",
"version" : "509.1.1"
}
}
],
"version" : 2
}
82 changes: 6 additions & 76 deletions Samples/XCResourceSample/XCResourceSampleLib/Package.swift
Expand Up @@ -8,99 +8,29 @@ let package = Package(
defaultLocalization: "en",
platforms: [.iOS(.v15), .macCatalyst(.v15), .macOS(.v12)],
products: [
.library(
name: "XCResourceSampleLib",
targets: ["View", "Resource"]),
.plugin(
name: "StringsToSwiftPlugin",
targets: ["StringsToSwiftPlugin"]),
.plugin(
name: "StringsToCSVPlugin",
targets: ["StringsToCSVPlugin"]),
.plugin(
name: "CSVToStringsPlugin",
targets: ["CSVToStringsPlugin"]),
.library(name: "XCResourceSampleLib", targets: ["View", "Resource"]),
],
dependencies: [
// .package(url: /* package url */, from: "1.0.0"),
.package(path: "../../../"),
],
targets: [
// MARK: - View
// MARK: - Core Modules

.target(
name: "View",
dependencies: ["Resource"]),

// MARK: - Resource

.target(
name: "Resource",
dependencies: [],
resources: [.copy("Resources/Fonts")],
plugins: [.plugin(name: "XCResourcePlugin")]),
plugins: []),

// MARK: - Tests

.testTarget(
name: "ResourceTests",
dependencies: ["Resource"]),

// MARK: - XCResourcePlugin

.plugin(
name: "XCResourcePlugin",
capability: .buildTool(),
dependencies: ["xcresource"]),

// MARK: - StringsToSwiftPlugin

.plugin(
name: "StringsToSwiftPlugin",
capability: .command(
intent: .custom(verb: "strings2swift", description: "Convert strings to swift"),
permissions: [
.writeToPackageDirectory(reason: "Converts strings to swift")
]),
dependencies: ["xcresource"]),

// MARK: - StringsdictToSwiftPlugin

.plugin(
name: "StringsdictToSwiftPlugin",
capability: .command(
intent: .custom(verb: "stringsdict2swift",
description: "Convert stringsdict to swift"),
permissions: [
.writeToPackageDirectory(reason: "Converts stringsdict to swift")
]),
dependencies: ["xcresource"]),

// MARK: - StringsToCSVPlugin

.plugin(
name: "StringsToCSVPlugin",
capability: .command(
intent: .custom(verb: "strings2csv", description: "Convert strings to csv"),
permissions: [
.writeToPackageDirectory(reason: "Converts strings to csv")
]),
dependencies: ["xcresource"]),

// MARK: - CSVToStringsPlugin

.plugin(
name: "CSVToStringsPlugin",
capability: .command(
intent: .custom(verb: "csv2strings", description: "Convert csv to strings"),
permissions: [
.writeToPackageDirectory(reason: "Converts csv to strings")
]),
dependencies: ["xcresource"]),

// MARK: - xcresource

.binaryTarget(
name: "xcresource",
url: "https://github.com/nearfri/XCResource/releases/download/0.9.25/xcresource.artifactbundle.zip",
checksum: "b4a297dea6b6c8df93dc7149d7d548e38ec699cdcfd2477b33c013da52fd7249"
),
]
)

This file was deleted.

0 comments on commit ff4b8f8

Please sign in to comment.