Skip to content

Commit 7238f73

Browse files
committed
Break ShellOut components into individual files
1 parent 576c8bd commit 7238f73

File tree

4 files changed

+244
-238
lines changed

4 files changed

+244
-238
lines changed

Sources/ShellOut.swift

Lines changed: 0 additions & 238 deletions
Original file line numberDiff line numberDiff line change
@@ -90,232 +90,6 @@ import Algorithms
9090
}
9191

9292

93-
public extension ShellOutCommand {
94-
static func bash(arguments: [Argument]) -> Self {
95-
let arguments = arguments.first == "-c" ? Array(arguments.dropFirst()) : arguments
96-
return .init(command: "bash", arguments: ["-c", arguments.map(\.description).joined(separator: " ")])
97-
}
98-
}
99-
100-
/// Git commands
101-
public extension ShellOutCommand {
102-
/// Initialize a git repository
103-
static func gitInit() -> ShellOutCommand {
104-
.init(command: "git", arguments: ["init"])
105-
}
106-
107-
/// Clone a git repository at a given URL
108-
static func gitClone(url: URL, to path: String? = nil, allowingPrompt: Bool = true, quiet: Bool = true) -> ShellOutCommand {
109-
var command = git(allowingPrompt: allowingPrompt)
110-
.appending(arguments: ["clone", url.absoluteString])
111-
112-
path.map { command.append(argument: $0) }
113-
114-
if quiet {
115-
command.append(argument: "--quiet")
116-
}
117-
118-
return command
119-
}
120-
121-
/// Create a git commit with a given message (also adds all untracked file to the index)
122-
static func gitCommit(message: String, allowingPrompt: Bool = true, quiet: Bool = true) -> ShellOutCommand {
123-
var command = git(allowingPrompt: allowingPrompt)
124-
.appending(arguments: ["commit", "-a", "-m", "\(message.quoted)"])
125-
126-
if quiet {
127-
command.append(argument: "--quiet")
128-
}
129-
130-
return command
131-
}
132-
133-
/// Perform a git push
134-
static func gitPush(remote: String? = nil, branch: String? = nil, allowingPrompt: Bool = true, quiet: Bool = true) -> ShellOutCommand {
135-
var command = git(allowingPrompt: allowingPrompt)
136-
.appending(arguments: ["push"])
137-
remote.map { command.append(argument: $0) }
138-
branch.map { command.append(argument: $0) }
139-
140-
if quiet {
141-
command.append(argument: "--quiet")
142-
}
143-
144-
return command
145-
}
146-
147-
/// Perform a git pull
148-
static func gitPull(remote: String? = nil, branch: String? = nil, allowingPrompt: Bool = true, quiet: Bool = true) -> ShellOutCommand {
149-
var command = git(allowingPrompt: allowingPrompt)
150-
.appending(arguments: ["pull"])
151-
remote.map { command.append(argument: $0) }
152-
branch.map { command.append(argument: $0) }
153-
154-
if quiet {
155-
command.append(argument: "--quiet")
156-
}
157-
158-
return command
159-
}
160-
161-
/// Run a git submodule update
162-
static func gitSubmoduleUpdate(initializeIfNeeded: Bool = true, recursive: Bool = true, allowingPrompt: Bool = true, quiet: Bool = true) -> ShellOutCommand {
163-
var command = git(allowingPrompt: allowingPrompt)
164-
.appending(arguments: ["submodule update"])
165-
166-
if initializeIfNeeded {
167-
command.append(argument: "--init")
168-
}
169-
170-
if recursive {
171-
command.append(argument: "--recursive")
172-
}
173-
174-
if quiet {
175-
command.append(argument: "--quiet")
176-
}
177-
178-
return command
179-
}
180-
181-
/// Checkout a given git branch
182-
static func gitCheckout(branch: String, quiet: Bool = true) -> ShellOutCommand {
183-
var command = ShellOutCommand(command: "git",
184-
arguments: ["checkout", branch])
185-
186-
if quiet {
187-
command.append(argument: "--quiet")
188-
}
189-
190-
return command
191-
}
192-
193-
private static func git(allowingPrompt: Bool) -> Self {
194-
allowingPrompt
195-
? .init(command: "git")
196-
: .init(command: "env",
197-
arguments: ["GIT_TERMINAL_PROMPT=0", "git"])
198-
199-
}
200-
}
201-
202-
/// File system commands
203-
public extension ShellOutCommand {
204-
/// Create a folder with a given name
205-
static func createFolder(named name: String) -> ShellOutCommand {
206-
.init(command: "mkdir", arguments: [name])
207-
}
208-
209-
/// Create a file with a given name and contents (will overwrite any existing file with the same name)
210-
static func createFile(named name: String, contents: String) -> ShellOutCommand {
211-
.bash(arguments: ["-c", #"echo \#(contents.quoted) > \#(name.quoted)"#.verbatim])
212-
}
213-
214-
/// Move a file from one path to another
215-
static func moveFile(from originPath: String, to targetPath: String) -> ShellOutCommand {
216-
.init(command: "mv", arguments: [originPath, targetPath])
217-
}
218-
219-
/// Copy a file from one path to another
220-
static func copyFile(from originPath: String, to targetPath: String) -> ShellOutCommand {
221-
.init(command: "cp", arguments: [originPath, targetPath])
222-
}
223-
224-
/// Remove a file
225-
static func removeFile(from path: String, arguments: [String] = ["-f"]) -> ShellOutCommand {
226-
.init(command: "rm", arguments: arguments + [path])
227-
}
228-
229-
/// Open a file using its designated application
230-
static func openFile(at path: String) -> ShellOutCommand {
231-
.init(command: "open", arguments: [path])
232-
}
233-
234-
/// Read a file as a string
235-
static func readFile(at path: String) -> ShellOutCommand {
236-
.init(command: "cat", arguments: [path])
237-
}
238-
239-
/// Create a symlink at a given path, to a given target
240-
static func createSymlink(to targetPath: String, at linkPath: String) -> ShellOutCommand {
241-
.init(command: "ln", arguments: ["-s", targetPath, linkPath])
242-
}
243-
244-
/// Expand a symlink at a given path, returning its target path
245-
static func expandSymlink(at path: String) -> ShellOutCommand {
246-
.init(command: "readlink", arguments: [path])
247-
}
248-
}
249-
250-
/// Swift Package Manager commands
251-
public extension ShellOutCommand {
252-
/// Enum defining available package types when using the Swift Package Manager
253-
enum SwiftPackageType: String {
254-
case library
255-
case executable
256-
}
257-
258-
/// Enum defining available build configurations when using the Swift Package Manager
259-
enum SwiftBuildConfiguration: String {
260-
case debug
261-
case release
262-
}
263-
264-
/// Create a Swift package with a given type (see SwiftPackageType for options)
265-
static func createSwiftPackage(withType type: SwiftPackageType = .library) -> ShellOutCommand {
266-
.init(command: "swift",
267-
arguments: ["package", "init", "--type", "\(type)"])
268-
}
269-
270-
/// Update all Swift package dependencies
271-
static func updateSwiftPackages() -> ShellOutCommand {
272-
.init(command: "swift", arguments: ["package", "update"])
273-
}
274-
275-
/// Build a Swift package using a given configuration (see SwiftBuildConfiguration for options)
276-
static func buildSwiftPackage(withConfiguration configuration: SwiftBuildConfiguration = .debug) -> ShellOutCommand {
277-
.init(command: "swift",
278-
arguments: ["build -c \(configuration)"])
279-
}
280-
281-
/// Test a Swift package using a given configuration (see SwiftBuildConfiguration for options)
282-
static func testSwiftPackage(withConfiguration configuration: SwiftBuildConfiguration = .debug) -> ShellOutCommand {
283-
.init(command: "swift",
284-
arguments: ["test", "-c", "\(configuration)"])
285-
}
286-
}
287-
288-
/// Error type thrown by the `shellOut()` function, in case the given command failed
289-
public struct ShellOutError: Swift.Error {
290-
/// The termination status of the command that was run
291-
public let terminationStatus: Int32
292-
/// The error message as a UTF8 string, as returned through `STDERR`
293-
public var message: String { return errorData.shellOutput() }
294-
/// The raw error buffer data, as returned through `STDERR`
295-
public let errorData: Data
296-
/// The raw output buffer data, as retuned through `STDOUT`
297-
public let outputData: Data
298-
/// The output of the command as a UTF8 string, as returned through `STDOUT`
299-
public var output: String { return outputData.shellOutput() }
300-
}
301-
302-
extension ShellOutError: CustomStringConvertible {
303-
public var description: String {
304-
return """
305-
ShellOut encountered an error
306-
Status code: \(terminationStatus)
307-
Message: "\(message)"
308-
Output: "\(output)"
309-
"""
310-
}
311-
}
312-
313-
extension ShellOutError: LocalizedError {
314-
public var errorDescription: String? {
315-
return description
316-
}
317-
}
318-
31993
// MARK: - Private
32094

32195
private extension TSCBasic.Process {
@@ -365,15 +139,3 @@ private extension TSCBasic.Process {
365139
}
366140
}
367141

368-
private extension Data {
369-
func shellOutput() -> String {
370-
let output = String(decoding: self, as: UTF8.self)
371-
372-
guard !output.hasSuffix("\n") else {
373-
return String(output.dropLast())
374-
}
375-
376-
return output
377-
378-
}
379-
}

Sources/ShellOutCommand+git.swift

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import Foundation
2+
3+
4+
/// Git commands
5+
public extension ShellOutCommand {
6+
/// Initialize a git repository
7+
static func gitInit() -> ShellOutCommand {
8+
.init(command: "git", arguments: ["init"])
9+
}
10+
11+
/// Clone a git repository at a given URL
12+
static func gitClone(url: URL, to path: String? = nil, allowingPrompt: Bool = true, quiet: Bool = true) -> ShellOutCommand {
13+
var command = git(allowingPrompt: allowingPrompt)
14+
.appending(arguments: ["clone", url.absoluteString])
15+
16+
path.map { command.append(argument: $0) }
17+
18+
if quiet {
19+
command.append(argument: "--quiet")
20+
}
21+
22+
return command
23+
}
24+
25+
/// Create a git commit with a given message (also adds all untracked file to the index)
26+
static func gitCommit(message: String, allowingPrompt: Bool = true, quiet: Bool = true) -> ShellOutCommand {
27+
var command = git(allowingPrompt: allowingPrompt)
28+
.appending(arguments: ["commit", "-a", "-m", "\(message.quoted)"])
29+
30+
if quiet {
31+
command.append(argument: "--quiet")
32+
}
33+
34+
return command
35+
}
36+
37+
/// Perform a git push
38+
static func gitPush(remote: String? = nil, branch: String? = nil, allowingPrompt: Bool = true, quiet: Bool = true) -> ShellOutCommand {
39+
var command = git(allowingPrompt: allowingPrompt)
40+
.appending(arguments: ["push"])
41+
remote.map { command.append(argument: $0) }
42+
branch.map { command.append(argument: $0) }
43+
44+
if quiet {
45+
command.append(argument: "--quiet")
46+
}
47+
48+
return command
49+
}
50+
51+
/// Perform a git pull
52+
static func gitPull(remote: String? = nil, branch: String? = nil, allowingPrompt: Bool = true, quiet: Bool = true) -> ShellOutCommand {
53+
var command = git(allowingPrompt: allowingPrompt)
54+
.appending(arguments: ["pull"])
55+
remote.map { command.append(argument: $0) }
56+
branch.map { command.append(argument: $0) }
57+
58+
if quiet {
59+
command.append(argument: "--quiet")
60+
}
61+
62+
return command
63+
}
64+
65+
/// Run a git submodule update
66+
static func gitSubmoduleUpdate(initializeIfNeeded: Bool = true, recursive: Bool = true, allowingPrompt: Bool = true, quiet: Bool = true) -> ShellOutCommand {
67+
var command = git(allowingPrompt: allowingPrompt)
68+
.appending(arguments: ["submodule update"])
69+
70+
if initializeIfNeeded {
71+
command.append(argument: "--init")
72+
}
73+
74+
if recursive {
75+
command.append(argument: "--recursive")
76+
}
77+
78+
if quiet {
79+
command.append(argument: "--quiet")
80+
}
81+
82+
return command
83+
}
84+
85+
/// Checkout a given git branch
86+
static func gitCheckout(branch: String, quiet: Bool = true) -> ShellOutCommand {
87+
var command = ShellOutCommand(command: "git",
88+
arguments: ["checkout", branch])
89+
90+
if quiet {
91+
command.append(argument: "--quiet")
92+
}
93+
94+
return command
95+
}
96+
97+
private static func git(allowingPrompt: Bool) -> Self {
98+
allowingPrompt
99+
? .init(command: "git")
100+
: .init(command: "env",
101+
arguments: ["GIT_TERMINAL_PROMPT=0", "git"])
102+
103+
}
104+
}

0 commit comments

Comments
 (0)