Skip to content

Commit b84362b

Browse files
authored
Allow relative path with swift package add-dependency command (#7871)
Enable passing relative path into `swift package add-dependency` ### Motivation: Currently only `AbsolutePath`s are supported with `--type path` flag ```bash swift package add-dependency /packagePath --type path ``` There is a need to support `RelativePath` because it's not uncommon to have a package structure inside of an xcodeproj as shown below. ```bash LocalPackages ├── ChildPackage │   ├── .gitignore │   ├── .swiftpm │   ├── Package.swift │   ├── Sources │   └── Tests └── ParentPackage    ├── .build    ├── .gitignore    ├── .swiftpm    ├── Package.swift    ├── Sources    └── Tests ``` If we want to open `ParentPackage` by itself, it will not be able to resolve that package. This pr allows for the user to add a package with a `RelativePath` path via the `swift package add-dependency --type path` command. Access level for - `.package(name:url:requirement:traits:)` - `.package(name:url:requirement:)` - `.package(id:requirement:traits:)` were upgraded from `private` to `package` allowing access to these functions from the `PackageCommands` module. ### Modifications: - Enable passing relative path into `swift package add-dependency` - Add unit test coverage ### Result: Both of the following commands are valid ```bash swift package add-dependency ../relative --type path ``` ```bash swift package add-dependency /absolute --type path ```
1 parent a86e9f9 commit b84362b

File tree

6 files changed

+137
-164
lines changed

6 files changed

+137
-164
lines changed

Sources/Commands/PackageCommands/AddDependency.swift

Lines changed: 11 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -66,24 +66,24 @@ extension SwiftPackageCommand {
6666
throw StringError("unknown package")
6767
}
6868

69-
switch type {
69+
switch self.type {
7070
case .url:
7171
try self.createSourceControlPackage(
7272
packagePath: packagePath,
7373
workspace: workspace,
74-
url: dependency
74+
url: self.dependency
7575
)
7676
case .path:
7777
try self.createFileSystemPackage(
7878
packagePath: packagePath,
7979
workspace: workspace,
80-
directory: dependency
80+
directory: self.dependency
8181
)
8282
case .registry:
8383
try self.createRegistryPackage(
8484
packagePath: packagePath,
8585
workspace: workspace,
86-
id: dependency
86+
id: self.dependency
8787
)
8888
}
8989
}
@@ -144,19 +144,10 @@ extension SwiftPackageCommand {
144144
}
145145
}
146146

147-
let packageDependency: PackageDependency = .sourceControl(
148-
identity: identity,
149-
nameForTargetDependencyResolutionOnly: nil,
150-
location: .remote(.init(url)),
151-
requirement: requirement,
152-
productFilter: .everything,
153-
traits: []
154-
)
155-
156-
try applyEdits(
147+
try self.applyEdits(
157148
packagePath: packagePath,
158149
workspace: workspace,
159-
packageDependency: packageDependency
150+
packageDependency: .sourceControl(name: nil, location: url, requirement: requirement)
160151
)
161152
}
162153

@@ -208,18 +199,10 @@ extension SwiftPackageCommand {
208199
}
209200
}
210201

211-
let packageDependency: PackageDependency = .registry(
212-
identity: identity,
213-
requirement: requirement,
214-
productFilter: .everything,
215-
traits: []
216-
)
217-
218-
219-
try applyEdits(
202+
try self.applyEdits(
220203
packagePath: packagePath,
221204
workspace: workspace,
222-
packageDependency: packageDependency
205+
packageDependency: .registry(id: id, requirement: requirement)
223206
)
224207
}
225208

