Skip to content

Commit 8eb2f1e

Browse files
committed
Remove bash from launch command
1 parent 5638f21 commit 8eb2f1e

File tree

2 files changed

+114
-120
lines changed

2 files changed

+114
-120
lines changed

Sources/ShellOut.swift

Lines changed: 72 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,17 @@ import Algorithms
3232
* For example: `shellOut(to: "mkdir", arguments: ["NewFolder"], at: "~/CurrentFolder")`
3333
*/
3434
@discardableResult public func shellOut(
35-
to command: SafeString,
36-
arguments: [Argument] = [],
35+
to command: String,
36+
arguments: [String] = [],
3737
at path: String = ".",
3838
logger: Logger? = nil,
3939
outputHandle: FileHandle? = nil,
4040
errorHandle: FileHandle? = nil,
4141
environment: [String : String]? = nil
4242
) async throws -> (stdout: String, stderr: String) {
43-
let command = "\(command) \(arguments.map(\.string).joined(separator: " "))"
44-
45-
return try await TSCBasic.Process.launchBash(
46-
with: command,
43+
try await TSCBasic.Process.launch(
44+
command: command,
45+
arguments: arguments,
4746
logger: logger,
4847
outputHandle: outputHandle,
4948
errorHandle: errorHandle,
@@ -95,58 +94,59 @@ import Algorithms
9594
/// Structure used to pre-define commands for use with ShellOut
9695
public struct ShellOutCommand {
9796
/// The string that makes up the command that should be run on the command line
98-
public var command: SafeString
97+
public var command: String
9998

100-
public var arguments: [Argument]
99+
public var arguments: [String]
101100

102101
/// Initialize a value using a string that makes up the underlying command
103-
public init(command: String, arguments: [Argument] = []) throws {
104-
self.init(command: try SafeString(command), arguments: arguments)
105-
}
106-
107-
public init(command: SafeString, arguments: [Argument] = []) {
102+
public init(command: String, arguments: [String] = []) {
108103
self.command = command
109104
self.arguments = arguments
110105
}
111106

112107
public var string: String {
113-
([command.value] + arguments.map(\.string))
114-
.joined(separator: " ")
108+
([command] + arguments).joined(separator: " ")
115109
}
116110

117-
public func appending(arguments newArguments: [Argument]) -> Self {
111+
public func appending(arguments newArguments: [String]) -> Self {
118112
.init(command: command, arguments: arguments + newArguments)
119113
}
120114

121-
public func appending(argument: Argument) -> Self {
115+
public func appending(argument: String) -> Self {
122116
appending(arguments: [argument])
123117
}
124118

125-
public mutating func append(arguments newArguments: [Argument]) {
119+
public mutating func append(arguments newArguments: [String]) {
126120
self.arguments = self.arguments + newArguments
127121
}
128122

129-
public mutating func append(argument: Argument) {
123+
public mutating func append(argument: String) {
130124
append(arguments: [argument])
131125
}
132126
}
133127

128+
public extension ShellOutCommand {
129+
static func bash(arguments: [Argument]) -> Self {
130+
.init(command: "bash", arguments: ["-c", arguments.map(\.string).joined(separator: " ")])
131+
}
132+
}
133+
134134
/// Git commands
135135
public extension ShellOutCommand {
136136
/// Initialize a git repository
137137
static func gitInit() -> ShellOutCommand {
138-
.init(command: "git".unchecked, arguments: ["init".verbatim])
138+
.init(command: "git", arguments: ["init"])
139139
}
140140

141141
/// Clone a git repository at a given URL
142142
static func gitClone(url: URL, to path: String? = nil, allowingPrompt: Bool = true, quiet: Bool = true) -> ShellOutCommand {
143143
var command = git(allowingPrompt: allowingPrompt)
144-
.appending(arguments: ["clone", url.absoluteString].quoted)
144+
.appending(arguments: ["clone", url.absoluteString])
145145

146-
path.map { command.append(argument: $0.quoted) }
146+
path.map { command.append(argument: $0) }
147147

148148
if quiet {
149-
command.append(argument: "--quiet".verbatim)
149+
command.append(argument: "--quiet")
150150
}
151151

152152
return command
@@ -155,11 +155,10 @@ public extension ShellOutCommand {
155155
/// Create a git commit with a given message (also adds all untracked file to the index)
156156
static func gitCommit(message: String, allowingPrompt: Bool = true, quiet: Bool = true) -> ShellOutCommand {
157157
var command = git(allowingPrompt: allowingPrompt)
158-
.appending(arguments: ["add . && git commit -a -m".verbatim])
159-
command.append(argument: message.quoted)
158+
.appending(arguments: ["commit", "-a", "-m", message.quoted.string])
160159

161160
if quiet {
162-
command.append(argument: "--quiet".verbatim)
161+
command.append(argument: "--quiet")
163162
}
164163

165164
return command
@@ -168,12 +167,12 @@ public extension ShellOutCommand {
168167
/// Perform a git push
169168
static func gitPush(remote: String? = nil, branch: String? = nil, allowingPrompt: Bool = true, quiet: Bool = true) -> ShellOutCommand {
170169
var command = git(allowingPrompt: allowingPrompt)
171-
.appending(arguments: ["push".verbatim])
172-
remote.map { command.append(argument: $0.verbatim) }
173-
branch.map { command.append(argument: $0.verbatim) }
170+
.appending(arguments: ["push"])
171+
remote.map { command.append(argument: $0) }
172+
branch.map { command.append(argument: $0) }
174173

175174
if quiet {
176-
command.append(argument: "--quiet".verbatim)
175+
command.append(argument: "--quiet")
177176
}
178177

179178
return command
@@ -182,12 +181,12 @@ public extension ShellOutCommand {
182181
/// Perform a git pull
183182
static func gitPull(remote: String? = nil, branch: String? = nil, allowingPrompt: Bool = true, quiet: Bool = true) -> ShellOutCommand {
184183
var command = git(allowingPrompt: allowingPrompt)
185-
.appending(arguments: ["pull".verbatim])
186-
remote.map { command.append(argument: $0.quoted) }
187-
branch.map { command.append(argument: $0.quoted) }
184+
.appending(arguments: ["pull"])
185+
remote.map { command.append(argument: $0) }
186+
branch.map { command.append(argument: $0) }
188187

189188
if quiet {
190-
command.append(argument: "--quiet".verbatim)
189+
command.append(argument: "--quiet")
191190
}
192191

193192
return command
@@ -196,40 +195,40 @@ public extension ShellOutCommand {
196195
/// Run a git submodule update
197196
static func gitSubmoduleUpdate(initializeIfNeeded: Bool = true, recursive: Bool = true, allowingPrompt: Bool = true, quiet: Bool = true) -> ShellOutCommand {
198197
var command = git(allowingPrompt: allowingPrompt)
199-
.appending(arguments: ["submodule update".verbatim])
198+
.appending(arguments: ["submodule update"])
200199

201200
if initializeIfNeeded {
202-
command.append(argument: "--init".verbatim)
201+
command.append(argument: "--init")
203202
}
204203

205204
if recursive {
206-
command.append(argument: "--recursive".verbatim)
205+
command.append(argument: "--recursive")
207206
}
208207

209208
if quiet {
210-
command.append(argument: "--quiet".verbatim)
209+
command.append(argument: "--quiet")
211210
}
212211

213212
return command
214213
}
215214

216215
/// Checkout a given git branch
217216
static func gitCheckout(branch: String, quiet: Bool = true) -> ShellOutCommand {
218-
var command = ShellOutCommand(command: "git".unchecked,
219-
arguments: ["checkout".verbatim, branch.quoted])
217+
var command = ShellOutCommand(command: "git",
218+
arguments: ["checkout", branch])
220219

221220
if quiet {
222-
command.append(argument: "--quiet".verbatim)
221+
command.append(argument: "--quiet")
223222
}
224223

225224
return command
226225
}
227226

228227
private static func git(allowingPrompt: Bool) -> Self {
229228
allowingPrompt
230-
? .init(command: "git".unchecked)
231-
: .init(command: "env".unchecked,
232-
arguments: ["GIT_TERMINAL_PROMPT=0", "git"].verbatim)
229+
? .init(command: "git")
230+
: .init(command: "env",
231+
arguments: ["GIT_TERMINAL_PROMPT=0", "git"])
233232

234233
}
235234
}
@@ -238,64 +237,62 @@ public extension ShellOutCommand {
238237
public extension ShellOutCommand {
239238
/// Create a folder with a given name
240239
static func createFolder(named name: String) -> ShellOutCommand {
241-
.init(command: "mkdir".unchecked, arguments: [name.quoted])
240+
.init(command: "mkdir", arguments: [name])
242241
}
243242

244243
/// Create a file with a given name and contents (will overwrite any existing file with the same name)
245244
static func createFile(named name: String, contents: String) -> ShellOutCommand {
246-
.init(command: "echo".unchecked, arguments: [contents.quoted])
247-
.appending(argument: ">".verbatim)
248-
.appending(argument: name.quoted)
245+
.init(command: "bash", arguments: ["-c", #"echo \#(contents.quoted) > \#(name.quoted)"#])
249246
}
250247

251248
/// Move a file from one path to another
252249
static func moveFile(from originPath: String, to targetPath: String) -> ShellOutCommand {
253-
.init(command: "mv".unchecked, arguments: [originPath, targetPath].quoted)
250+
.init(command: "mv", arguments: [originPath, targetPath])
254251
}
255252

256253
/// Copy a file from one path to another
257254
static func copyFile(from originPath: String, to targetPath: String) -> ShellOutCommand {
258-
.init(command: "cp".unchecked, arguments: [originPath, targetPath].quoted)
255+
.init(command: "cp", arguments: [originPath, targetPath])
259256
}
260257

261258
/// Remove a file
262259
static func removeFile(from path: String, arguments: [String] = ["-f"]) -> ShellOutCommand {
263-
.init(command: "rm".unchecked, arguments: arguments.quoted + [path.quoted])
260+
.init(command: "rm", arguments: arguments + [path])
264261
}
265262

266263
/// Open a file using its designated application
267264
static func openFile(at path: String) -> ShellOutCommand {
268-
.init(command: "open".unchecked, arguments: [path.quoted])
265+
.init(command: "open", arguments: [path])
269266
}
270267

271268
/// Read a file as a string
272269
static func readFile(at path: String) -> ShellOutCommand {
273-
.init(command: "cat".unchecked, arguments: [path.quoted])
270+
.init(command: "cat", arguments: [path])
274271
}
275272

276273
/// Create a symlink at a given path, to a given target
277274
static func createSymlink(to targetPath: String, at linkPath: String) -> ShellOutCommand {
278-
.init(command: "ln".unchecked, arguments: ["-s", targetPath, linkPath].quoted)
275+
.init(command: "ln", arguments: ["-s", targetPath, linkPath])
279276
}
280277

281278
/// Expand a symlink at a given path, returning its target path
282279
static func expandSymlink(at path: String) -> ShellOutCommand {
283-
.init(command: "readlink".unchecked, arguments: [path.quoted])
280+
.init(command: "readlink", arguments: [path])
284281
}
285282
}
286283

287284
/// Marathon commands
288285
public extension ShellOutCommand {
289286
/// Run a Marathon Swift script
290287
static func runMarathonScript(at path: String, arguments: [String] = []) -> ShellOutCommand {
291-
.init(command: "marathon".unchecked,
292-
arguments: ["run", path].quoted + arguments.quoted)
288+
.init(command: "marathon",
289+
arguments: ["run", path] + arguments)
293290
}
294291

295292
/// Update all Swift packages managed by Marathon
296293
static func updateMarathonPackages() -> ShellOutCommand {
297-
.init(command: "marathon".unchecked,
298-
arguments: ["update".verbatim])
294+
.init(command: "marathon",
295+
arguments: ["update"])
299296
}
300297
}
301298

@@ -315,46 +312,46 @@ public extension ShellOutCommand {
315312

316313
/// Create a Swift package with a given type (see SwiftPackageType for options)
317314
static func createSwiftPackage(withType type: SwiftPackageType = .library) -> ShellOutCommand {
318-
.init(command: "swift".unchecked,
319-
arguments: ["package init --type \(type)".verbatim])
315+
.init(command: "swift",
316+
arguments: ["package init --type \(type)"])
320317
}
321318

322319
/// Update all Swift package dependencies
323320
static func updateSwiftPackages() -> ShellOutCommand {
324-
.init(command: "swift".unchecked, arguments: ["package", "update"].verbatim)
321+
.init(command: "swift", arguments: ["package", "update"])
325322
}
326323

327324
/// Build a Swift package using a given configuration (see SwiftBuildConfiguration for options)
328325
static func buildSwiftPackage(withConfiguration configuration: SwiftBuildConfiguration = .debug) -> ShellOutCommand {
329-
.init(command: "swift".unchecked,
330-
arguments: ["build -c \(configuration)".verbatim])
326+
.init(command: "swift",
327+
arguments: ["build -c \(configuration)"])
331328
}
332329

333330
/// Test a Swift package using a given configuration (see SwiftBuildConfiguration for options)
334331
static func testSwiftPackage(withConfiguration configuration: SwiftBuildConfiguration = .debug) -> ShellOutCommand {
335-
.init(command: "swift".unchecked,
336-
arguments: ["test -c \(configuration)".verbatim])
332+
.init(command: "swift",
333+
arguments: ["test -c \(configuration)"])
337334
}
338335
}
339336

340337
/// Fastlane commands
341338
public extension ShellOutCommand {
342339
/// Run Fastlane using a given lane
343340
static func runFastlane(usingLane lane: String) -> ShellOutCommand {
344-
.init(command: "fastlane".unchecked, arguments: [lane.quoted])
341+
.init(command: "fastlane", arguments: [lane])
345342
}
346343
}
347344

348345
/// CocoaPods commands
349346
public extension ShellOutCommand {
350347
/// Update all CocoaPods dependencies
351348
static func updateCocoaPods() -> ShellOutCommand {
352-
.init(command: "pod".unchecked, arguments: ["update".verbatim])
349+
.init(command: "pod", arguments: ["update"])
353350
}
354351

355352
/// Install all CocoaPods dependencies
356353
static func installCocoaPods() -> ShellOutCommand {
357-
.init(command: "pod".unchecked, arguments: ["install".verbatim])
354+
.init(command: "pod", arguments: ["install"])
358355
}
359356
}
360357

@@ -399,16 +396,19 @@ extension ShellOutCommand {
399396
// MARK: - Private
400397

401398
private extension TSCBasic.Process {
402-
@discardableResult static func launchBash(
403-
with command: String,
399+
@discardableResult static func launch(
400+
command: String,
401+
arguments: [String],
404402
logger: Logger? = nil,
405403
outputHandle: FileHandle? = nil,
406404
errorHandle: FileHandle? = nil,
407405
environment: [String : String]? = nil,
408406
at: String? = nil
409407
) async throws -> (stdout: String, stderr: String) {
408+
print("command:", command)
409+
print("arguments:", arguments)
410410
let process = try Self.init(
411-
arguments: ["/bin/bash", "-c", command],
411+
arguments: [command] + arguments,
412412
environment: environment ?? ProcessEnv.vars,
413413
workingDirectory: at.map { try .init(validating: $0) } ?? TSCBasic.localFileSystem.currentWorkingDirectory ?? .root,
414414
outputRedirection: .collect(redirectStderr: false),

0 commit comments

Comments
 (0)