Skip to content

Commit f559cb5

Browse files
committed
Add downloaded constructor to ManagedDependency
Define helpers for paths to downloaded source archives
1 parent e534541 commit f559cb5

File tree

5 files changed

+74
-58
lines changed

5 files changed

+74
-58
lines changed

Sources/Workspace/Diagnostics.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ extension Diagnostic.Message {
129129
.warning("dependency '\(packageName)' was being edited but is missing; falling back to original checkout")
130130
}
131131

132+
static func downloadedDependencyMissing(packageName: String, version: Version) -> Diagnostic.Message {
133+
.warning("dependency '\(packageName)' was downloaded from a registry but is missing; downloading again")
134+
}
135+
132136
static func checkedOutDependencyMissing(packageName: String) -> Diagnostic.Message {
133137
.warning("dependency '\(packageName)' is missing; cloning again")
134138
}

Sources/Workspace/ManagedDependency.swift

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public struct ManagedDependency: Equatable {
3333
/// located at the path. In other words, this dependency is being used
3434
/// for top of the tree style development.
3535
case edited(basedOn: ManagedDependency, EditedState)
36+
37+
case downloaded(version: Version)
3638
}
3739

3840
/// The package reference.
@@ -49,12 +51,14 @@ public struct ManagedDependency: Equatable {
4951

5052
/// Returns true if the dependency is edited.
5153
public var isEdited: Bool {
52-
switch state {
53-
case .checkout, .local:
54-
return false
55-
case .edited:
56-
return true
57-
}
54+
if case .edited = state { return true }
55+
return false
56+
}
57+
58+
/// Returns true if the dependency is downloaded.
59+
public var isDownloaded: Bool {
60+
if case .downloaded = state { return true }
61+
return false
5862
}
5963

6064
/// Create a dependency present locally on the filesystem.
@@ -74,6 +78,12 @@ public struct ManagedDependency: Equatable {
7478
return ManagedDependency(package: dependency.package, state: .edited(basedOn: dependency, state))
7579
}
7680

81+
82+
/// Create a dependency downloaded from a registry.
83+
public static func downloaded(package: PackageReference, version: Version) -> ManagedDependency {
84+
return ManagedDependency(package: package, state: .downloaded(version: version))
85+
}
86+
7787
init(package: PackageReference, state: State) {
7888
self.package = package
7989
self.state = state

Sources/Workspace/Workspace.swift

Lines changed: 41 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,8 @@ extension Workspace {
989989
diagnostics.emit(error: "dependency '\(dependency.package.name)' already in edit mode")
990990
case .local:
991991
diagnostics.emit(error: "local dependency '\(dependency.package.name)' can't be edited")
992+
case .downloaded:
993+
diagnostics.emit(error: "dependency downloaded from registry '\(dependency.package.name)' can't be edited")
992994
}
993995
return nil
994996
}
@@ -1200,20 +1202,8 @@ fileprivate extension PinsStore {
12001202
///
12011203
/// This method does nothing if the dependency is in edited state.
12021204
func pin(_ dependency: ManagedDependency) {
1203-
1204-
// Get the checkout state.
1205-
let checkoutState: CheckoutState
1206-
switch dependency.state {
1207-
case .checkout(let state):
1208-
checkoutState = state
1209-
case .edited, .local:
1210-
return
1211-
}
1212-
1213-
self.pin(
1214-
packageRef: dependency.package,
1215-
state: checkoutState
1216-
)
1205+
guard case .checkout(let state) = dependency.state else { return }
1206+
self.pin(packageRef: dependency.package, state: state)
12171207
}
12181208
}
12191209

@@ -1325,10 +1315,10 @@ extension Workspace {
13251315
if checkout.isBranchOrRevisionBased {
13261316
result.insert(dependency.package)
13271317
}
1328-
case .edited:
1329-
continue
13301318
case .local:
13311319
result.insert(dependency.package)
1320+
default:
1321+
continue
13321322
}
13331323
}
13341324

@@ -1403,7 +1393,7 @@ extension Workspace {
14031393
requirement: .unversioned,
14041394
products: productFilter)
14051395
allConstraints.append(constraint)
1406-
case .checkout, .local:
1396+
default:
14071397
break
14081398
}
14091399
allConstraints += try externalManifest.dependencyConstraints(productFilter: productFilter)
@@ -1417,20 +1407,11 @@ extension Workspace {
14171407
var constraints = [PackageContainerConstraint]()
14181408

14191409
for (_, managedDependency, productFilter) in dependencies {
1420-
switch managedDependency.state {
1421-
case .checkout, .local: continue
1422-
case .edited: break
1423-
}
1424-
// FIXME: We shouldn't need to construct a new package reference object here.
1425-
// We should get the correct one from managed dependency object.
1426-
let ref = PackageReference.local(
1427-
identity: managedDependency.package.identity,
1428-
path: workspace.path(to: managedDependency)
1429-
)
1430-
let constraint = PackageContainerConstraint(
1431-
package: ref,
1432-
requirement: .unversioned,
1433-
products: productFilter)
1410+
guard case .edited = managedDependency.state else { continue }
1411+
1412+
let constraint = PackageContainerConstraint(package: managedDependency.package,
1413+
requirement: .unversioned,
1414+
products: productFilter)
14341415
constraints.append(constraint)
14351416
}
14361417
return constraints
@@ -1476,6 +1457,8 @@ extension Workspace {
14761457
return path
14771458
case .local:
14781459
return AbsolutePath(dependency.package.location)
1460+
case .downloaded(version: let version):
1461+
return self.location.sourceArchiveDirectory(for: dependency.package, at: version)
14791462
}
14801463
}
14811464

