1
1
/*
2
2
This source file is part of the Swift.org open source project
3
-
3
+
4
4
Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5
5
Licensed under Apache License v2.0 with Runtime Library Exception
6
-
6
+
7
7
See http://swift.org/LICENSE.txt for license information
8
8
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9
9
*/
@@ -16,33 +16,36 @@ import TSCBasic
16
16
17
17
public final class PinsStore {
18
18
public typealias PinsMap = [ PackageIdentity : PinsStore . Pin ]
19
-
19
+
20
20
public struct Pin : Equatable {
21
21
/// The package reference of the pinned dependency.
22
22
public let packageRef : PackageReference
23
-
23
+
24
24
/// The pinned state.
25
25
public let state : CheckoutState
26
-
26
+
27
27
public init ( packageRef: PackageReference , state: CheckoutState ) {
28
28
self . packageRef = packageRef
29
29
self . state = state
30
30
}
31
31
}
32
32
33
33
private let mirrors : DependencyMirrors
34
-
35
- /// The pins map.
36
- public fileprivate( set) var pinsMap : PinsMap
37
-
34
+
35
+ /// storage
36
+ private let storage : PinsStorage
37
+ private let _pins : ThreadSafeKeyValueStore < PackageIdentity , PinsStore . Pin >
38
+
38
39
/// The current pins.
40
+
41
+ public var pinsMap : PinsMap {
42
+ self . _pins. get ( )
43
+ }
44
+
39
45
public var pins : AnySequence < Pin > {
40
- return AnySequence < Pin > ( pinsMap. values)
46
+ return AnySequence < Pin > ( self . pinsMap. values)
41
47
}
42
48
43
- /// storage
44
- private let storage : PinsStorage
45
-
46
49
/// Create a new pins store.
47
50
///
48
51
/// - Parameters:
@@ -51,17 +54,17 @@ public final class PinsStore {
51
54
public init ( pinsFile: AbsolutePath , fileSystem: FileSystem , mirrors: DependencyMirrors ) throws {
52
55
self . storage = . init( path: pinsFile, fileSystem: fileSystem)
53
56
self . mirrors = mirrors
54
-
57
+
55
58
do {
56
- self . pinsMap = try self . storage. load ( mirrors: mirrors)
59
+ self . _pins = . init ( try self . storage. load ( mirrors: mirrors) )
57
60
} catch {
58
- self . pinsMap = [ : ]
61
+ self . _pins = . init ( )
59
62
// FIXME: delete the file?
60
63
// FIXME: warning instead of error?
61
64
throw StringError ( " Package.resolved file is corrupted or malformed; fix or delete the file to continue: \( error) " )
62
65
}
63
66
}
64
-
67
+
65
68
/// Pin a repository at a version.
66
69
///
67
70
/// This method does not automatically write to state file.
@@ -75,24 +78,24 @@ public final class PinsStore {
75
78
state: state
76
79
) )
77
80
}
78
-
81
+
79
82
/// Add a pin.
80
83
///
81
84
/// This will replace any previous pin with same package name.
82
85
public func add( _ pin: Pin ) {
83
- self . pinsMap [ pin. packageRef. identity] = pin
86
+ self . _pins [ pin. packageRef. identity] = pin
84
87
}
85
-
88
+
86
89
/// Unpin all of the currently pinned dependencies.
87
90
///
88
91
/// This method does not automatically write to state file.
89
92
public func unpinAll( ) {
90
93
// Reset the pins map.
91
- self . pinsMap = [ : ]
94
+ self . _pins . clear ( )
92
95
}
93
-
96
+
94
97
public func saveState( ) throws {
95
- try self . storage. save ( pins: self . pinsMap , mirrors: self . mirrors, removeIfEmpty: true )
98
+ try self . storage. save ( pins: self . _pins . get ( ) , mirrors: self . mirrors, removeIfEmpty: true )
96
99
}
97
100
}
98
101
@@ -108,13 +111,14 @@ fileprivate struct PinsStorage {
108
111
self . path = path
109
112
self . fileSystem = fileSystem
110
113
}
111
-
114
+
112
115
func load( mirrors: DependencyMirrors ) throws -> PinsStore . PinsMap {
113
116
if !self . fileSystem. exists ( self . path) {
114
117
return [ : ]
115
118
}
116
-
117
- return try self . fileSystem. withLock ( on: self . path, type: . shared) {
119
+
120
+ // 👀 do we want a lock file here? safer but pretty noisy
121
+ //return try self.fileSystem.withLock(on: self.path, type: .shared) {
118
122
let version = try self . decoder. decode ( path: self . path, fileSystem: self . fileSystem, as: Version . self)
119
123
switch version. version {
120
124
case 1 :
@@ -128,15 +132,15 @@ fileprivate struct PinsStorage {
128
132
default :
129
133
throw InternalError ( " unknown RepositoryManager version: \( version) " )
130
134
}
131
- }
135
+ // }
132
136
}
133
-
137
+
134
138
func save( pins: PinsStore . PinsMap , mirrors: DependencyMirrors , removeIfEmpty: Bool ) throws {
135
139
if !self . fileSystem. exists ( self . path. parentDirectory) {
136
140
try self . fileSystem. createDirectory ( self . path. parentDirectory)
137
141
}
138
-
139
- try self . fileSystem. withLock ( on: self . path, type: . exclusive) {
142
+ // 👀 do we want a lock file here? safer but pretty noisy
143
+ // try self.fileSystem.withLock(on: self.path, type: .exclusive) {
140
144
// Remove the pins file if there are zero pins to save.
141
145
//
142
146
// This can happen if all dependencies are path-based or edited
@@ -145,61 +149,64 @@ fileprivate struct PinsStorage {
145
149
try self . fileSystem. removeFileTree ( self . path)
146
150
return
147
151
}
148
-
152
+
149
153
let container = V1 ( pins: pins, mirrors: mirrors)
150
154
let data = try self . encoder. encode ( container)
151
155
try self . fileSystem. writeFileContents ( self . path, data: data)
152
- }
156
+ // }
153
157
}
154
-
158
+
155
159
func reset( ) throws {
156
160
if !self . fileSystem. exists ( self . path. parentDirectory) {
157
161
return
158
162
}
159
- try self . fileSystem. withLock ( on: self . path, type: . exclusive) {
163
+ // 👀 do we want a lock file here? safer but pretty noisy
164
+ //try self.fileSystem.withLock(on: self.path, type: .exclusive) {
160
165
try self . fileSystem. removeFileTree ( self . path)
161
- }
166
+ // }
162
167
}
163
-
168
+
164
169
// version reader
165
170
struct Version : Codable {
166
171
let version : Int
167
172
}
168
-
173
+
169
174
// v1 storage format
170
175
struct V1 : Codable {
171
176
let version : Int
172
177
let object : Container
173
-
178
+
174
179
init ( pins: PinsStore . PinsMap , mirrors: DependencyMirrors ) {
175
180
self . version = 1
176
181
self . object = . init(
177
- pins: pins. values. map { Pin ( $0, mirrors: mirrors) }
182
+ pins: pins. values
183
+ . sorted ( by: { $0. packageRef. identity < $1. packageRef. identity } )
184
+ . map { Pin ( $0, mirrors: mirrors) }
178
185
)
179
186
}
180
-
187
+
181
188
struct Container : Codable {
182
189
var pins : [ Pin ]
183
190
}
184
-
191
+
185
192
struct Pin : Codable {
186
193
let package : String ?
187
194
let repositoryURL : String
188
195
let state : CheckoutInfo
189
-
196
+
190
197
init ( _ pin: PinsStore . Pin , mirrors: DependencyMirrors ) {
191
198
self . package = pin. packageRef. name
192
199
// rdar://52529014, rdar://52529011: pin file should store the original location but remap when loading
193
200
self . repositoryURL = mirrors. originalURL ( for: pin. packageRef. location) ?? pin. packageRef. location
194
201
self . state = . init( pin. state)
195
202
}
196
203
}
197
-
204
+
198
205
struct CheckoutInfo : Codable {
199
206
let revision : String
200
207
let branch : String ?
201
208
let version : String ?
202
-
209
+
203
210
init ( _ state: CheckoutState ) {
204
211
switch state {
205
212
case . version( let version, let revision) :
0 commit comments