Skip to content

Commit d771063

Browse files
authored
Do not crash on relative file URLs in a dependency (#3603)
Currently, SwiftPM crashes when someone specifies the URL of a package dependency as a relative file URL. We should instead be able to just make it absolute based on the location of the package itself.
1 parent 17a8eb0 commit d771063

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

Sources/PackageLoading/PackageDescription4Loader.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ extension PackageDependencyDescription {
345345
} else if dependencyLocation.hasPrefix(filePrefix) {
346346
// FIXME: SwiftPM can't handle file locations with file:// scheme so we need to
347347
// strip that. We need to design a Location data structure for SwiftPM.
348-
return AbsolutePath(String(dependencyLocation.dropFirst(filePrefix.count))).pathString
348+
return AbsolutePath(String(dependencyLocation.dropFirst(filePrefix.count)), relativeTo: AbsolutePath(packageLocation)).pathString
349349
} else if URL.scheme(dependencyLocation) == nil {
350350
// If the dependency URL is not remote, try to "fix" it.
351351
// If the URL has no scheme, we treat it as a path (either absolute or relative to the base URL).

Tests/PackageLoadingTests/PD4_2LoadingTests.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,37 @@ class PackageDescription4_2LoadingTests: PackageDescriptionLoadingTests {
499499
}
500500
}
501501

502+
func testURLContainsNotAbsolutePath() throws {
503+
let stream = BufferedOutputByteStream()
504+
stream <<< """
505+
import PackageDescription
506+
let package = Package(
507+
name: "Trivial",
508+
dependencies: [
509+
.package(url: "file://../best", from: "1.0.0"),
510+
],
511+
targets: [
512+
.target(
513+
name: "foo",
514+
dependencies: []),
515+
]
516+
)
517+
"""
518+
519+
try loadManifestThrowing(stream.bytes) { manifest in
520+
if let dep = manifest.dependencies.first {
521+
switch dep {
522+
case .scm(let scm):
523+
XCTAssertEqual(scm.location, "/best")
524+
default:
525+
XCTFail("dependency was expected to be remote")
526+
}
527+
} else {
528+
XCTFail("manifest had no dependencies")
529+
}
530+
}
531+
}
532+
502533
func testCacheInvalidationOnEnv() throws {
503534
#if os(Linux)
504535
// rdar://79415639 (Test Case 'PackageDescription4_2LoadingTests.testCacheInvalidationOnEnv' failed)

0 commit comments

Comments
 (0)