1
1
import Foundation
2
2
3
3
@available ( OSX 10 . 13 , * )
4
+ /// Container of parsed netrc connection settings
4
5
public struct Netrc {
5
6
6
- public struct Machine : Equatable {
7
- public var isDefault : Bool {
8
- return name == " default "
9
- }
10
- public let name : String
11
- public let login : String
12
- public let password : String
13
-
14
- init ? ( for match: NSTextCheckingResult , string: String , variant: String = " " ) {
15
- guard let name = Token . machine. capture ( in: match, string: string) ?? Token . default. capture ( in: match, string: string) ,
16
- let login = Token . login. capture ( prefix: variant, in: match, string: string) ,
17
- let password = Token . password. capture ( prefix: variant, in: match, string: string) else {
18
- return nil
19
- }
20
- self = Machine ( name: name, login: login, password: password)
21
- }
22
-
23
- public init ( name: String , login: String , password: String ) {
24
- self . name = name
25
- self . login = login
26
- self . password = password
27
- }
28
- }
29
-
30
- public enum Error : Swift . Error {
31
- case fileNotFound( Foundation . URL )
32
- case unreadableFile( Foundation . URL )
33
- case machineNotFound
34
- case invalidDefaultMachinePosition
35
- }
36
-
37
- @frozen private enum Token : String , CaseIterable {
38
- case machine
39
- case login
40
- case password
41
- case macdef
42
- case `default`
43
-
44
- func capture( prefix: String = " " , in match: NSTextCheckingResult , string: String ) -> String ? {
45
- guard let range = Range ( match. range ( withName: prefix + rawValue) , in: string) else { return nil }
46
- return String ( string [ range] )
47
- }
48
- }
49
-
7
+ /// Representation of `machine` connection settings & `default` connection settings. If `default` connection settings present, they will be last element.
50
8
public let machines : [ Machine ]
51
9
52
10
init ( machines: [ Machine ] ) {
53
11
self . machines = machines
54
12
}
55
13
14
+ /// Basic authorization header string
15
+ /// - Parameter url: URI of network resource to be accessed
16
+ /// - Returns: (optional) Basic Authorization header string to be added to the request
56
17
public func authorization( for url: Foundation . URL ) -> String ? {
57
18
guard let index = machines. firstIndex ( where: { $0. name == url. host } ) ?? machines. firstIndex ( where: { $0. isDefault } ) else { return nil }
58
19
let machine = machines [ index]
@@ -61,6 +22,9 @@ public struct Netrc {
61
22
return " Basic \( authData. base64EncodedString ( ) ) "
62
23
}
63
24
25
+ ///
26
+ /// - Parameter fileURL: Location of netrc file, defaults to `~/.netrc`
27
+ /// - Returns: `Netrc` container with parsed connection settings, or error
64
28
public static func load( from fileURL: Foundation . URL = Foundation . URL ( fileURLWithPath: " \( NSHomeDirectory ( ) ) /.netrc " ) ) -> Result < Netrc , Netrc . Error > {
65
29
guard FileManager . default. fileExists ( atPath: fileURL. path) else { return . failure( . fileNotFound( fileURL) ) }
66
30
guard FileManager . default. isReadableFile ( atPath: fileURL. path) ,
@@ -69,6 +33,10 @@ public struct Netrc {
69
33
return Netrc . from ( fileContents)
70
34
}
71
35
36
+
37
+ /// Regex matching logic for deriving `Netrc` container from string content
38
+ /// - Parameter content: String text of netrc file
39
+ /// - Returns: `Netrc` container with parsed connection settings, or error
72
40
public static func from( _ content: String ) -> Result < Netrc , Netrc . Error > {
73
41
74
42
let content = trimComments ( from: content)
@@ -87,6 +55,10 @@ public struct Netrc {
87
55
return . success( Netrc ( machines: machines) )
88
56
}
89
57
58
+
59
+ /// Utility method to trim comments from netrc content
60
+ /// - Parameter text: String text of netrc file
61
+ /// - Returns: String text of netrc file *sans* comments
90
62
private static func trimComments( from text: String ) -> String {
91
63
let regex = try ! NSRegularExpression ( pattern: RegexUtil . comments, options: . anchorsMatchLines)
92
64
let nsString = text as NSString
@@ -101,7 +73,57 @@ public struct Netrc {
101
73
}
102
74
}
103
75
76
+ @available ( OSX 10 . 13 , * )
77
+ public extension Netrc {
78
+
79
+ enum Error : Swift . Error {
80
+ case fileNotFound( Foundation . URL )
81
+ case unreadableFile( Foundation . URL )
82
+ case machineNotFound
83
+ case invalidDefaultMachinePosition
84
+ }
85
+
86
+
87
+ /// Representation of connection settings
88
+ /// - important: Default connection settings are stored in machine named `default`
89
+ struct Machine : Equatable {
90
+ public let name : String
91
+ public let login : String
92
+ public let password : String
93
+
94
+ public var isDefault : Bool {
95
+ return name == " default "
96
+ }
97
+
98
+ public init ( name: String , login: String , password: String ) {
99
+ self . name = name
100
+ self . login = login
101
+ self . password = password
102
+ }
103
+
104
+ init ? ( for match: NSTextCheckingResult , string: String , variant: String = " " ) {
105
+ guard let name = RegexUtil . Token. machine. capture ( in: match, string: string) ?? RegexUtil . Token. default. capture ( in: match, string: string) ,
106
+ let login = RegexUtil . Token. login. capture ( prefix: variant, in: match, string: string) ,
107
+ let password = RegexUtil . Token. password. capture ( prefix: variant, in: match, string: string) else {
108
+ return nil
109
+ }
110
+ self = Machine ( name: name, login: login, password: password)
111
+ }
112
+ }
113
+ }
114
+
115
+ @available ( OSX 10 . 13 , * )
104
116
fileprivate enum RegexUtil {
117
+
118
+ @frozen fileprivate enum Token : String , CaseIterable {
119
+
120
+ case machine, login, password, account, macdef, `default`
121
+
122
+ func capture( prefix: String = " " , in match: NSTextCheckingResult , string: String ) -> String ? {
123
+ guard let range = Range ( match. range ( withName: prefix + rawValue) , in: string) else { return nil }
124
+ return String ( string [ range] )
125
+ }
126
+ }
105
127
106
128
static let comments : String = " \\ #[ \\ s \\ S]*?.*$ "
107
129
0 commit comments