Skip to content

Commit 42f4bcf

Browse files
miggs597Miguel Perez
andauthored
Improved the error message when using a local package dependency as 'url:' instead of 'path:' (#3236)
Improved the error message when using a local package dependency as 'url:' instead of 'path:' rdar://69272273 Co-authored-by: Miguel Perez <[email protected]>
1 parent a783f11 commit 42f4bcf

File tree

9 files changed

+76
-4
lines changed

9 files changed

+76
-4
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// swift-tools-version:5.1
2+
import PackageDescription
3+
4+
let package = Package(
5+
name: "Bar",
6+
dependencies: [
7+
.package(url: "../Foo", from: "1.0.0"),
8+
],
9+
targets: [
10+
.target(name: "Bar", dependencies: ["Foo"], path: "./"),
11+
]
12+
)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import Foo
2+
3+
foo()
4+
print("here")
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public func foo() {
2+
{}()
3+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// swift-tools-version:4.2
2+
import PackageDescription
3+
4+
let package = Package(
5+
name: "Foo",
6+
products: [
7+
.library(name: "Foo", targets: ["Foo"]),
8+
],
9+
targets: [
10+
.target(name: "Foo", path: "./"),
11+
]
12+
)

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ let package = Package(
137137
.target(
138138
/** Package model conventions and loading support */
139139
name: "PackageLoading",
140-
dependencies: ["SwiftToolsSupport-auto", "Basics", "PackageModel"]),
140+
dependencies: ["SwiftToolsSupport-auto", "Basics", "PackageModel", "SourceControl"]),
141141

142142
// MARK: Package Dependency Resolution
143143

Sources/PackageLoading/PackageDescription4Loader.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import TSCBasic
1313
import TSCUtility
1414
import PackageModel
1515
import Foundation
16+
import SourceControl
1617

1718
enum ManifestJSONParser {
1819
struct Result {
@@ -361,13 +362,21 @@ extension PackageDependencyDescription {
361362
self = .local(identity: identity,
362363
name: name,
363364
path: path,
364-
productFilter: .everything)
365+
productFilter: .everything)
365366
// a package in a git location, may be a remote URL or on disk
366367
// TODO: consider refining the behavior + validation when the package is on disk
367368
// TODO: refactor this when adding registry support
368369
default:
369370
// location mapping (aka mirrors)
370371
let location = identityResolver.resolveLocation(from: location)
372+
373+
if let validPath = try? AbsolutePath(validating: location), fileSystem.exists(validPath) {
374+
let gitRepoProvider = GitRepositoryProvider()
375+
guard gitRepoProvider.isValidDirectory(location) else {
376+
throw StringError("Cannot clone from local directory \(location)\nPlease git init or use \"path:\" for \(location)")
377+
}
378+
}
379+
371380
// in the future this will check with the registries for the identity of the URL
372381
let identity = identityResolver.resolveIdentity(for: location)
373382
let requirement = try Requirement(v4: requirementJSON)

Sources/SPMTestSupport/misc.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import class Foundation.Bundle
3333
/// the name were a relative path.
3434
public func fixture(
3535
name: String,
36+
createGitRepo: Bool = true,
3637
file: StaticString = #file,
3738
line: UInt = #line,
3839
body: (AbsolutePath) throws -> Void
@@ -76,7 +77,9 @@ public func fixture(
7677
guard localFileSystem.isDirectory(srcDir) else { continue }
7778
let dstDir = tmpDirPath.appending(component: fileName)
7879
try systemQuietly("cp", "-R", "-H", srcDir.pathString, dstDir.pathString)
79-
initGitRepo(dstDir, tag: "1.2.3", addFile: false)
80+
if createGitRepo {
81+
initGitRepo(dstDir, tag: "1.2.3", addFile: false)
82+
}
8083
}
8184

8285
// Invoke the block, passing it the path of the copied fixture.

Sources/SourceControl/GitRepository.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,25 @@ public struct GitRepositoryProvider: RepositoryProvider {
8181
// expected cost of iterative updates on a full clone is less than on a
8282
// shallow clone.
8383
precondition(!localFileSystem.exists(path))
84+
8485
// FIXME: Ideally we should pass `--progress` here and report status regularly. We currently don't have callbacks for that.
8586
try self.callGit("clone", "--mirror", repository.url, path.pathString,
8687
repository: repository,
8788
failureMessage: "Failed to clone repository \(repository.url)")
8889
}
89-
90+
91+
public func isValidDirectory(_ directory: String) -> Bool {
92+
// Provides better feedback when mistakingly using url: for a dependency that
93+
// is a local package. Still allows for using url with a local package that has
94+
// also been initialized by git
95+
do {
96+
try self.callGit("-C", directory, "rev-parse", "--git-dir", repository: RepositorySpecifier(url: directory))
97+
return true
98+
} catch {
99+
return false
100+
}
101+
}
102+
90103
public func copy(from sourcePath: AbsolutePath, to destinationPath: AbsolutePath) throws {
91104
try localFileSystem.copy(from: sourcePath, to: destinationPath)
92105
}

Tests/FunctionalTests/MiscellaneousTests.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,23 @@ class MiscellaneousTestCase: XCTestCase {
421421
XCTAssert(output.contains("does not exist"), "Error from git was not propogated to process output: \(output)")
422422
}
423423
}
424+
425+
func testLocalPackageUsedAsURL() throws {
426+
fixture(name: "Miscellaneous/LocalPackageAsURL", createGitRepo: false) { prefix in
427+
// This fixture has a setup that is trying to use a local package
428+
// as a url that hasn't been initialized as a repo
429+
430+
// Launch swift-build.
431+
let app = prefix.appending(component: "Bar")
432+
433+
let result = try SwiftPMProduct.SwiftBuild.executeProcess([], packagePath: app)
424434

435+
XCTAssert(result.exitStatus != .terminated(code: 0))
436+
let output = try result.utf8stderrOutput()
437+
XCTAssert(output.contains("Cannot clone from local directory"), "Didn't find expected output: \(output)")
438+
}
439+
}
440+
425441
func testUnicode() {
426442
#if !os(Linux) && !os(Android) // TODO: - Linux has trouble with this and needs investigation.
427443
fixture(name: "Miscellaneous/Unicode") { prefix in

0 commit comments

Comments
 (0)