12
12
13
13
import Foundation
14
14
15
- #if USE_IMPL_ONLY_IMPORTS
16
- @_implementationOnly import TSCclibc
15
+ #if canImport(Glibc)
16
+ import Glibc
17
+ #elseif canImport(Musl)
18
+ import Musl
19
+ #elseif os(Windows)
20
+ import CRT
21
+ import WinSDK
17
22
#else
18
- import TSCclibc
23
+ import Darwin . C
19
24
#endif
20
25
21
26
// FIXME: Use Synchronization.Mutex when available
@@ -79,7 +84,7 @@ extension Environment {
79
84
package mutating func prependPath( key: EnvironmentKey , value: String ) {
80
85
guard !value. isEmpty else { return }
81
86
if let existing = self [ key] {
82
- self [ key] = " \( value) \( Self . pathValueDelimiter ) \( existing) "
87
+ self [ key] = " \( value) \( Self . pathEntryDelimiter ) \( existing) "
83
88
} else {
84
89
self [ key] = value
85
90
}
@@ -88,13 +93,13 @@ extension Environment {
88
93
package mutating func appendPath( key: EnvironmentKey , value: String ) {
89
94
guard !value. isEmpty else { return }
90
95
if let existing = self [ key] {
91
- self [ key] = " \( existing) \( Self . pathValueDelimiter ) \( value) "
96
+ self [ key] = " \( existing) \( Self . pathEntryDelimiter ) \( value) "
92
97
} else {
93
98
self [ key] = value
94
99
}
95
100
}
96
101
97
- package static var pathValueDelimiter : String {
102
+ package static var pathEntryDelimiter : String {
98
103
#if os(Windows)
99
104
" ; "
100
105
#else
@@ -195,8 +200,32 @@ extension Environment {
195
200
///
196
201
/// > Important: This operation is _not_ concurrency safe.
197
202
package static func set( key: EnvironmentKey , value: String ? ) throws {
203
+ #if os(Windows)
204
+ func SetEnvironmentVariableW( _ key: String , _ value: String ? ) -> Bool {
205
+ key. withCString ( encodedAs: UTF16 . self) { key in
206
+ if let value {
207
+ value. withCString ( encodedAs: UTF16 . self) { value in
208
+ SetEnvironmentVariableW ( key, value)
209
+ }
210
+ } else {
211
+ SetEnvironmentVariableW ( key, nil )
212
+ }
213
+ }
214
+ }
215
+ #endif
216
+
217
+ // Invalidate cached value after mutating the global environment.
218
+ // This is potentially overly safe because we may not need to invalidate
219
+ // the cache if the mutation fails. However this approach is easier to
220
+ // read and reason about.
221
+ defer { Self . _cachedCurrent. withLock { $0 = nil } }
198
222
if let value = value {
199
223
#if os(Windows)
224
+ guard SetEnvironmentVariableW ( key. rawValue, value) else {
225
+ throw UpdateEnvironmentError (
226
+ function: " SetEnvironmentVariableW " ,
227
+ code: Int32 ( GetLastError ( ) ) )
228
+ }
200
229
guard _putenv ( " \( key) = \( value) " ) == 0 else {
201
230
throw UpdateEnvironmentError (
202
231
function: " _putenv " ,
@@ -211,6 +240,11 @@ extension Environment {
211
240
#endif
212
241
} else {
213
242
#if os(Windows)
243
+ guard SetEnvironmentVariableW ( key. rawValue, nil ) else {
244
+ throw UpdateEnvironmentError (
245
+ function: " SetEnvironmentVariableW " ,
246
+ code: Int32 ( GetLastError ( ) ) )
247
+ }
214
248
guard _putenv ( " \( key) = " ) == 0 else {
215
249
throw UpdateEnvironmentError (
216
250
function: " _putenv " ,
@@ -224,7 +258,6 @@ extension Environment {
224
258
}
225
259
#endif
226
260
}
227
- Self . _cachedCurrent. withLock { $0 = nil }
228
261
}
229
262
}
230
263
@@ -254,9 +287,6 @@ extension Environment: Collection {
254
287
var underlying : Dictionary < EnvironmentKey , String > . Index
255
288
}
256
289
public typealias Element = ( key: EnvironmentKey , value: String )
257
- // FIXME: Remove after upgrading past Swift 5.9
258
- // Required to be explicitly spelled out on older Swift compilers.
259
- public typealias Iterator = IndexingIterator < Self >
260
290
261
291
public var startIndex : Index {
262
292
Index ( underlying: self . storage. startIndex)
@@ -266,8 +296,8 @@ extension Environment: Collection {
266
296
Index ( underlying: self . storage. endIndex)
267
297
}
268
298
269
- public subscript( index: Index ) -> Iterator . Element {
270
- get { self . storage [ index. underlying] }
299
+ public subscript( index: Index ) -> Element {
300
+ self . storage [ index. underlying]
271
301
}
272
302
273
303
public func index( after index: Self . Index ) -> Self . Index {
@@ -277,23 +307,11 @@ extension Environment: Collection {
277
307
278
308
extension Environment : CustomStringConvertible {
279
309
public var description : String {
280
- var description = " [ "
281
- let sorted = self . sorted { $0. key < $1. key }
282
- var first = true
283
- for (key, value) in sorted {
284
- if first {
285
- first = false
286
- } else {
287
- description. append ( " , " )
288
- }
289
- description. append ( " \" " )
290
- description. append ( key. rawValue)
291
- description. append ( " = " )
292
- description. append ( value)
293
- description. append ( " \" " )
294
- }
295
- description. append ( " ] " )
296
- return description
310
+ let body = self
311
+ . sorted { $0. key < $1. key }
312
+ . map { #"" \#( $0. rawValue) "=" \#( $1) ""# }
313
+ . joined ( separator: " , " )
314
+ return " [ \( body) ] "
297
315
}
298
316
}
299
317
0 commit comments