@@ -23,6 +23,46 @@ import Dispatch
23
23
24
24
import _Concurrency
25
25
26
+ public struct ProcessEnvironmentBlock {
27
+ #if os(Windows)
28
+ internal typealias Key = CaseInsensitiveString
29
+ private var storage : Dictionary < CaseInsensitiveString , String >
30
+ #else
31
+ internal typealias Key = String
32
+ private var storage : Dictionary < String , String >
33
+ #endif
34
+
35
+ #if !os(Windows)
36
+ internal init ( dictionary: Dictionary < String , String > ) {
37
+ self . storage = dictionary
38
+ }
39
+ #endif
40
+
41
+ internal init < S: Sequence > ( uniqueKeysWithValues keysAndValues: S )
42
+ where S. Element == ( Key , String ) {
43
+ storage = . init( uniqueKeysWithValues: keysAndValues)
44
+ }
45
+
46
+ internal var dictionary : Dictionary < String , String > {
47
+ #if os(Windows)
48
+ return Dictionary < String , String > ( uniqueKeysWithValues: storage. map {
49
+ ( $0. value, $1)
50
+ } )
51
+ #else
52
+ return storage
53
+ #endif
54
+ }
55
+
56
+ public subscript( _ key: String ) -> String ? {
57
+ #if os(Windows)
58
+ return storage [ CaseInsensitiveString ( key) ]
59
+ #else
60
+ return storage [ key]
61
+ #endif
62
+ }
63
+ }
64
+
65
+
26
66
/// Process result data which is available after process termination.
27
67
public struct ProcessResult : CustomStringConvertible , Sendable {
28
68
@@ -53,7 +93,7 @@ public struct ProcessResult: CustomStringConvertible, Sendable {
53
93
public let arguments : [ String ]
54
94
55
95
/// The environment with which the process was launched.
56
- public let environment : [ String : String ]
96
+ public let environment : ProcessEnvironmentBlock
57
97
58
98
/// The exit status of the process.
59
99
public let exitStatus : ExitStatus
@@ -71,7 +111,7 @@ public struct ProcessResult: CustomStringConvertible, Sendable {
71
111
/// See `waitpid(2)` for information on the exit status code.
72
112
public init (
73
113
arguments: [ String ] ,
74
- environment: [ String : String ] ,
114
+ environment: ProcessEnvironmentBlock ,
75
115
exitStatusCode: Int32 ,
76
116
normal: Bool ,
77
117
output: Result < [ UInt8 ] , Swift . Error > ,
@@ -99,7 +139,7 @@ public struct ProcessResult: CustomStringConvertible, Sendable {
99
139
/// Create an instance using an exit status and output result.
100
140
public init (
101
141
arguments: [ String ] ,
102
- environment: [ String : String ] ,
142
+ environment: ProcessEnvironmentBlock ,
103
143
exitStatus: ExitStatus ,
104
144
output: Result < [ UInt8 ] , Swift . Error > ,
105
145
stderrOutput: Result < [ UInt8 ] , Swift . Error >
@@ -285,7 +325,7 @@ public final class Process {
285
325
public let arguments : [ String ]
286
326
287
327
/// The environment with which the process was executed.
288
- public let environment : [ String : String ]
328
+ public let environment : ProcessEnvironmentBlock
289
329
290
330
/// The path to the directory under which to run the process.
291
331
public let workingDirectory : AbsolutePath ?
@@ -359,7 +399,7 @@ public final class Process {
359
399
@available ( macOS 10 . 15 , * )
360
400
public init (
361
401
arguments: [ String ] ,
362
- environment: [ String : String ] = ProcessEnv . vars,
402
+ environment: ProcessEnvironmentBlock = ProcessEnv . vars,
363
403
workingDirectory: AbsolutePath ,
364
404
outputRedirection: OutputRedirection = . collect,
365
405
startNewProcessGroup: Bool = true ,
@@ -379,7 +419,7 @@ public final class Process {
379
419
@available ( macOS 10 . 15 , * )
380
420
public convenience init (
381
421
arguments: [ String ] ,
382
- environment: [ String : String ] = ProcessEnv . vars,
422
+ environment: ProcessEnvironmentBlock = ProcessEnv . vars,
383
423
workingDirectory: AbsolutePath ,
384
424
outputRedirection: OutputRedirection = . collect,
385
425
verbose: Bool ,
@@ -411,7 +451,7 @@ public final class Process {
411
451
/// - loggingHandler: Handler for logging messages
412
452
public init (
413
453
arguments: [ String ] ,
414
- environment: [ String : String ] = ProcessEnv . vars,
454
+ environment: ProcessEnvironmentBlock = ProcessEnv . vars,
415
455
outputRedirection: OutputRedirection = . collect,
416
456
startNewProcessGroup: Bool = true ,
417
457
loggingHandler: LoggingHandler ? = . none
@@ -428,7 +468,7 @@ public final class Process {
428
468
@available ( * , deprecated, message: " use version without verbosity flag " )
429
469
public convenience init (
430
470
arguments: [ String ] ,
431
- environment: [ String : String ] = ProcessEnv . vars,
471
+ environment: ProcessEnvironmentBlock = ProcessEnv . vars,
432
472
outputRedirection: OutputRedirection = . collect,
433
473
verbose: Bool = Process . verbose,
434
474
startNewProcessGroup: Bool = true
@@ -444,7 +484,7 @@ public final class Process {
444
484
445
485
public convenience init (
446
486
args: String ... ,
447
- environment: [ String : String ] = ProcessEnv . vars,
487
+ environment: ProcessEnvironmentBlock = ProcessEnv . vars,
448
488
outputRedirection: OutputRedirection = . collect,
449
489
loggingHandler: LoggingHandler ? = . none
450
490
) {
@@ -536,7 +576,7 @@ public final class Process {
536
576
process. currentDirectoryURL = workingDirectory. asURL
537
577
}
538
578
process. executableURL = executablePath. asURL
539
- process. environment = environment
579
+ process. environment = environment. dictionary
540
580
541
581
let stdinPipe = Pipe ( )
542
582
process. standardInput = stdinPipe
@@ -989,7 +1029,7 @@ extension Process {
989
1029
@available ( macOS 10 . 15 , iOS 13 . 0 , tvOS 13 . 0 , watchOS 6 . 0 , * )
990
1030
static public func popen(
991
1031
arguments: [ String ] ,
992
- environment: [ String : String ] = ProcessEnv . vars,
1032
+ environment: ProcessEnvironmentBlock = ProcessEnv . vars,
993
1033
loggingHandler: LoggingHandler ? = . none
994
1034
) async throws -> ProcessResult {
995
1035
let process = Process (
@@ -1012,7 +1052,7 @@ extension Process {
1012
1052
@available ( macOS 10 . 15 , iOS 13 . 0 , tvOS 13 . 0 , watchOS 6 . 0 , * )
1013
1053
static public func popen(
1014
1054
args: String ... ,
1015
- environment: [ String : String ] = ProcessEnv . vars,
1055
+ environment: ProcessEnvironmentBlock = ProcessEnv . vars,
1016
1056
loggingHandler: LoggingHandler ? = . none
1017
1057
) async throws -> ProcessResult {
1018
1058
try await popen ( arguments: args, environment: environment, loggingHandler: loggingHandler)
@@ -1030,7 +1070,7 @@ extension Process {
1030
1070
@discardableResult
1031
1071
static public func checkNonZeroExit(
1032
1072
arguments: [ String ] ,
1033
- environment: [ String : String ] = ProcessEnv . vars,
1073
+ environment: ProcessEnvironmentBlock = ProcessEnv . vars,
1034
1074
loggingHandler: LoggingHandler ? = . none
1035
1075
) async throws -> String {
1036
1076
let result = try await popen ( arguments: arguments, environment: environment, loggingHandler: loggingHandler)
@@ -1053,7 +1093,7 @@ extension Process {
1053
1093
@discardableResult
1054
1094
static public func checkNonZeroExit(
1055
1095
args: String ... ,
1056
- environment: [ String : String ] = ProcessEnv . vars,
1096
+ environment: ProcessEnvironmentBlock = ProcessEnv . vars,
1057
1097
loggingHandler: LoggingHandler ? = . none
1058
1098
) async throws -> String {
1059
1099
try await checkNonZeroExit ( arguments: args, environment: environment, loggingHandler: loggingHandler)
@@ -1075,7 +1115,7 @@ extension Process {
1075
1115
// #endif
1076
1116
static public func popen(
1077
1117
arguments: [ String ] ,
1078
- environment: [ String : String ] = ProcessEnv . vars,
1118
+ environment: ProcessEnvironmentBlock = ProcessEnv . vars,
1079
1119
loggingHandler: LoggingHandler ? = . none,
1080
1120
queue: DispatchQueue ? = nil ,
1081
1121
completion: @escaping ( Result < ProcessResult , Swift . Error > ) -> Void
@@ -1113,7 +1153,7 @@ extension Process {
1113
1153
@discardableResult
1114
1154
static public func popen(
1115
1155
arguments: [ String ] ,
1116
- environment: [ String : String ] = ProcessEnv . vars,
1156
+ environment: ProcessEnvironmentBlock = ProcessEnv . vars,
1117
1157
loggingHandler: LoggingHandler ? = . none
1118
1158
) throws -> ProcessResult {
1119
1159
let process = Process (
@@ -1140,7 +1180,7 @@ extension Process {
1140
1180
@discardableResult
1141
1181
static public func popen(
1142
1182
args: String ... ,
1143
- environment: [ String : String ] = ProcessEnv . vars,
1183
+ environment: ProcessEnvironmentBlock = ProcessEnv . vars,
1144
1184
loggingHandler: LoggingHandler ? = . none
1145
1185
) throws -> ProcessResult {
1146
1186
return try Process . popen ( arguments: args, environment: environment, loggingHandler: loggingHandler)
@@ -1160,7 +1200,7 @@ extension Process {
1160
1200
@discardableResult
1161
1201
static public func checkNonZeroExit(
1162
1202
arguments: [ String ] ,
1163
- environment: [ String : String ] = ProcessEnv . vars,
1203
+ environment: ProcessEnvironmentBlock = ProcessEnv . vars,
1164
1204
loggingHandler: LoggingHandler ? = . none
1165
1205
) throws -> String {
1166
1206
let process = Process (
@@ -1192,7 +1232,7 @@ extension Process {
1192
1232
@discardableResult
1193
1233
static public func checkNonZeroExit(
1194
1234
args: String ... ,
1195
- environment: [ String : String ] = ProcessEnv . vars,
1235
+ environment: ProcessEnvironmentBlock = ProcessEnv . vars,
1196
1236
loggingHandler: LoggingHandler ? = . none
1197
1237
) throws -> String {
1198
1238
return try checkNonZeroExit ( arguments: args, environment: environment, loggingHandler: loggingHandler)
0 commit comments