@@ -228,29 +211,17 @@ extension SwiftPackageCommand {
228211
workspace: Workspace,
229212
directory: String
230213
) throws {
231-
guard let path = try? Basics.AbsolutePath(validating: directory) else {
232-
throw StringError("Package path not found")
233-
}
234-
let identity = PackageIdentity(path: path)
235-
let packageDependency: PackageDependency = .fileSystem(
236-
identity: identity,
237-
nameForTargetDependencyResolutionOnly: nil,
238-
path: path,
239-
productFilter: .everything,
240-
traits: []
241-
)
242-
243-
try applyEdits(
214+
try self.applyEdits(
244215
packagePath: packagePath,
245216
workspace: workspace,
246-
packageDependency: packageDependency
217+
packageDependency: .fileSystem(name: nil, path: directory)
247218
)
248219
}
249220

250221
private func applyEdits(
251222
packagePath: Basics.AbsolutePath,
252223
workspace: Workspace,
253-
packageDependency: PackageDependency
224+
packageDependency: MappablePackageDependency.Kind
254225
) throws {
255226
// Load the manifest file
256227
let fileSystem = workspace.fileSystem

Sources/PackageModelSyntax/AddPackageDependency.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import SwiftSyntax
1818
import SwiftSyntaxBuilder
1919

2020
/// Add a package dependency to a manifest's source code.
21-
public struct AddPackageDependency {
21+
public enum AddPackageDependency {
2222
/// The set of argument labels that can occur after the "dependencies"
2323
/// argument in the Package initializers.
2424
///
@@ -28,13 +28,13 @@ public struct AddPackageDependency {
2828
"targets",
2929
"swiftLanguageVersions",
3030
"cLanguageStandard",
31-
"cxxLanguageStandard"
31+
"cxxLanguageStandard",
3232
]
3333

3434
/// Produce the set of source edits needed to add the given package
3535
/// dependency to the given manifest file.
3636
public static func addPackageDependency(
37-
_ dependency: PackageDependency,
37+
_ dependency: MappablePackageDependency.Kind,
3838
to manifest: SourceFileSyntax
3939
) throws -> PackageEditResult {
4040
// Make sure we have a suitable tools version in the manifest.
@@ -50,19 +50,19 @@ public struct AddPackageDependency {
5050

5151
return PackageEditResult(
5252
manifestEdits: [
53-
.replace(packageCall, with: newPackageCall.description)
53+
.replace(packageCall, with: newPackageCall.description),
5454
]
5555
)
5656
}
5757

5858
/// Implementation of adding a package dependency to an existing call.
5959
static func addPackageDependencyLocal(
60-
_ dependency: PackageDependency,
60+
_ dependency: MappablePackageDependency.Kind,
6161
to packageCall: FunctionCallExprSyntax
6262
) throws -> FunctionCallExprSyntax {
6363
try packageCall.appendingToArrayArgument(
6464
label: "dependencies",
65-
trailingLabels: Self.argumentLabelsAfterDependencies,
65+
trailingLabels: self.argumentLabelsAfterDependencies,
6666
newElement: dependency.asSyntax()
6767
)
6868
}

Sources/PackageModelSyntax/AddTarget.swift

Lines changed: 34 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import SwiftSyntaxBuilder
1818
import struct TSCUtility.Version
1919

2020
/// Add a target to a manifest's source code.
21-
public struct AddTarget {
21+
public enum AddTarget {
2222
/// The set of argument labels that can occur after the "targets"
2323
/// argument in the Package initializers.
2424
///
@@ -27,7 +27,7 @@ public struct AddTarget {
2727
private static let argumentLabelsAfterTargets: Set<String> = [
2828
"swiftLanguageVersions",
2929
"cLanguageStandard",
30-
"cxxLanguageStandard"
30+
"cxxLanguageStandard",
3131
]
3232

3333
/// The kind of test harness to use. This isn't part of the manifest
@@ -85,7 +85,7 @@ public struct AddTarget {
8585
target.dependencies.append(contentsOf: macroTargetDependencies)
8686

8787
default:
88-
break;
88+
break
8989
}
9090

9191
var newPackageCall = try packageCall.appendingToArrayArgument(
@@ -103,7 +103,7 @@ public struct AddTarget {
103103
guard let outerDirectory else {
104104
return PackageEditResult(
105105
manifestEdits: [
106-
.replace(packageCall, with: newPackageCall.description)
106+
.replace(packageCall, with: newPackageCall.description),
107107
]
108108
)
109109
}
@@ -114,7 +114,7 @@ public struct AddTarget {
114114
var auxiliaryFiles: AuxiliaryFiles = []
115115

116116
// Add the primary source file. Every target type has this.
117-
addPrimarySourceFile(
117+
self.addPrimarySourceFile(
118118
outerPath: outerPath,
119119
target: target,
120120
configuration: configuration,
@@ -125,7 +125,7 @@ public struct AddTarget {
125125
var extraManifestEdits: [SourceEdit] = []
126126
switch target.type {
127127
case .macro:
128-
addProvidedMacrosSourceFile(
128+
self.addProvidedMacrosSourceFile(
129129
outerPath: outerPath,
130130
target: target,
131131
to: &auxiliaryFiles
@@ -135,7 +135,7 @@ public struct AddTarget {
135135
newPackageCall = try AddPackageDependency
136136
.addPackageDependencyLocal(
137137
.swiftSyntax(
138-
configuration: installedSwiftPMConfiguration
138+
configuration: installedSwiftPMConfiguration
139139
),
140140
to: newPackageCall
141141
)
@@ -149,7 +149,7 @@ public struct AddTarget {
149149
.positionAfterSkippingLeadingTrivia
150150
extraManifestEdits.append(
151151
SourceEdit(
152-
range: insertPos..<insertPos,
152+
range: insertPos ..< insertPos,
153153
replacement: newImport
154154
)
155155
)
@@ -158,12 +158,12 @@ public struct AddTarget {
158158
}
159159
}
160160

161-
default: break;
161+
default: break
162162
}
163163

164164
return PackageEditResult(
165165
manifestEdits: [
166-
.replace(packageCall, with: newPackageCall.description)
166+
.replace(packageCall, with: newPackageCall.description),
167167
] + extraManifestEdits,
168168
auxiliaryFiles: auxiliaryFiles
169169
)
@@ -182,20 +182,18 @@ public struct AddTarget {
182182
)
183183

184184
// Introduce imports for each of the dependencies that were specified.
185-
var importModuleNames = target.dependencies.map {
186-
$0.name
187-
}
185+
var importModuleNames = target.dependencies.map(\.name)
188186

189187
// Add appropriate test module dependencies.
190188
if target.type == .test {
191189
switch configuration.testHarness {
192-
case .none:
190+
case .none:
193191
break
194192

195193
case .xctest:
196194
importModuleNames.append("XCTest")
197195

198-
case .swiftTesting:
196+
case .swiftTesting:
199197
importModuleNames.append("Testing")
200198
}
201199
}
@@ -306,25 +304,25 @@ public struct AddTarget {
306304
}
307305
}
308306

309-
fileprivate extension TargetDescription.Dependency {
307+
extension TargetDescription.Dependency {
310308
/// Retrieve the name of the dependency
311-
var name: String {
309+
fileprivate var name: String {
312310
switch self {
313311
case .target(name: let name, condition: _),
314-
.byName(name: let name, condition: _),
315-
.product(name: let name, package: _, moduleAliases: _, condition: _):
312+
.byName(name: let name, condition: _),
313+
.product(name: let name, package: _, moduleAliases: _, condition: _):
316314
name
317315
}
318316
}
319317
}
320318

321319
/// The array of auxiliary files that can be added by a package editing
322320
/// operation.
323-
fileprivate typealias AuxiliaryFiles = [(RelativePath, SourceFileSyntax)]
321+
private typealias AuxiliaryFiles = [(RelativePath, SourceFileSyntax)]
324322

325-
fileprivate extension AuxiliaryFiles {
323+
extension AuxiliaryFiles {
326324
/// Add a source file to the list of auxiliary files.
327-
mutating func addSourceFile(
325+
fileprivate mutating func addSourceFile(
328326
path: RelativePath,
329327
sourceCode: SourceFileSyntax
330328
) {
@@ -334,45 +332,42 @@ fileprivate extension AuxiliaryFiles {
334332

335333
/// The set of dependencies we need to introduce to a newly-created macro
336334
/// target.
337-
fileprivate let macroTargetDependencies: [TargetDescription.Dependency] = [
335+
private let macroTargetDependencies: [TargetDescription.Dependency] = [
338336
.product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
339337
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
340338
]
341339

342340
/// The package dependency for swift-syntax, for use in macros.
343-
fileprivate extension PackageDependency {
341+
extension MappablePackageDependency.Kind {
344342
/// Source control URL for the swift-syntax package.
345-
static var swiftSyntaxURL: SourceControlURL {
343+
fileprivate static var swiftSyntaxURL: SourceControlURL {
346344
"https://github.com/swiftlang/swift-syntax.git"
347345
}
348346

349347
/// Package dependency on the swift-syntax package.
350-
static func swiftSyntax(
351-
configuration: InstalledSwiftPMConfiguration
352-
) -> PackageDependency {
348+
fileprivate static func swiftSyntax(
349+
configuration: InstalledSwiftPMConfiguration
350+
) -> MappablePackageDependency.Kind {
353351
let swiftSyntaxVersionDefault = configuration
354352
.swiftSyntaxVersionForMacroTemplate
355353
let swiftSyntaxVersion = Version(swiftSyntaxVersionDefault.description)!
356354

357355
return .sourceControl(
358-
identity: PackageIdentity(url: swiftSyntaxURL),
359-
nameForTargetDependencyResolutionOnly: nil,
360-
location: .remote(swiftSyntaxURL),
361-
requirement: .range(.upToNextMajor(from: swiftSyntaxVersion)),
362-
productFilter: .everything,
363-
traits: []
356+
name: nil,
357+
location: self.swiftSyntaxURL.absoluteString,
358+
requirement: .range(.upToNextMajor(from: swiftSyntaxVersion))
364359
)
365360
}
366361
}
367362

368-
fileprivate extension TargetDescription {
369-
var sanitizedName: String {
370-
name
363+
extension TargetDescription {
364+
fileprivate var sanitizedName: String {
365+
self.name
371366
.spm_mangledToC99ExtendedIdentifier()
372367
.localizedFirstWordCapitalized()
373368
}
374369
}
375370

376-
fileprivate extension String {
377-
func localizedFirstWordCapitalized() -> String { prefix(1).localizedCapitalized + dropFirst() }
371+
extension String {
372+
fileprivate func localizedFirstWordCapitalized() -> String { prefix(1).localizedCapitalized + dropFirst() }
378373
}

0 commit comments

Comments
 (0)