Skip to content

Commit 16a9a29

Browse files
authored
Merge pull request #8 from p-x9/feature/command-plugin
Command Plugin
2 parents 356045a + b9bdede commit 16a9a29

File tree

3 files changed

+126
-0
lines changed

3 files changed

+126
-0
lines changed

Package.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ let package = Package(
99
name: "RunScriptPlugin",
1010
targets: ["RunScriptPlugin"]
1111
),
12+
.plugin(
13+
name: "RunScriptCommandPlugin",
14+
targets: ["RunScriptCommandPlugin"]
15+
),
1216
.executable(
1317
name: "run-script",
1418
targets: ["run-script"]
@@ -39,6 +43,21 @@ let package = Package(
3943
dependencies: [
4044
"run-script-bin"
4145
]
46+
),
47+
.plugin(
48+
name: "RunScriptCommandPlugin",
49+
capability: .command(
50+
intent: .custom(
51+
verb: "run script",
52+
description: "run scripts defined in `runscript.yml`"
53+
),
54+
permissions: [
55+
.writeToPackageDirectory(reason: "to run scripts defined in `runscript.yml`")
56+
]
57+
),
58+
dependencies: [
59+
"run-script-bin"
60+
]
4261
)
4362
]
4463
)
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//
2+
// plugin.swift
3+
//
4+
//
5+
// Created by p-x9 on 2023/03/21.
6+
//
7+
8+
import Foundation
9+
import PackagePlugin
10+
11+
@main
12+
struct RunScriptCommandPlugin: CommandPlugin {
13+
func performCommand(context: PackagePlugin.PluginContext, arguments: [String]) async throws {
14+
try performCommand(
15+
packageDirectory: context.package.directory,
16+
tool: try context.tool(named: "run-script-bin"),
17+
arguments: arguments
18+
)
19+
}
20+
21+
private func performCommand(
22+
packageDirectory: Path,
23+
tool: PluginContext.Tool,
24+
arguments: [String]
25+
) throws {
26+
var argumentExtractor = ArgumentExtractor(arguments)
27+
let config = argumentExtractor.extractOption(named: "config").first
28+
?? packageDirectory.firstConfigurationFileInParentDirectories()?.string ?? ""
29+
let timing = argumentExtractor.extractOption(named: "timing").first ?? "command"
30+
31+
let process = Process()
32+
process.launchPath = tool.path.string
33+
process.arguments = [
34+
"--config",
35+
config,
36+
"--timing",
37+
timing
38+
]
39+
40+
try process.run()
41+
process.waitUntilExit()
42+
}
43+
}
44+
45+
#if canImport(XcodeProjectPlugin)
46+
import XcodeProjectPlugin
47+
48+
extension RunScriptCommandPlugin: XcodeCommandPlugin {
49+
func performCommand(context: XcodeProjectPlugin.XcodePluginContext, arguments: [String]) throws {
50+
try performCommand(
51+
packageDirectory: context.xcodeProject.directory,
52+
tool: try context.tool(named: "run-script-bin"),
53+
arguments: arguments
54+
)
55+
}
56+
}
57+
#endif
58+
59+
// ref: https://github.com/realm/SwiftLint/blob/main/Plugins/SwiftLintPlugin/Path%2BHelpers.swift
60+
extension Path {
61+
func firstConfigurationFileInParentDirectories() -> Path? {
62+
let defaultConfigurationFileNames = [
63+
"runscript.yml",
64+
".runscript.yml"
65+
]
66+
let proposedDirectories = sequence(
67+
first: self,
68+
next: { path in
69+
guard path.stem.count > 1 else {
70+
// Check we're not at the root of this filesystem, as `removingLastComponent()`
71+
// will continually return the root from itself.
72+
return nil
73+
}
74+
75+
return path.removingLastComponent()
76+
}
77+
)
78+
79+
for proposedDirectory in proposedDirectories {
80+
for fileName in defaultConfigurationFileNames {
81+
let potentialConfigurationFile = proposedDirectory.appending(subpath: fileName)
82+
if potentialConfigurationFile.isAccessible() {
83+
return potentialConfigurationFile
84+
}
85+
}
86+
}
87+
return nil
88+
}
89+
90+
/// Safe way to check if the file is accessible from within the current process sandbox.
91+
private func isAccessible() -> Bool {
92+
let result = string.withCString { pointer in
93+
access(pointer, R_OK)
94+
}
95+
96+
return result == 0
97+
}
98+
}

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
SwiftPackage Plugin for executing arbitrary ShellScript.
44

5+
## Feature
6+
- BuildToolPlugin: RunScriptPlugin
7+
- CommandPlugin: RunScriptCommandPlugin
8+
- XcodeBuildToolPlugin: RunScriptPlugin
9+
- XcodeCommandPlugin: RunScriptCommandPlugin
510

611
## Usage
712
Place the file named `runscript.yml`(or `.runscript.yml`) in the root of the project.
@@ -35,6 +40,10 @@ build: # build Command
3540
- name: "Hello"
3641
script: "echo Hello"
3742

43+
command: # Command Plugin
44+
- name: "Hello from Command"
45+
script: "echo 'Hello from Command'"
46+
3847
all: # run in `prebuild`, `build`...
3948
- name: "Hello(all)"
4049
script: "echo Hello(all)"

0 commit comments

Comments
 (0)