Skip to content

Commit 2868726

Browse files
committed
Refactored ManagedDependency to make unmanaged path an associated value of edited state
1 parent c3860f1 commit 2868726

File tree

7 files changed

+189
-177
lines changed

7 files changed

+189
-177
lines changed

Sources/SPMTestSupport/MockWorkspace.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ public final class MockWorkspace {
437437
}
438438

439439
case checkout(CheckoutState)
440-
case edited(AbsolutePath?)
440+
case edited(EditedState)
441441
case local
442442
}
443443

@@ -476,8 +476,8 @@ public final class MockWorkspace {
476476
case .branch(let branch):
477477
XCTAssertEqual(dependencyCheckoutState.branch, branch, file: file, line: line)
478478
}
479-
case .edited(let path):
480-
if dependency.state != .edited(path) {
479+
case .edited(let editedState):
480+
if dependency.state != .edited(editedState) {
481481
XCTFail("Expected edited dependency; found '\(dependency.state)' instead", file: file, line: line)
482482
}
483483
case .local:

Sources/Workspace/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ add_library(Workspace
1010
DefaultPluginScriptRunner.swift
1111
Destination.swift
1212
Diagnostics.swift
13+
EditedState.swift
1314
Export.swift
1415
InitPackage.swift
1516
ManagedArtifact.swift

Sources/Workspace/EditedState.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2021 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
import TSCBasic
12+
13+
public enum EditedState: Equatable {
14+
/// An edited dependency with a managed path relative to the editables directory.
15+
case managed(RelativePath)
16+
17+
/// An edited dependency with an unmanaged, absolute path.
18+
case unmanaged(AbsolutePath)
19+
}

Sources/Workspace/ManagedDependency.swift

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public class ManagedDependency {
3232
/// If the path is non-nil, the dependency is managed by a user and is
3333
/// located at the path. In other words, this dependency is being used
3434
/// for top of the tree style development.
35-
case edited(AbsolutePath?)
35+
case edited(EditedState)
3636
}
3737

3838
/// The package reference.
@@ -67,17 +67,6 @@ public class ManagedDependency {
6767
/// unedit a package.
6868
public internal(set) var basedOn: ManagedDependency?
6969

70-
public init(
71-
packageRef: PackageReference,
72-
subpath: RelativePath,
73-
checkoutState: CheckoutState
74-
) {
75-
self.package = packageRef
76-
self.state = .checkout(checkoutState)
77-
self.basedOn = nil
78-
self.subpath = subpath
79-
}
80-
8170
/// Create a dependency present locally on the filesystem.
8271
public static func local(
8372
package: PackageReference
@@ -91,6 +80,32 @@ public class ManagedDependency {
9180
)
9281
}
9382

83+
/// Create an editable managed dependency based on a dependency which
84+
/// was *not* in edit state.
85+
public static func checkout(package: PackageReference, state: CheckoutState) -> ManagedDependency {
86+
// FIXME: Temporary until subpath property is removed
87+
let subpath: RelativePath
88+
if let path = try? AbsolutePath(validating: package.location),
89+
let lastPathComponent = path.components.last {
90+
subpath = RelativePath(lastPathComponent)
91+
} else {
92+
subpath = RelativePath(package.identity.description)
93+
}
94+
95+
return ManagedDependency(package: package, state: .checkout(state), subpath: subpath, basedOn: nil)
96+
}
97+
98+
/// Create an editable managed dependency based on a dependency which
99+
/// was *not* in edit state.
100+
public static func edited(basedOn dependency: ManagedDependency, state: EditedState) -> ManagedDependency {
101+
switch state {
102+
case .managed(let path):
103+
return ManagedDependency(package: dependency.package, state: .edited(state), subpath: path, basedOn: dependency)
104+
case .unmanaged:
105+
return ManagedDependency(package: dependency.package, state: .edited(state), subpath: dependency.subpath, basedOn: dependency)
106+
}
107+
}
108+
94109
internal init(
95110
package: PackageReference,
96111
state: State,
@@ -102,28 +117,6 @@ public class ManagedDependency {
102117
self.basedOn = basedOn
103118
self.state = state
104119
}
105-
106-
private init(
107-
basedOn dependency: ManagedDependency,
108-
subpath: RelativePath,
109-
unmanagedPath: AbsolutePath?
110-
) {
111-
assert(dependency.isCheckout)
112-
self.basedOn = dependency
113-
self.package = dependency.package
114-
self.subpath = subpath
115-
self.state = .edited(unmanagedPath)
116-
}
117-
118-
/// Create an editable managed dependency based on a dependency which
119-
/// was *not* in edit state.
120-
///
121-
/// - Parameters:
122-
/// - subpath: The subpath inside the editable directory.
123-
/// - unmanagedPath: A custom absolute path instead of the subpath.
124-
public func editedDependency(subpath: RelativePath, unmanagedPath: AbsolutePath?) -> ManagedDependency {
125-
return ManagedDependency(basedOn: self, subpath: subpath, unmanagedPath: unmanagedPath)
126-
}
127120
}
128121

129122
extension ManagedDependency: CustomStringConvertible {

Sources/Workspace/Workspace.swift

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,8 @@ extension Workspace {
10701070
}
10711071
}
10721072

1073+
let editedState: EditedState
1074+
10731075
// For unmanaged dependencies, create the symlink under editables dir.
10741076
if let path = path {
10751077
try fileSystem.createDirectory(self.location.editsDirectory)
@@ -1087,6 +1089,10 @@ extension Workspace {
10871089
// entry at this location.
10881090
try fileSystem.createSymbolicLink(symLinkPath, pointingAt: path, relative: false)
10891091
}
1092+
1093+
editedState = .unmanaged(path)
1094+
} else {
1095+
editedState = .managed(RelativePath(packageName))
10901096
}
10911097

10921098
// Remove the existing checkout.
@@ -1097,7 +1103,7 @@ extension Workspace {
10971103
}
10981104

10991105
// Save the new state.
1100-
state.dependencies.add(dependency.editedDependency(subpath: RelativePath(packageName), unmanagedPath: path))
1106+
state.dependencies.add(.edited(basedOn: dependency, state: editedState))
11011107
try state.saveState()
11021108
}
11031109

@@ -1108,27 +1114,17 @@ extension Workspace {
11081114
root: PackageGraphRootInput? = nil,
11091115
diagnostics: DiagnosticsEngine
11101116
) throws {
1111-
1112-
// Compute if we need to force remove.
1113-
var forceRemove = forceRemove
1114-
1115-
switch dependency.state {
1116-
// If the dependency isn't in edit mode, we can't unedit it.
1117-
case .checkout, .local:
1117+
guard case .edited(let editedState) = dependency.state else {
11181118
throw WorkspaceDiagnostics.DependencyNotInEditMode(dependencyName: dependency.package.name)
1119-
1120-
case .edited(let path):
1121-
if path != nil {
1122-
// Set force remove to true for unmanaged dependencies. Note that
1123-
// this only removes the symlink under the editable directory and
1124-
// not the actual unmanaged package.
1125-
forceRemove = true
1126-
}
11271119
}
11281120

1129-
// Form the edit working repo path.
11301121
let path = self.location.editsDirectory.appending(dependency.subpath)
1131-
// Check for uncommited and unpushed changes if force removal is off.
1122+
1123+
var forceRemove = forceRemove
1124+
if case .unmanaged = editedState {
1125+
forceRemove = true
1126+
}
1127+
11321128
if !forceRemove {
11331129
let workingCopy = try repositoryManager.openWorkingCopy(at: path)
11341130
guard !workingCopy.hasUncommittedChanges() else {
@@ -1138,6 +1134,7 @@ extension Workspace {
11381134
throw WorkspaceDiagnostics.UnpushedChanges(repositoryPath: path)
11391135
}
11401136
}
1137+
11411138
// Remove the editable checkout from disk.
11421139
if fileSystem.exists(path) {
11431140
try fileSystem.removeFileTree(path)
@@ -1148,10 +1145,10 @@ extension Workspace {
11481145
}
11491146

11501147
if case .checkout(let checkoutState) = dependency.basedOn?.state {
1151-
// Restore the original checkout.
1152-
//
1153-
// The clone method will automatically update the managed dependency state.
1154-
_ = try clone(package: dependency.package, at: checkoutState)
1148+
// Restore the original checkout.
1149+
//
1150+
// The clone method will automatically update the managed dependency state.
1151+
_ = try clone(package: dependency.package, at: checkoutState)
11551152
} else {
11561153
// The original dependency was removed, update the managed dependency state.
11571154
state.dependencies.remove(forURL: dependency.package.location)
@@ -1472,8 +1469,10 @@ extension Workspace {
14721469
switch dependency.state {
14731470
case .checkout:
14741471
return self.location.repositoriesCheckoutsDirectory.appending(dependency.subpath)
1475-
case .edited(let path):
1476-
return path ?? self.location.editsDirectory.appending(dependency.subpath)
1472+
case .edited(.managed(let subpath)):
1473+
return self.location.editsDirectory.appending(subpath)
1474+
case .edited(.unmanaged(let path)):
1475+
return path
14771476
case .local:
14781477
return AbsolutePath(dependency.package.location)
14791478
}
@@ -2784,10 +2783,7 @@ extension Workspace {
27842783
try? fileSystem.chmod(.userUnWritable, path: path, options: [.recursive, .onlyFiles])
27852784

27862785
// Write the state record.
2787-
state.dependencies.add(ManagedDependency(
2788-
packageRef: package,
2789-
subpath: path.relative(to: self.location.repositoriesCheckoutsDirectory),
2790-
checkoutState: checkoutState))
2786+
state.dependencies.add(.checkout(package: package, state: checkoutState))
27912787
try state.saveState()
27922788

27932789
delegate?.didCheckOut(repository: package.repository.url, revision: checkoutState.description, at: path, error: nil)

0 commit comments

Comments
 (0)