@@ -21,10 +21,9 @@ extension FileSystem {
21
21
public var dotSwiftPM : AbsolutePath {
22
22
self . homeDirectory. appending ( component: " .swiftpm " )
23
23
}
24
-
25
- /// SwiftPM security directory
26
- public var swiftPMSecurityDirectory : AbsolutePath {
27
- self . dotSwiftPM. appending ( component: " security " )
24
+
25
+ fileprivate var idiomaticSwiftPMDirectory : AbsolutePath ? {
26
+ return FileManager . default. urls ( for: . libraryDirectory, in: . userDomainMask) . first. flatMap { AbsolutePath ( $0. path) } ? . appending ( component: " org.swift.swiftpm " )
28
27
}
29
28
}
30
29
@@ -62,59 +61,144 @@ extension FileSystem {
62
61
try self . createDirectory ( self . dotSwiftPM, recursive: true )
63
62
}
64
63
// Create ~/.swiftpm/cache symlink if necessary
65
- if !self . exists ( self . dotSwiftPMCachesDirectory, followSymlink: false ) {
66
- try self . createSymbolicLink ( dotSwiftPMCachesDirectory, pointingAt: idiomaticCacheDirectory, relative: false )
64
+ // locking ~/.swiftpm to protect from concurrent access
65
+ try self . withLock ( on: self . dotSwiftPM, type: . exclusive) {
66
+ if !self . exists ( self . dotSwiftPMCachesDirectory, followSymlink: false ) {
67
+ try self . createSymbolicLink ( dotSwiftPMCachesDirectory, pointingAt: idiomaticCacheDirectory, relative: false )
68
+ }
67
69
}
68
70
return idiomaticCacheDirectory
69
71
}
70
72
}
71
73
72
- // MARK: - config
74
+ // MARK: - configuration
73
75
74
76
extension FileSystem {
75
- private var idiomaticUserConfigDirectory : AbsolutePath ? {
76
- return FileManager . default. urls ( for: . libraryDirectory, in: . userDomainMask) . first. flatMap { AbsolutePath ( $0. path) }
77
+ /// SwiftPM config directory under user's config directory (if exists)
78
+ public var swiftPMConfigurationDirectory : AbsolutePath {
79
+ if let path = self . idiomaticSwiftPMDirectory {
80
+ return path. appending ( component: " configuration " )
81
+ } else {
82
+ return self . dotSwiftPMConfigurationDirectory
83
+ }
77
84
}
78
85
79
- /// SwiftPM config directory under user's config directory (if exists)
80
- public var swiftPMConfigDirectory : AbsolutePath {
81
- if let path = self . idiomaticUserConfigDirectory {
82
- return path. appending ( component: " org.swift.swiftpm " )
86
+ fileprivate var dotSwiftPMConfigurationDirectory : AbsolutePath {
87
+ return self . dotSwiftPM. appending ( component: " configuration " )
88
+ }
89
+ }
90
+
91
+ extension FileSystem {
92
+ public func getOrCreateSwiftPMConfigurationDirectory( observabilityScope: ObservabilityScope ? ) throws -> AbsolutePath {
93
+ let idiomaticConfigurationDirectory = self . swiftPMConfigurationDirectory
94
+
95
+ // temporary 5.6, remove on next version: transition from previous configuration location
96
+ if !self . exists ( idiomaticConfigurationDirectory) {
97
+ try self . createDirectory ( idiomaticConfigurationDirectory, recursive: true )
98
+ }
99
+
100
+ // in the case where ~/.swiftpm/configuration is not the idiomatic location (eg on macOS where its /Users/<user>/Library/org.swift.swiftpm/configuration)
101
+ if idiomaticConfigurationDirectory != self . dotSwiftPMConfigurationDirectory {
102
+ // copy the configuration files from old location (eg /Users/<user>/Library/org.swift.swiftpm) to new one (eg /Users/<user>/Library/org.swift.swiftpm/configuration)
103
+ // but leave them there for backwards compatibility (eg older xcode)
104
+ let oldConfigDirectory = idiomaticConfigurationDirectory. parentDirectory
105
+ if self . exists ( oldConfigDirectory, followSymlink: false ) && self . isDirectory ( oldConfigDirectory) {
106
+ let configurationFiles = try self . getDirectoryContents ( oldConfigDirectory)
107
+ . map { oldConfigDirectory. appending ( component: $0) }
108
+ . filter { self . isFile ( $0) && !self . isSymlink ( $0) && $0. extension != " lock " }
109
+ for file in configurationFiles {
110
+ let destination = idiomaticConfigurationDirectory. appending ( component: file. basename)
111
+ observabilityScope? . emit ( warning: " Usage of \( file) has been deprecated. Please delete it and use the new \( destination) instead. " )
112
+ if !self . exists ( destination) {
113
+ try self . copy ( from: file, to: destination)
114
+ }
115
+ }
116
+ }
117
+ // in the case where ~/.swiftpm/configuration is the idiomatic location (eg on Linux)
118
+ } else {
119
+ // copy the configuration files from old location (~/.swiftpm/config) to new one (~/.swiftpm/configuration)
120
+ // but leave them there for backwards compatibility (eg older toolchain)
121
+ let oldConfigDirectory = self . dotSwiftPM. appending ( component: " config " )
122
+ if self . exists ( oldConfigDirectory, followSymlink: false ) && self . isDirectory ( oldConfigDirectory) {
123
+ let configurationFiles = try self . getDirectoryContents ( oldConfigDirectory)
124
+ . map { oldConfigDirectory. appending ( component: $0) }
125
+ . filter { self . isFile ( $0) && !self . isSymlink ( $0) && $0. extension != " lock " }
126
+ for file in configurationFiles {
127
+ let destination = idiomaticConfigurationDirectory. appending ( component: file. basename)
128
+ observabilityScope? . emit ( warning: " Usage of \( file) has been deprecated. Please delete it and use the new \( destination) instead. " )
129
+ if !self . exists ( destination) {
130
+ try self . copy ( from: file, to: destination)
131
+ }
132
+ }
133
+ }
134
+ }
135
+ // ~temporary 5.6 migration
136
+
137
+ // Create idiomatic if necessary
138
+ if !self . exists ( idiomaticConfigurationDirectory) {
139
+ try self . createDirectory ( idiomaticConfigurationDirectory, recursive: true )
140
+ }
141
+ // Create ~/.swiftpm if necessary
142
+ if !self . exists ( self . dotSwiftPM) {
143
+ try self . createDirectory ( self . dotSwiftPM, recursive: true )
144
+ }
145
+ // Create ~/.swiftpm/configuration symlink if necessary
146
+ // locking ~/.swiftpm to protect from concurrent access
147
+ try self . withLock ( on: self . dotSwiftPM, type: . exclusive) {
148
+ if !self . exists ( self . dotSwiftPMConfigurationDirectory, followSymlink: false ) {
149
+ try self . createSymbolicLink ( dotSwiftPMConfigurationDirectory, pointingAt: idiomaticConfigurationDirectory, relative: false )
150
+ }
151
+ }
152
+
153
+ return idiomaticConfigurationDirectory
154
+ }
155
+ }
156
+
157
+ // MARK: - security
158
+
159
+ extension FileSystem {
160
+ /// SwiftPM security directory under user's security directory (if exists)
161
+ public var swiftPMSecurityDirectory : AbsolutePath {
162
+ if let path = self . idiomaticSwiftPMDirectory {
163
+ return path. appending ( component: " security " )
83
164
} else {
84
- return self . dotSwiftPMConfigDirectory
165
+ return self . dotSwiftPMSecurityDirectory
85
166
}
86
167
}
87
168
88
- fileprivate var dotSwiftPMConfigDirectory : AbsolutePath {
89
- return self . dotSwiftPM. appending ( component: " config " )
169
+ fileprivate var dotSwiftPMSecurityDirectory : AbsolutePath {
170
+ return self . dotSwiftPM. appending ( component: " security " )
90
171
}
91
172
}
92
173
93
174
extension FileSystem {
94
- public func getOrCreateSwiftPMConfigDirectory ( ) throws -> AbsolutePath {
95
- let idiomaticConfigDirectory = self . swiftPMConfigDirectory
175
+ public func getOrCreateSwiftPMSecurityDirectory ( ) throws -> AbsolutePath {
176
+ let idiomaticSecurityDirectory = self . swiftPMSecurityDirectory
96
177
97
- // temporary 5.5, remove on next version: transition from ~/.swiftpm/config to idiomatic location + symbolic link
98
- if idiomaticConfigDirectory != self . dotSwiftPMConfigDirectory &&
99
- self . exists ( self . dotSwiftPMConfigDirectory) && self . isDirectory ( self . dotSwiftPMConfigDirectory) &&
100
- !self . exists ( idiomaticConfigDirectory) {
101
- print ( " transitioning \( self . dotSwiftPMConfigDirectory) to \( idiomaticConfigDirectory) " )
102
- try self . move ( from: self . dotSwiftPMConfigDirectory, to: idiomaticConfigDirectory)
178
+ // temporary 5.6, remove on next version: transition from ~/.swiftpm/security to idiomatic location + symbolic link
179
+ if idiomaticSecurityDirectory != self . dotSwiftPMSecurityDirectory &&
180
+ self . exists ( self . dotSwiftPMSecurityDirectory) &&
181
+ self . isDirectory ( self . dotSwiftPMSecurityDirectory) {
182
+ try self . removeFileTree ( self . dotSwiftPMSecurityDirectory)
103
183
}
184
+ // ~temporary 5.6 migration
104
185
105
186
// Create idiomatic if necessary
106
- if !self . exists ( idiomaticConfigDirectory ) {
107
- try self . createDirectory ( idiomaticConfigDirectory , recursive: true )
187
+ if !self . exists ( idiomaticSecurityDirectory ) {
188
+ try self . createDirectory ( idiomaticSecurityDirectory , recursive: true )
108
189
}
109
190
// Create ~/.swiftpm if necessary
110
191
if !self . exists ( self . dotSwiftPM) {
111
192
try self . createDirectory ( self . dotSwiftPM, recursive: true )
112
193
}
113
- // Create ~/.swiftpm/config symlink if necessary
114
- if !self . exists ( self . dotSwiftPMConfigDirectory, followSymlink: false ) {
115
- try self . createSymbolicLink ( dotSwiftPMConfigDirectory, pointingAt: idiomaticConfigDirectory, relative: false )
194
+ // Create ~/.swiftpm/security symlink if necessary
195
+ // locking ~/.swiftpm to protect from concurrent access
196
+ try self . withLock ( on: self . dotSwiftPM, type: . exclusive) {
197
+ if !self . exists ( self . dotSwiftPMSecurityDirectory, followSymlink: false ) {
198
+ try self . createSymbolicLink ( dotSwiftPMSecurityDirectory, pointingAt: idiomaticSecurityDirectory, relative: false )
199
+ }
116
200
}
117
- return idiomaticConfigDirectory
201
+ return idiomaticSecurityDirectory
118
202
}
119
203
}
120
204
0 commit comments