@@ -401,8 +401,8 @@ extension Arguments: CustomStringConvertible, CustomDebugStringConvertible {
401401/// A set of environment variables to use when executing the subprocess.
402402public struct Environment : Sendable , Hashable {
403403 internal enum Configuration : Sendable , Hashable {
404- case inherit( [ String : String ] )
405- case custom( [ String : String ] )
404+ case inherit( [ Key : String ] )
405+ case custom( [ Key : String ] )
406406 #if !os(Windows)
407407 case rawBytes( [ [ UInt8 ] ] )
408408 #endif
@@ -419,11 +419,11 @@ public struct Environment: Sendable, Hashable {
419419 return . init( config: . inherit( [ : ] ) )
420420 }
421421 /// Override the provided `newValue` in the existing `Environment`
422- public func updating( _ newValue: [ String : String ] ) -> Self {
422+ public func updating( _ newValue: [ Key : String ] ) -> Self {
423423 return . init( config: . inherit( newValue) )
424424 }
425425 /// Use custom environment variables
426- public static func custom( _ newValue: [ String : String ] ) -> Self {
426+ public static func custom( _ newValue: [ Key : String ] ) -> Self {
427427 return . init( config: . custom( newValue) )
428428 }
429429
@@ -436,6 +436,17 @@ public struct Environment: Sendable, Hashable {
436436}
437437
438438extension Environment : CustomStringConvertible , CustomDebugStringConvertible {
439+ /// A key used to access values in an ``Environment``.
440+ ///
441+ /// This type respects the compiled platform's case sensitivity requirements.
442+ public struct Key {
443+ public var rawValue : String
444+
445+ package init ( _ rawValue: String ) {
446+ self . rawValue = rawValue
447+ }
448+ }
449+
439450 /// A textual representation of the environment.
440451 public var description : String {
441452 switch self . config {
@@ -464,9 +475,9 @@ extension Environment: CustomStringConvertible, CustomDebugStringConvertible {
464475 return self . description
465476 }
466477
467- internal static func currentEnvironmentValues( ) -> [ String : String ] {
478+ internal static func currentEnvironmentValues( ) -> [ Key : String ] {
468479 return self . withCopiedEnv { environments in
469- var results : [ String : String ] = [ : ]
480+ var results : [ Key : String ] = [ : ]
470481 for env in environments {
471482 let environmentString = String ( cString: env)
472483
@@ -488,13 +499,76 @@ extension Environment: CustomStringConvertible, CustomDebugStringConvertible {
488499 let value = String (
489500 environmentString [ environmentString. index ( after: delimiter) ..< environmentString. endIndex]
490501 )
491- results [ key] = value
502+ results [ Key ( key) ] = value
492503 }
493504 return results
494505 }
495506 }
496507}
497508
509+ extension Environment . Key {
510+ package static let path : Self = " PATH "
511+ }
512+
513+ extension Environment . Key : CodingKeyRepresentable { }
514+
515+ extension Environment . Key : Comparable {
516+ public static func < ( lhs: Self , rhs: Self ) -> Bool {
517+ // Even on windows use a stable sort order.
518+ lhs. rawValue < rhs. rawValue
519+ }
520+ }
521+
522+ extension Environment . Key : CustomStringConvertible {
523+ public var description : String { self . rawValue }
524+ }
525+
526+ extension Environment . Key : Encodable {
527+ public func encode( to encoder: any Swift . Encoder ) throws {
528+ try self . rawValue. encode ( to: encoder)
529+ }
530+ }
531+
532+ extension Environment . Key : Equatable {
533+ public static func == ( _ lhs: Self , _ rhs: Self ) -> Bool {
534+ #if os(Windows)
535+ lhs. rawValue. lowercased ( ) == rhs. rawValue. lowercased ( )
536+ #else
537+ lhs. rawValue == rhs. rawValue
538+ #endif
539+ }
540+ }
541+
542+ extension Environment . Key : ExpressibleByStringLiteral {
543+ public init ( stringLiteral rawValue: String ) {
544+ self . init ( rawValue)
545+ }
546+ }
547+
548+ extension Environment . Key : Decodable {
549+ public init ( from decoder: any Swift . Decoder ) throws {
550+ self . rawValue = try String ( from: decoder)
551+ }
552+ }
553+
554+ extension Environment . Key : Hashable {
555+ public func hash( into hasher: inout Hasher ) {
556+ #if os(Windows)
557+ self . rawValue. lowercased ( ) . hash ( into: & hasher)
558+ #else
559+ self . rawValue. hash ( into: & hasher)
560+ #endif
561+ }
562+ }
563+
564+ extension Environment . Key : RawRepresentable {
565+ public init ? ( rawValue: String ) {
566+ self . rawValue = rawValue
567+ }
568+ }
569+
570+ extension Environment . Key : Sendable { }
571+
498572// MARK: - TerminationStatus
499573
500574/// An exit status of a subprocess.
0 commit comments