Skip to content

Commit 935980c

Browse files
authored
Fix discrepancies with usage of package display name/package identity in swift package edit command (#7941)
Fixes #7931 `swift package edit` was reliant on the user-passed `packageName` argument to be able to both find the dependency (which needs the identity) as well as to match the manifest display name. Default to treating the user-passed argument as a package identity, and fix the comparisons made to the manifest by instead assuring that the canonical locations for the manifest and the dependency match. The display name was intended to be deprecated. ### Motivation: The vscode-swift extension made use of of the package identities when listing dependencies in its UI. When a user would execute a `Use Local Version` on one of these dependencies, it would call `swift package edit <package-name>` under the hood, using the identity for the package-name argument. However, this would fail as the `edit` command would also treat the package name argument as the package's manifest `displayName`, which is not guaranteed to match the identity. ### Modifications: Treat the user-passed argument as the package identity, and deprecate the usage of `displayName` in the `edit` command. Fix any necessary test cases to follow suite with this change. ### Result: The`edit` command should now be using the package identity, and there should no longer be any discrepancies.
1 parent 909779a commit 935980c

File tree

6 files changed

+77
-87
lines changed

6 files changed

+77
-87
lines changed

Sources/Commands/PackageCommands/EditCommands.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@ extension SwiftPackageCommand {
3232
@Option(help: "Create or use the checkout at this path")
3333
var path: AbsolutePath?
3434

35-
@Argument(help: "The name of the package to edit")
36-
var packageName: String
35+
@Argument(help: "The identity of the package to edit")
36+
var packageIdentity: String
3737

3838
func run(_ swiftCommandState: SwiftCommandState) async throws {
3939
try await swiftCommandState.resolve()
4040
let workspace = try swiftCommandState.getActiveWorkspace()
4141

4242
// Put the dependency in edit mode.
4343
await workspace.edit(
44-
packageName: packageName,
44+
packageIdentity: packageIdentity,
4545
path: path,
4646
revision: revision,
4747
checkoutBranch: checkoutBranch,
@@ -61,15 +61,15 @@ extension SwiftPackageCommand {
6161
help: "Unedit the package even if it has uncommitted and unpushed changes")
6262
var shouldForceRemove: Bool = false
6363

64-
@Argument(help: "The name of the package to unedit")
65-
var packageName: String
64+
@Argument(help: "The identity of the package to unedit")
65+
var packageIdentity: String
6666

6767
func run(_ swiftCommandState: SwiftCommandState) async throws {
6868
try await swiftCommandState.resolve()
6969
let workspace = try swiftCommandState.getActiveWorkspace()
7070

7171
try await workspace.unedit(
72-
packageName: packageName,
72+
packageIdentity: packageIdentity,
7373
forceRemove: shouldForceRemove,
7474
root: swiftCommandState.getWorkspaceRoot(),
7575
observabilityScope: swiftCommandState.observabilityScope

Sources/Workspace/Workspace+Editing.swift

+11-11
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ import struct SourceControl.Revision
2121
extension Workspace {
2222
/// Edit implementation.
2323
func _edit(
24-
packageName: String,
24+
packageIdentity: String,
2525
path: AbsolutePath? = nil,
2626
revision: Revision? = nil,
2727
checkoutBranch: String? = nil,
2828
observabilityScope: ObservabilityScope
2929
) async throws {
3030
// Look up the dependency and check if we can edit it.
31-
guard let dependency = self.state.dependencies[.plain(packageName)] else {
32-
observabilityScope.emit(.dependencyNotFound(packageName: packageName))
31+
guard let dependency = self.state.dependencies[.plain(packageIdentity)] else {
32+
observabilityScope.emit(.dependencyNotFound(packageName: packageIdentity))
3333
return
3434
}
3535

@@ -58,10 +58,10 @@ extension Workspace {
5858

5959
// If a path is provided then we use it as destination. If not, we
6060
// use the folder with packageName inside editablesPath.
61-
let destination = path ?? self.location.editsDirectory.appending(component: packageName)
61+
let destination = path ?? self.location.editsDirectory.appending(component: packageIdentity)
6262

6363
// If there is something present at the destination, we confirm it has
64-
// a valid manifest with name same as the package we are trying to edit.
64+
// a valid manifest with name canonical location as the package we are trying to edit.
6565
if fileSystem.exists(destination) {
6666
// FIXME: this should not block
6767
let manifest = try await withCheckedThrowingContinuation { continuation in
@@ -77,23 +77,23 @@ extension Workspace {
7777
)
7878
}
7979

80-
guard manifest.displayName == packageName else {
80+
guard dependency.packageRef.canonicalLocation == manifest.canonicalPackageLocation else {
8181
return observabilityScope
8282
.emit(
83-
error: "package at '\(destination)' is \(manifest.displayName) but was expecting \(packageName)"
83+
error: "package at '\(destination)' is \(dependency.packageRef.identity) but was expecting \(packageIdentity)"
8484
)
8585
}
8686

8787
// Emit warnings for branch and revision, if they're present.
8888
if let checkoutBranch {
8989
observabilityScope.emit(.editBranchNotCheckedOut(
90-
packageName: packageName,
90+
packageName: packageIdentity,
9191
branchName: checkoutBranch
9292
))
9393
}
9494
if let revision {
9595
observabilityScope.emit(.editRevisionNotUsed(
96-
packageName: packageName,
96+
packageName: packageIdentity,
9797
revisionIdentifier: revision.identifier
9898
))
9999
}
@@ -135,7 +135,7 @@ extension Workspace {
135135
try fileSystem.createDirectory(self.location.editsDirectory)
136136
// FIXME: We need this to work with InMem file system too.
137137
if !(fileSystem is InMemoryFileSystem) {
138-
let symLinkPath = self.location.editsDirectory.appending(component: packageName)
138+
let symLinkPath = self.location.editsDirectory.appending(component: packageIdentity)
139139

140140
// Cleanup any existing symlink.
141141
if fileSystem.isSymlink(symLinkPath) {
@@ -158,7 +158,7 @@ extension Workspace {
158158

159159
// Save the new state.
160160
try self.state.dependencies.add(
161-
dependency.edited(subpath: RelativePath(validating: packageName), unmanagedPath: path)
161+
dependency.edited(subpath: RelativePath(validating: packageIdentity), unmanagedPath: path)
162162
)
163163
try self.state.save()
164164
}

Sources/Workspace/Workspace.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -597,23 +597,23 @@ extension Workspace {
597597
/// Puts a dependency in edit mode creating a checkout in editables directory.
598598
///
599599
/// - Parameters:
600-
/// - packageName: The name of the package to edit.
600+
/// - packageIdentity: The identity of the package to edit.
601601
/// - path: If provided, creates or uses the checkout at this location.
602602
/// - revision: If provided, the revision at which the dependency
603603
/// should be checked out to otherwise current revision.
604604
/// - checkoutBranch: If provided, a new branch with this name will be
605605
/// created from the revision provided.
606606
/// - observabilityScope: The observability scope that reports errors, warnings, etc
607607
public func edit(
608-
packageName: String,
608+
packageIdentity: String,
609609
path: AbsolutePath? = nil,
610610
revision: Revision? = nil,
611611
checkoutBranch: String? = nil,
612612
observabilityScope: ObservabilityScope
613613
) async {
614614
do {
615615
try await self._edit(
616-
packageName: packageName,
616+
packageIdentity: packageIdentity,
617617
path: path,
618618
revision: revision,
619619
checkoutBranch: checkoutBranch,
@@ -636,13 +636,13 @@ extension Workspace {
636636
/// - root: The workspace root. This is used to resolve the dependencies post unediting.
637637
/// - observabilityScope: The observability scope that reports errors, warnings, etc
638638
public func unedit(
639-
packageName: String,
639+
packageIdentity: String,
640640
forceRemove: Bool,
641641
root: PackageGraphRootInput,
642642
observabilityScope: ObservabilityScope
643643
) async throws {
644-
guard let dependency = self.state.dependencies[.plain(packageName)] else {
645-
observabilityScope.emit(.dependencyNotFound(packageName: packageName))
644+
guard let dependency = self.state.dependencies[.plain(packageIdentity)] else {
645+
observabilityScope.emit(.dependencyNotFound(packageName: packageIdentity))
646646
return
647647
}
648648

Sources/_InternalTestSupport/MockWorkspace.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ public final class MockWorkspace {
372372
}
373373

374374
public func checkEdit(
375-
packageName: String,
375+
packageIdentity: String,
376376
path: AbsolutePath? = nil,
377377
revision: Revision? = nil,
378378
checkoutBranch: String? = nil,
@@ -382,7 +382,7 @@ public final class MockWorkspace {
382382
await observability.topScope.trap {
383383
let ws = try self.getOrCreateWorkspace()
384384
await ws.edit(
385-
packageName: packageName,
385+
packageIdentity: packageIdentity,
386386
path: path,
387387
revision: revision,
388388
checkoutBranch: checkoutBranch,
@@ -393,7 +393,7 @@ public final class MockWorkspace {
393393
}
394394

395395
public func checkUnedit(
396-
packageName: String,
396+
packageIdentity: String,
397397
roots: [String],
398398
forceRemove: Bool = false,
399399
_ result: ([Basics.Diagnostic]) -> Void
@@ -403,7 +403,7 @@ public final class MockWorkspace {
403403
let rootInput = PackageGraphRootInput(packages: try rootPaths(for: roots))
404404
let ws = try self.getOrCreateWorkspace()
405405
try await ws.unedit(
406-
packageName: packageName,
406+
packageIdentity: packageIdentity,
407407
forceRemove: forceRemove,
408408
root: rootInput,
409409
observabilityScope: observability.topScope

Sources/_InternalTestSupport/PackageGraphTester.swift

-10
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,10 @@ public final class PackageGraphResult {
2828
self.graph = graph
2929
}
3030

31-
// TODO: deprecate / transition to PackageIdentity
32-
public func check(roots: String..., file: StaticString = #file, line: UInt = #line) {
33-
XCTAssertEqual(graph.rootPackages.map{$0.manifest.displayName }.sorted(), roots.sorted(), file: file, line: line)
34-
}
35-
3631
public func check(roots: PackageIdentity..., file: StaticString = #file, line: UInt = #line) {
3732
XCTAssertEqual(graph.rootPackages.map{$0.identity }.sorted(), roots.sorted(), file: file, line: line)
3833
}
3934

40-
// TODO: deprecate / transition to PackageIdentity
41-
public func check(packages: String..., file: StaticString = #file, line: UInt = #line) {
42-
XCTAssertEqual(graph.packages.map {$0.manifest.displayName }.sorted(), packages.sorted(), file: file, line: line)
43-
}
44-
4535
public func check(packages: PackageIdentity..., file: StaticString = #file, line: UInt = #line) {
4636
XCTAssertEqual(graph.packages.map {$0.identity }.sorted(), packages.sorted(), file: file, line: line)
4737
}

0 commit comments

Comments
 (0)