@@ -75,6 +75,7 @@ public struct SwiftScriptTool: ParsableCommand {
75
75
Clean . self,
76
76
Reset . self,
77
77
Resolve . self,
78
+ List . self,
78
79
] ,
79
80
helpNames: [ . short, . long, . customLong( " help " , withSingleDash: true ) ] )
80
81
@@ -138,7 +139,10 @@ extension SwiftScriptTool {
138
139
139
140
@OptionGroup ( )
140
141
var options : ScriptToolOptions
141
-
142
+
143
+ @Option ( name: . shortAndLong, help: " Save the prebuilt script binary " , transform: AbsolutePath . init)
144
+ var output : AbsolutePath ?
145
+
142
146
func run( _ swiftTool: SwiftTool , as productName: String , at cacheDirPath: AbsolutePath ) throws {
143
147
swiftTool. redirectStdoutToStderr ( )
144
148
swiftTool. diagnostics. emit ( note: " Using cache: \( cacheDirPath. basename) " )
@@ -148,6 +152,15 @@ extension SwiftScriptTool {
148
152
if options. shouldBuild {
149
153
try buildSystem. build ( subset: . product( productName) )
150
154
}
155
+
156
+ if let output = output {
157
+ let executablePath = try swiftTool. buildParameters ( ) . buildPath. appending ( component: productName)
158
+ guard !localFileSystem. isDirectory ( output) else {
159
+ throw ScriptError . isDirectory ( output. pathString)
160
+ }
161
+ try ? localFileSystem. removeFileTree ( output)
162
+ try localFileSystem. copy ( from: executablePath, to: output)
163
+ }
151
164
} catch let error as ScriptError {
152
165
swiftTool. diagnostics. emit ( error)
153
166
throw ExitCode . failure
@@ -238,6 +251,35 @@ extension SwiftScriptTool {
238
251
}
239
252
}
240
253
254
+ extension SwiftScriptTool {
255
+ struct List : ParsableCommand {
256
+ static let configuration = CommandConfiguration (
257
+ abstract: " List script caches " )
258
+
259
+ @OptionGroup ( _hiddenFromHelp: true )
260
+ var swiftOptions : SwiftToolOptions
261
+
262
+ func run( ) throws {
263
+ let cacheDir = try localFileSystem. getOrCreateSwiftScriptCacheDirectory ( )
264
+ let scripts = try localFileSystem. getDirectoryContents ( cacheDir)
265
+ let resolved = try scripts. map { script -> ( String , AbsolutePath ) in
266
+ let sourceDir = cacheDir. appending ( components: script, " Sources " )
267
+ guard localFileSystem. isDirectory ( sourceDir) ,
268
+ let name = try localFileSystem. getDirectoryContents ( sourceDir) . first,
269
+ case let realpath = resolveSymlinks ( sourceDir. appending ( components: name, " main.swift " ) ) else {
270
+ throw Diagnostics . fatalError
271
+ }
272
+ return ( script, realpath)
273
+ }
274
+ print ( " \( scripts. count) script \( scripts. count > 1 ? " s " : " " ) cached at \( cacheDir) " )
275
+ guard let maxLength = resolved. map ( \. 0 . count) . max ( ) else { return }
276
+ resolved. forEach { ( name, path) in
277
+ print ( name + String( repeating: " " , count: maxLength - name. count + 2 ) + path. pathString)
278
+ }
279
+ }
280
+ }
281
+ }
282
+
241
283
extension SwiftScriptTool {
242
284
struct ResolveOptions : ParsableArguments {
243
285
@Option ( help: " The version to resolve at " , transform: { Version ( string: $0) } )
0 commit comments