Skip to content

Commit 239f860

Browse files
committed
Merge branch 'make-strings-type-safe' into safe-api
2 parents 5dac4b0 + e14c634 commit 239f860

File tree

5 files changed

+215
-113
lines changed

5 files changed

+215
-113
lines changed

Sources/Argument.swift

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
public enum Argument {
2+
case safe(SafeString)
3+
case quoted(QuotedString)
4+
case verbatim(String)
5+
6+
init(safe string: String) throws {
7+
self = try .safe(.init(string))
8+
}
9+
10+
init(_ string: SafeString) {
11+
self = .safe(string)
12+
}
13+
14+
init(quoted string: String) {
15+
self = .quoted(.init(string))
16+
}
17+
18+
init(verbatim string: String) {
19+
self = .verbatim(string)
20+
}
21+
22+
var string: String {
23+
switch self {
24+
case let .safe(value):
25+
return value.value
26+
case let .quoted(value):
27+
return value.quoted
28+
case let .verbatim(string):
29+
return string
30+
}
31+
}
32+
}
33+
34+
35+
extension String {
36+
var quoted: Argument { .init(quoted: self) }
37+
var verbatim: Argument { .init(verbatim: self) }
38+
}
39+
40+
41+
extension Array<String> {
42+
var quoted: [Argument] { map(\.quoted) }
43+
44+
@available(*, deprecated)
45+
func safe() throws -> [Argument] { try map(Argument.init(safe:)) }
46+
47+
var verbatim: [Argument] { map(\.verbatim) }
48+
}

Sources/QuotedString.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import ShellQuote
2+
3+
4+
public struct QuotedString {
5+
public var unquoted: String
6+
public var quoted: String
7+
8+
public init(_ value: String) {
9+
self.unquoted = value
10+
self.quoted = ShellQuote.quote(value)
11+
}
12+
}
13+
14+
15+
extension QuotedString: CustomStringConvertible {
16+
public var description: String { quoted }
17+
}

Sources/SafeString.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import ShellQuote
2+
3+
4+
public struct SafeString {
5+
public var value: String
6+
7+
public init(_ value: String) throws {
8+
guard !ShellQuote.hasUnsafeContent(value) else {
9+
throw ShellOutCommand.Error(message: "Command must not contain characters that require quoting, was: \(value)")
10+
}
11+
self.value = value
12+
}
13+
14+
public init(unchecked value: String) {
15+
self.value = value
16+
}
17+
}
18+
19+
extension SafeString: CustomStringConvertible {
20+
public var description: String { value }
21+
}
22+
23+
24+
extension String {
25+
var safe: SafeString {
26+
get throws { try .init(self) }
27+
}
28+
var unchecked: SafeString { .init(unchecked: self) }
29+
}

0 commit comments

Comments
 (0)