Skip to content

Commit 17bf45a

Browse files
committed
[Commands] Update Workspace to track checkout versions.
1 parent 2792f32 commit 17bf45a

File tree

2 files changed

+45
-16
lines changed

2 files changed

+45
-16
lines changed

Sources/Commands/Workspace.swift

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ public class Workspace {
3535
/// The checked out path of the dependency on disk, relative to the workspace checkouts path.
3636
public let subpath: RelativePath
3737

38+
/// The current version of the dependency, if known.
39+
public let currentVersion: Version?
40+
3841
/// The current revision of the dependency.
3942
///
4043
/// This should always be a revision corresponding to the version in the
@@ -44,9 +47,10 @@ public class Workspace {
4447
/// resolved).
4548
public let currentRevision: Revision
4649

47-
fileprivate init(repository: RepositorySpecifier, subpath: RelativePath, currentRevision: Revision) {
50+
fileprivate init(repository: RepositorySpecifier, subpath: RelativePath, currentVersion: Version?, currentRevision: Revision) {
4851
self.repository = repository
4952
self.subpath = subpath
53+
self.currentVersion = currentVersion
5054
self.currentRevision = currentRevision
5155
}
5256

@@ -57,18 +61,39 @@ public class Workspace {
5761
guard case let .dictionary(contents) = data,
5862
case let .string(repositoryURL)? = contents["repositoryURL"],
5963
case let .string(subpathString)? = contents["subpath"],
64+
let currentVersionData = contents["currentVersion"],
6065
case let .string(currentRevisionString)? = contents["currentRevision"] else {
6166
return nil
6267
}
68+
let currentVersion: Version?
69+
switch currentVersionData {
70+
case .null:
71+
currentVersion = nil
72+
case .string(let string):
73+
currentVersion = Version(string)
74+
if currentVersion == nil {
75+
return nil
76+
}
77+
default:
78+
return nil
79+
}
6380
self.repository = RepositorySpecifier(url: repositoryURL)
6481
self.subpath = RelativePath(subpathString)
82+
self.currentVersion = currentVersion
6583
self.currentRevision = Revision(identifier: currentRevisionString)
6684
}
6785

6886
fileprivate func toJSON() -> JSON {
87+
let currentVersionData: JSON
88+
if let currentVersion = self.currentVersion {
89+
currentVersionData = .string(String(describing: currentVersion))
90+
} else {
91+
currentVersionData = .null
92+
}
6993
return .dictionary([
7094
"repositoryURL": .string(repository.url),
7195
"subpath": .string(subpath.asString),
96+
"currentVersion": currentVersionData,
7297
"currentRevision": .string(currentRevision.identifier),
7398
])
7499
}
@@ -187,12 +212,13 @@ public class Workspace {
187212
/// - Parameters:
188213
/// - repository: The repository to clone.
189214
/// - revision: The revision to check out.
215+
/// - version: The dependency version the repository is being checked out at, if known.
190216
/// - Returns: The path of the local repository.
191217
/// - Throws: If the operation could not be satisfied.
192218
//
193219
// FIXME: We are probably going to need a delegate interface so we have a
194220
// mechanism for observing the actions.
195-
func clone(repository: RepositorySpecifier, at revision: Revision) throws -> AbsolutePath {
221+
func clone(repository: RepositorySpecifier, at revision: Revision, for version: Version? = nil) throws -> AbsolutePath {
196222
// Get the repository.
197223
let path = try fetch(repository: repository)
198224

@@ -202,7 +228,8 @@ public class Workspace {
202228

203229
// Write the state record.
204230
dependencyMap[repository] = ManagedDependency(
205-
repository: repository, subpath: path.relative(to: checkoutsPath), currentRevision: revision)
231+
repository: repository, subpath: path.relative(to: checkoutsPath),
232+
currentVersion: version, currentRevision: revision)
206233
try saveState()
207234

208235
return path
@@ -232,9 +259,7 @@ public class Workspace {
232259
// got this checkout via loading its manifest successfully.
233260
//
234261
// FIXME: Nevertheless, we should handle this failure explicitly.
235-
//
236-
// FIXME: We need to have the correct version to pass here.
237-
let manifest: Manifest = try! manifestLoader.load(packagePath: checkoutsPath.appending(managedDependency.subpath), baseURL: managedDependency.repository.url, version: nil)
262+
let manifest: Manifest = try! manifestLoader.load(packagePath: checkoutsPath.appending(managedDependency.subpath), baseURL: managedDependency.repository.url, version: managedDependency.currentVersion)
238263

239264
return KeyedPair(manifest, key: manifest.url)
240265
}

Tests/CommandsTests/WorkspaceTests.swift

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ extension Workspace {
3333
}
3434

3535
private let v1: Version = "1.0.0"
36-
private let v2: Version = "2.0.0"
3736

3837
final class WorkspaceTests: XCTestCase {
3938
func testBasics() throws {
@@ -104,7 +103,7 @@ final class WorkspaceTests: XCTestCase {
104103
//
105104
// Root
106105
// \ A: checked out (@v1)
107-
// \ AA: checked out (@v2)
106+
// \ AA: checked out (@v1)
108107
// \ B: missing
109108

110109
mktmpdir { path in
@@ -148,13 +147,12 @@ final class WorkspaceTests: XCTestCase {
148147
package: PackageDescription.Package(
149148
name: "AA"),
150149
products: [],
151-
version: v2
150+
version: v1
152151
)
153152
let mockManifestLoader = MockManifestLoader(manifests: [
154153
MockManifestLoader.Key(url: path.asString, version: nil): rootManifest,
155-
// FIXME: These versions are wrong, we aren't preserving versions currently.
156-
MockManifestLoader.Key(url: repos["A"]!.url, version: nil): aManifest,
157-
MockManifestLoader.Key(url: repos["AA"]!.url, version: nil): aaManifest
154+
MockManifestLoader.Key(url: repos["A"]!.url, version: v1): aManifest,
155+
MockManifestLoader.Key(url: repos["AA"]!.url, version: v1): aaManifest
158156
])
159157

160158
// Create the workspace.
@@ -163,15 +161,21 @@ final class WorkspaceTests: XCTestCase {
163161
// Ensure we have checkouts for A & AA.
164162
for name in ["A", "AA"] {
165163
let revision = try GitRepository(path: AbsolutePath(repos[name]!.url)).getCurrentRevision()
166-
_ = try workspace.clone(repository: repos[name]!, at: revision)
164+
_ = try workspace.clone(repository: repos[name]!, at: revision, for: v1)
167165
}
168166

169167
// Load the "current" manifests.
170168
let manifests = try workspace.loadDependencyManifests()
171169
XCTAssertEqual(manifests.root.package, rootManifest.package)
172-
XCTAssertEqual(manifests.dependencies.map{ $0.package.name }.sorted(), ["A", "AA"])
173-
174-
// FIXME: These manifests do not have the right versions in them, and they should.
170+
var dependencyManifests: [String: Manifest] = [:]
171+
for manifest in manifests.dependencies {
172+
dependencyManifests[manifest.package.name] = manifest
173+
}
174+
XCTAssertEqual(dependencyManifests.keys.sorted(), ["A", "AA"])
175+
XCTAssertEqual(dependencyManifests["A"]?.package, aManifest.package)
176+
XCTAssertEqual(dependencyManifests["A"]?.version, aManifest.version)
177+
XCTAssertEqual(dependencyManifests["AA"]?.package, aaManifest.package)
178+
XCTAssertEqual(dependencyManifests["AA"]?.version, aaManifest.version)
175179
}
176180
}
177181

0 commit comments

Comments
 (0)