@@ -1619,6 +1602,9 @@ extension Workspace {
16191602
default:
16201603
version = .none
16211604
}
1605+
case .downloaded(version: let downloadedVersion):
1606+
packageKind = .remote
1607+
version = downloadedVersion
16221608
case .edited, .local:
16231609
packageKind = .local
16241610
version = .none
@@ -2077,15 +2063,13 @@ extension Workspace {
20772063
// We require cloning if there is no checkout or if the checkout doesn't
20782064
// match with the pin.
20792065
let requiredPins = pinsStore.pins.filter{ pin in
2080-
guard let dependency = state.dependencies[pin.packageRef.identity] else {
2081-
return true
2082-
}
2083-
switch dependency.state {
2084-
case .checkout(let checkoutState):
2085-
return pin.state != checkoutState
2086-
case .edited, .local:
2066+
guard let dependency = state.dependencies[pin.packageRef.identity],
2067+
case .checkout(let checkoutState) = dependency.state
2068+
else {
20872069
return true
20882070
}
2071+
2072+
return pin.state != checkoutState
20892073
}
20902074

20912075
// Clone the required pins.
@@ -2334,8 +2318,8 @@ extension Workspace {
23342318

23352319
for dependency in state.dependencies {
23362320
switch dependency.state {
2337-
case .checkout: break
2338-
case .edited, .local: continue
2321+
case .checkout, .downloaded: break
2322+
default: continue
23392323
}
23402324

23412325
let identity = dependency.package.identity
@@ -2488,6 +2472,8 @@ extension Workspace {
24882472
case .checkout:
24892473
let newState = PackageStateChange.State(requirement: .unversioned, products: products)
24902474
packageStateChanges[packageRef.location] = (packageRef, .updated(newState))
2475+
case .downloaded:
2476+
throw InternalError("downloaded package must be versioned")
24912477
}
24922478
} else {
24932479
let newState = PackageStateChange.State(requirement: .unversioned, products: products)
@@ -2536,16 +2522,16 @@ extension Workspace {
25362522
}
25372523

25382524
case .version(let version):
2539-
if let currentDependency = currentDependency {
2540-
if case .checkout(let checkoutState) = currentDependency.state, case .version(version, _) = checkoutState {
2541-
packageStateChanges[packageRef.location] = (packageRef, .unchanged)
2542-
} else {
2543-
let newState = PackageStateChange.State(requirement: .version(version), products: products)
2544-
packageStateChanges[packageRef.location] = (packageRef, .updated(newState))
2545-
}
2546-
} else {
2525+
switch currentDependency?.state {
2526+
case nil:
25472527
let newState = PackageStateChange.State(requirement: .version(version), products: products)
25482528
packageStateChanges[packageRef.location] = (packageRef, .added(newState))
2529+
case .checkout(.version(version, _))?,
2530+
.downloaded(version)?:
2531+
packageStateChanges[packageRef.location] = (packageRef, .unchanged)
2532+
default:
2533+
let newState = PackageStateChange.State(requirement: .version(version), products: products)
2534+
packageStateChanges[packageRef.location] = (packageRef, .updated(newState))
25492535
}
25502536
}
25512537
}
@@ -2634,6 +2620,10 @@ extension Workspace {
26342620

26352621
diagnostics.emit(.editedDependencyMissing(packageName: dependency.package.name))
26362622

2623+
case .downloaded(version: let version):
2624+
_ = try temp_await { registryManager?.downloadSourceArchive(for: version, of: dependency.package, into: fileSystem, at: path(to: dependency), expectedChecksum: nil, on: .sharedConcurrent, completion: $0) }
2625+
diagnostics.emit(.downloadedDependencyMissing(packageName: dependency.package.name, version: version))
2626+
26372627
case .local:
26382628
state.dependencies.remove(dependency)
26392629
try state.saveState()
@@ -2842,13 +2832,10 @@ extension Workspace {
28422832
// a local package.
28432833
//
28442834
// Note that we don't actually remove a local package from disk.
2845-
switch dependency.state {
2846-
case .local:
2835+
if case .local = dependency.state {
28472836
state.dependencies.remove(dependency)
28482837
try state.saveState()
28492838
return
2850-
case .checkout, .edited:
2851-
break
28522839
}
28532840

28542841
// Inform the delegate.
@@ -2913,6 +2900,8 @@ extension Workspace {
29132900
result.append("edited")
29142901
case .local?:
29152902
result.append("versioned")
2903+
case .downloaded?:
2904+
result.append("downloaded")
29162905
case nil:
29172906
result.append("root")
29182907
}

Sources/Workspace/WorkspaceConfiguration.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,17 @@ extension Workspace {
5959
self.workingDirectory.appending(component: "artifacts")
6060
}
6161

62+
/// Path to store the dependencies downloaded from a registry.
63+
public var sourceArchivesDirectory: AbsolutePath {
64+
self.workingDirectory.appending(component: "source-archives")
65+
}
66+
67+
/// Returns the path to the repository checkout directory for a managed dependency.
68+
public func sourceArchiveDirectory(for package: PackageReference, at version: Version) -> AbsolutePath {
69+
self.sourceArchivesDirectory.appending(subpath(for: package))
70+
.appending(component: version.description.lowercased())
71+
}
72+
6273
/// Path to the shared repositories cache.
6374
public var sharedRepositoriesCacheDirectory: AbsolutePath? {
6475
self.sharedCacheDirectory.map { $0.appending(component: "repositories") }

Sources/Workspace/WorkspaceState.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ fileprivate struct WorkspaceStateStorage {
243243
case .managed:
244244
try nestedContainer.encodeNil(forKey: .path)
245245
}
246+
case .downloaded(version: let version):
247+
fatalError("Not implemented") // FIXME
246248
}
247249
}
248250

0 commit comments

Comments
 (0)