Skip to content

Add swift package add-target-dependency command to edit the manifest #7594

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ if ProcessInfo.processInfo.environment["SWIFTCI_DISABLE_SDK_DEPENDENT_TESTS"] ==
"Build",
"Commands",
"PackageModel",
"PackageModelSyntax",
"PackageRegistryCommand",
"SourceControl",
"SPMTestSupport",
Expand Down
1 change: 1 addition & 0 deletions Sources/Commands/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ add_library(Commands
PackageCommands/AddDependency.swift
PackageCommands/AddProduct.swift
PackageCommands/AddTarget.swift
PackageCommands/AddTargetDependency.swift
PackageCommands/APIDiff.swift
PackageCommands/ArchiveSource.swift
PackageCommands/CompletionCommand.swift
Expand Down
89 changes: 89 additions & 0 deletions Sources/Commands/PackageCommands/AddTargetDependency.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2014-2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import ArgumentParser
import Basics
import CoreCommands
import PackageModel
import PackageModelSyntax
import SwiftParser
import SwiftSyntax
import TSCBasic
import TSCUtility
import Workspace

extension SwiftPackageCommand {
struct AddTargetDependency: SwiftCommand {
package static let configuration = CommandConfiguration(
abstract: "Add a new target dependency to the manifest")

@OptionGroup(visibility: .hidden)
var globalOptions: GlobalOptions

@Argument(help: "The name of the new dependency")
var dependencyName: String

@Argument(help: "The name of the target to update")
var targetName: String

@Option(help: "The package in which the dependency resides")
var package: String?

func run(_ swiftCommandState: SwiftCommandState) throws {
let workspace = try swiftCommandState.getActiveWorkspace()

guard let packagePath = try swiftCommandState.getWorkspaceRoot().packages.first else {
throw StringError("unknown package")
}

// Load the manifest file
let fileSystem = workspace.fileSystem
let manifestPath = packagePath.appending("Package.swift")
let manifestContents: ByteString
do {
manifestContents = try fileSystem.readFileContents(manifestPath)
} catch {
throw StringError("cannot find package manifest in \(manifestPath)")
}

// Parse the manifest.
let manifestSyntax = manifestContents.withData { data in
data.withUnsafeBytes { buffer in
buffer.withMemoryRebound(to: UInt8.self) { buffer in
Parser.parse(source: buffer)
}
}
}

let dependency: TargetDescription.Dependency
if let package {
dependency = .product(name: dependencyName, package: package)
} else {
dependency = .target(name: dependencyName, condition: nil)
}

let editResult = try PackageModelSyntax.AddTargetDependency.addTargetDependency(
dependency,
targetName: targetName,
to: manifestSyntax
)

try editResult.applyEdits(
to: fileSystem,
manifest: manifestSyntax,
manifestPath: manifestPath,
verbose: !globalOptions.logging.quiet
)
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public struct SwiftPackageCommand: AsyncParsableCommand {
AddDependency.self,
AddProduct.self,
AddTarget.self,
AddTargetDependency.self,
Clean.self,
PurgeCache.self,
Reset.self,
Expand Down
32 changes: 32 additions & 0 deletions Tests/CommandsTests/PackageCommandTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,38 @@ final class PackageCommandTests: CommandsTestCase {
}
}

func testPackageAddTargetDependency() throws {
try testWithTemporaryDirectory { tmpPath in
let fs = localFileSystem
let path = tmpPath.appending("PackageB")
try fs.createDirectory(path)

try fs.writeFileContents(path.appending("Package.swift"), string:
"""
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "client",
targets: [ .target(name: "library") ]
)
"""
)
try localFileSystem.writeFileContents(path.appending(components: "Sources", "library", "library.swift"), string:
"""
public func Foo() { }
"""
)

_ = try execute(["add-target-dependency", "--package", "other-package", "other-product", "library"], packagePath: path)

let manifest = path.appending("Package.swift")
XCTAssertFileExists(manifest)
let contents: String = try fs.readFileContents(manifest)

XCTAssertMatch(contents, .contains(#".product(name: "other-product", package: "other-package"#))
}
}

func testPackageAddProduct() throws {
try testWithTemporaryDirectory { tmpPath in
let fs = localFileSystem
Expand Down