Skip to content

Commit 0c07485

Browse files
committed
Remove use of AbsolutePath.appending(RelativePath(_:))
This replaces the use of `AbsolutePath.appending(RelativePath(_:))` in the code base in favour of `AbsolutPath(_:relativeTo:)`. This form allows us to compute the absolute path prior to the normalization of the path which ensures that we can validate the path properly. This is particular important to enable the use of relative paths on Windows which cannot normalize at the parent path without a reference as there may be substitutions which need to be applied.
1 parent f40a368 commit 0c07485

17 files changed

+41
-39
lines changed

Sources/Build/BuildPlan.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,8 @@ public final class ClangTargetBuildDescription {
330330
return sources.flatMap { (root, relativePaths) in
331331
relativePaths.map { source in
332332
let path = root.appending(source)
333-
let object = tempsPath.appending(RelativePath("\(source.pathString).o"))
334-
let deps = tempsPath.appending(RelativePath("\(source.pathString).d"))
333+
let object = AbsolutePath("\(source.pathString).o", relativeTo: tempsPath)
334+
let deps = AbsolutePath("\(source.pathString).d", relativeTo: tempsPath)
335335
return (source, path, object, deps)
336336
}
337337
}
@@ -420,7 +420,7 @@ public final class ClangTargetBuildDescription {
420420
// Header search paths.
421421
let headerSearchPaths = scope.evaluate(.HEADER_SEARCH_PATHS)
422422
flags += headerSearchPaths.map({
423-
"-I\(target.sources.root.appending(RelativePath($0)).pathString)"
423+
"-I\(AbsolutePath($0, relativeTo: target.sources.root).pathString)"
424424
})
425425

426426
// Other C flags.
@@ -555,7 +555,9 @@ public final class SwiftTargetBuildDescription {
555555
/// The objects in this target.
556556
public var objects: [AbsolutePath] {
557557
let relativePaths = target.sources.relativePaths + derivedSources.relativePaths + pluginDerivedSources.relativePaths
558-
return relativePaths.map{ tempsPath.appending(RelativePath("\($0.pathString).o")) }
558+
return relativePaths.map {
559+
AbsolutePath("\($0.pathString).o", relativeTo: tempsPath)
560+
}
559561
}
560562

561563
/// The path to the swiftmodule file after compilation.
@@ -1073,7 +1075,7 @@ public final class SwiftTargetBuildDescription {
10731075
// Header search paths.
10741076
let headerSearchPaths = scope.evaluate(.HEADER_SEARCH_PATHS)
10751077
flags += headerSearchPaths.flatMap({ path -> [String] in
1076-
return ["-Xcc", "-I\(target.sources.root.appending(RelativePath(path)).pathString)"]
1078+
return ["-Xcc", "-I\(AbsolutePath(path, relativeTo: target.sources.root).pathString)"]
10771079
})
10781080

10791081
// Other C flags.

Sources/Commands/SwiftPackageTool.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1873,7 +1873,7 @@ extension SwiftPackageTool {
18731873
}
18741874

18751875
let files = try fileSystem.getDirectoryContents(directory)
1876-
.map { directory.appending(RelativePath($0)) }
1876+
.map { AbsolutePath($0, relativeTo: directory) }
18771877
.filter { fileSystem.isFile($0) }
18781878

18791879
guard let fileExtension = fileExtension else {
@@ -1888,7 +1888,7 @@ extension SwiftPackageTool {
18881888
return []
18891889
}
18901890
return try fileSystem.getDirectoryContents(directory)
1891-
.map { directory.appending(RelativePath($0)) }
1891+
.map { AbsolutePath($0, relativeTo: directory) }
18921892
.filter { fileSystem.isDirectory($0) }
18931893
}
18941894

Sources/PackageLoading/ManifestJSONParser.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ enum ManifestJSONParser {
215215
private static func sanitizeDependencyLocation(fileSystem: TSCBasic.FileSystem, packageKind: PackageReference.Kind, dependencyLocation: String) throws -> String {
216216
if dependencyLocation.hasPrefix("~/") {
217217
// If the dependency URL starts with '~/', try to expand it.
218-
return fileSystem.homeDirectory.appending(RelativePath(String(dependencyLocation.dropFirst(2)))).pathString
218+
return AbsolutePath(String(dependencyLocation.dropFirst(2)), relativeTo: fileSystem.homeDirectory).pathString
219219
} else if dependencyLocation.hasPrefix(filePrefix) {
220220
// FIXME: SwiftPM can't handle file locations with file:// scheme so we need to
221221
// strip that. We need to design a Location data structure for SwiftPM.

Sources/PackageLoading/MinimumDeploymentTarget.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public struct MinimumDeploymentTarget {
4545
static func computeXCTestMinimumDeploymentTarget(with runResult: ProcessResult, platform: PackageModel.Platform) throws -> PlatformVersion? {
4646
guard let output = try runResult.utf8Output().spm_chuzzle() else { return nil }
4747
let sdkPath = try AbsolutePath(validating: output)
48-
let xcTestPath = sdkPath.appending(RelativePath("Developer/Library/Frameworks/XCTest.framework/XCTest"))
48+
let xcTestPath = AbsolutePath("Developer/Library/Frameworks/XCTest.framework/XCTest", relativeTo: sdkPath)
4949
return try computeMinimumDeploymentTarget(of: xcTestPath, platform: platform)
5050
}
5151

Sources/PackageLoading/TargetSourcesBuilder.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public struct TargetSourcesBuilder {
7979
let actualAdditionalRules = (toolsVersion <= ToolsVersion.v5_4 ? FileRuleDescription.xcbuildFileTypes : additionalFileRules)
8080
self.rules = FileRuleDescription.builtinRules + actualAdditionalRules
8181
self.toolsVersion = toolsVersion
82-
let excludedPaths = target.exclude.map{ path.appending(RelativePath($0)) }
82+
let excludedPaths = target.exclude.map { AbsolutePath($0, relativeTo: path) }
8383
self.excludedPaths = Set(excludedPaths)
8484
self.opaqueDirectoriesExtensions = FileRuleDescription.opaqueDirectoriesExtensions.union(
8585
additionalFileRules.reduce(into: Set<String>(), { partial, item in
@@ -94,7 +94,7 @@ public struct TargetSourcesBuilder {
9494
return metadata
9595
}
9696

97-
let declaredSources = target.sources?.map{ path.appending(RelativePath($0)) }
97+
let declaredSources = target.sources?.map { AbsolutePath($0, relativeTo: path) }
9898
if let declaredSources = declaredSources {
9999
// Diagnose duplicate entries.
100100
let duplicates = declaredSources.spm_findDuplicateElements()
@@ -190,7 +190,7 @@ public struct TargetSourcesBuilder {
190190

191191
// First match any resources explicitly declared in the manifest file.
192192
for declaredResource in target.resources {
193-
let resourcePath = self.targetPath.appending(RelativePath(declaredResource.path))
193+
let resourcePath = AbsolutePath(declaredResource.path, relativeTo: self.targetPath)
194194
if path.isDescendantOfOrEqual(to: resourcePath) {
195195
if matchedRule != .none {
196196
self.observabilityScope.emit(error: "duplicate resource rule '\(declaredResource.rule)' found for file at '\(path)'")
@@ -334,7 +334,7 @@ public struct TargetSourcesBuilder {
334334

335335
private func diagnoseInvalidResource(in resources: [TargetDescription.Resource]) {
336336
resources.forEach { resource in
337-
let resourcePath = self.targetPath.appending(RelativePath(resource.path))
337+
let resourcePath = AbsolutePath(resource.path, relativeTo: self.targetPath)
338338
if let message = validTargetPath(at: resourcePath), self.packageKind.emitAuthorWarnings {
339339
let warning = "Invalid Resource '\(resource.path)': \(message)."
340340
self.observabilityScope.emit(warning: warning)
@@ -423,7 +423,7 @@ public struct TargetSourcesBuilder {
423423

424424
// Check if the directory is marked to be copied.
425425
let directoryMarkedToBeCopied = target.resources.contains{ resource in
426-
let resourcePath = self.targetPath.appending(RelativePath(resource.path))
426+
let resourcePath = AbsolutePath(resource.path, relativeTo: self.targetPath)
427427
if resource.rule == .copy && resourcePath == path {
428428
return true
429429
}

Sources/SPMBuildCore/BinaryTarget+Extensions.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ extension BinaryTarget {
5353
}
5454
// Construct a LibraryInfo for the library.
5555
let libraryDir = self.artifactPath.appending(component: library.libraryIdentifier)
56-
let libraryFile = libraryDir.appending(RelativePath(library.libraryPath))
57-
let headersDir = library.headersPath.map{ libraryDir.appending(RelativePath($0)) }
56+
let libraryFile = AbsolutePath(library.libraryPath, relativeTo: libraryDir)
57+
let headersDir = library.headersPath.map { AbsolutePath($0, relativeTo: libraryDir) }
5858
return [LibraryInfo(libraryPath: libraryFile, headersPath: headersDir)]
5959
}
6060

@@ -75,7 +75,7 @@ extension BinaryTarget {
7575
return tripleStrings.contains(triple.tripleString)
7676
}
7777
}.map{
78-
ExecutableInfo(name: entry.key, executablePath: self.artifactPath.appending(RelativePath($0.path)))
78+
ExecutableInfo(name: entry.key, executablePath: AbsolutePath($0.path, relativeTo: self.artifactPath))
7979
}
8080
}
8181
}

Sources/SPMBuildCore/Toolchain.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ extension Toolchain {
4444
}
4545

4646
public var macosSwiftStdlib: AbsolutePath {
47-
return resolveSymlinks(swiftCompiler).appending(RelativePath("../../lib/swift/macosx"))
47+
return AbsolutePath("../../lib/swift/macosx", relativeTo: resolveSymlinks(swiftCompiler))
4848
}
4949

5050
public var toolchainLibDir: AbsolutePath {
5151
// FIXME: Not sure if it's better to base this off of Swift compiler or our own binary.
52-
return resolveSymlinks(swiftCompiler).appending(RelativePath("../../lib"))
52+
return AbsolutePath("../../lib", relativeTo: resolveSymlinks(swiftCompiler))
5353
}
5454
}

Sources/SPMTestSupport/MockRegistry.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ private struct MockRegistryArchiver: Archiver {
348348
let rootPath = lines[1]
349349
for path in lines[2..<lines.count] {
350350
let relativePath = String(path.dropFirst(rootPath.count + 1))
351-
let targetPath = destinationPath.appending(component: "package").appending(RelativePath(relativePath))
351+
let targetPath = AbsolutePath(relativePath, relativeTo: destinationPath.appending(component: "package"))
352352
if !self.fileSystem.exists(targetPath.parentDirectory) {
353353
try self.fileSystem.createDirectory(targetPath.parentDirectory, recursive: true)
354354
}

Sources/SPMTestSupport/MockWorkspace.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ public final class MockWorkspace {
9898
}
9999

100100
public func pathToRoot(withName name: String) -> AbsolutePath {
101-
return self.rootsDir.appending(RelativePath(name))
101+
return AbsolutePath(name, relativeTo: self.rootsDir)
102102
}
103103

104104
public func pathToPackage(withName name: String) -> AbsolutePath {
105-
return self.packagesDir.appending(RelativePath(name))
105+
return AbsolutePath(name, relativeTo: self.packagesDir)
106106
}
107107

108108
private func create() throws {
@@ -294,7 +294,7 @@ public final class MockWorkspace {
294294
}
295295

296296
public func rootPaths(for packages: [String]) -> [AbsolutePath] {
297-
return packages.map { rootsDir.appending(RelativePath($0)) }
297+
return packages.map { AbsolutePath($0, relativeTo: rootsDir) }
298298
}
299299

300300
public func checkEdit(

Sources/SPMTestSupport/misc.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public func fixture(
5757

5858
// Construct the expected path of the fixture.
5959
// FIXME: This seems quite hacky; we should provide some control over where fixtures are found.
60-
let fixtureDir = AbsolutePath(#file).appending(RelativePath("../../../Fixtures")).appending(fixtureSubpath)
60+
let fixtureDir = AbsolutePath("../../../Fixtures", relativeTo: AbsolutePath(#file)).appending(fixtureSubpath)
6161

6262
// Check that the fixture is really there.
6363
guard localFileSystem.isDirectory(fixtureDir) else {

Sources/Workspace/InitPackage.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ public final class InitPackage {
299299
try makeDirectories(moduleDir)
300300

301301
let sourceFileName = "\(typeName).swift"
302-
let sourceFile = moduleDir.appending(RelativePath(sourceFileName))
302+
let sourceFile = AbsolutePath(sourceFileName, relativeTo: moduleDir)
303303

304304
let content: String
305305
switch packageType {
@@ -412,11 +412,11 @@ public final class InitPackage {
412412
}
413413

414414
private func writeTestFileStubs(testsPath: AbsolutePath) throws {
415-
let testModule = testsPath.appending(RelativePath(pkgname + Target.testModuleNameSuffix))
415+
let testModule = AbsolutePath(pkgname + Target.testModuleNameSuffix, relativeTo: testsPath)
416416
progressReporter?("Creating \(testModule.relative(to: destinationPath))/")
417417
try makeDirectories(testModule)
418418

419-
let testClassFile = testModule.appending(RelativePath("\(moduleName)Tests.swift"))
419+
let testClassFile = AbsolutePath("\(moduleName)Tests.swift", relativeTo: testModule)
420420
switch packageType {
421421
case .systemModule, .empty, .manifest, .`extension`: break
422422
case .library:

Sources/Workspace/UserToolchain.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,8 @@ public final class UserToolchain: Toolchain {
279279
.appending(component: "Library")
280280
.appending(component: "XCTest-\(info.defaults.xctestVersion)")
281281
xctest = [
282-
"-I", path.appending(RelativePath("usr/lib/swift/windows/\(triple.arch)")).pathString,
283-
"-L", path.appending(RelativePath("usr/lib/swift/windows")).pathString,
282+
"-I", AbsolutePath("usr/lib/swift/windows/\(triple.arch)", relativeTo: path).pathString,
283+
"-L", AbsolutePath("usr/lib/swift/windows", relativeTo: path).pathString,
284284
]
285285

286286
extraSwiftCFlags = info.defaults.extraSwiftCFlags ?? []

Sources/Workspace/Workspace.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,7 @@ extension Workspace {
977977
// Remove all but protected paths.
978978
let contentsToRemove = Set(contents).subtracting(protectedAssets)
979979
for name in contentsToRemove {
980-
try? fileSystem.removeFileTree(self.location.scratchDirectory.appending(RelativePath(name)))
980+
try? fileSystem.removeFileTree(AbsolutePath(name, relativeTo: self.location.scratchDirectory))
981981
}
982982
}
983983

Sources/XCBuildSupport/PIFBuilder.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -864,7 +864,7 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder {
864864
for assignment in assignments {
865865
var value = assignment.value
866866
if setting == .HEADER_SEARCH_PATHS {
867-
value = value.map { target.sources.root.appending(RelativePath($0)).pathString }
867+
value = value.map { AbsolutePath($0, relativeTo: target.sources.root).pathString }
868868
}
869869

870870
if let platforms = assignment.platforms {

Sources/XCBuildSupport/XcodeBuildSystem.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public final class XcodeBuildSystem: SPMBuildCore.BuildSystem {
8080
} else {
8181
let xcodeSelectOutput = try Process.popen(args: "xcode-select", "-p").utf8Output().spm_chomp()
8282
let xcodeDirectory = try AbsolutePath(validating: xcodeSelectOutput)
83-
xcbuildPath = xcodeDirectory.appending(RelativePath("../SharedFrameworks/XCBuild.framework/Versions/A/Support/xcbuild"))
83+
xcbuildPath = AbsolutePath("../SharedFrameworks/XCBuild.framework/Versions/A/Support/xcbuild", relativeTo: xcodeDirectory)
8484
}
8585

8686
guard fileSystem.exists(xcbuildPath) else {

Sources/Xcodeproj/SchemesGenerator.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,12 @@ public final class SchemesGenerator {
206206
207207
"""
208208

209-
let file = schemesDir.appending(RelativePath(scheme.filename))
209+
let file = AbsolutePath(scheme.filename, relativeTo: schemesDir)
210210
try fs.writeFileContents(file, bytes: stream.bytes)
211211
}
212212

213213
private func disableSchemeAutoCreation() throws {
214-
let workspacePath = schemesDir.appending(RelativePath("../../project.xcworkspace"))
214+
let workspacePath = AbsolutePath("../../project.xcworkspace", relativeTo: schemesDir)
215215

216216
// Write the settings file to disable automatic scheme creation.
217217
var stream = BufferedOutputByteStream()
@@ -225,12 +225,12 @@ public final class SchemesGenerator {
225225
</dict>
226226
</plist>
227227
"""
228-
let settingsPlist = workspacePath.appending(RelativePath("xcshareddata/WorkspaceSettings.xcsettings"))
228+
let settingsPlist = AbsolutePath("xcshareddata/WorkspaceSettings.xcsettings", relativeTo: workspacePath)
229229
try fs.createDirectory(settingsPlist.parentDirectory, recursive: true)
230230
try fs.writeFileContents(settingsPlist, bytes: stream.bytes)
231231

232232
// Write workspace contents file.
233-
let contentsFile = workspacePath.appending(RelativePath("contents.xcworkspacedata"))
233+
let contentsFile = AbsolutePath("contents.xcworkspacedata", relativeTo: workspacePath)
234234
stream = BufferedOutputByteStream()
235235
stream <<< """
236236
<?xml version="1.0" encoding="UTF-8"?>

Sources/Xcodeproj/generate.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public enum XcodeProject {
6464
// Determine the path of the .xcodeproj wrapper directory.
6565
public static func makePath(outputDir: AbsolutePath, projectName: String) -> AbsolutePath {
6666
let xcodeprojName = "\(projectName).xcodeproj"
67-
return outputDir.appending(RelativePath(xcodeprojName))
67+
return AbsolutePath(xcodeprojName, relativeTo: outputDir)
6868
}
6969

7070
/// Generates an Xcode project and all needed support files. The .xcodeproj
@@ -144,7 +144,7 @@ public enum XcodeProject {
144144
///// For framework targets, generate target.c99Name_Info.plist files in the
145145
///// directory that Xcode project is generated
146146
let name = target.infoPlistFileName
147-
try open(xcodeprojPath.appending(RelativePath(name))) { print in
147+
try open(AbsolutePath(name, relativeTo: xcodeprojPath)) { print in
148148
print("""
149149
<?xml version="1.0" encoding="UTF-8"?>
150150
<plist version="1.0">
@@ -244,7 +244,7 @@ public enum XcodeProject {
244244
// -Package so its name doesn't collide with any products or target with
245245
// same name.
246246
let schemeName = "\(graph.rootPackages[0].manifest.displayName)-Package.xcscheme" // TODO: use identity instead?
247-
try open(schemesDir.appending(RelativePath(schemeName))) { stream in
247+
try open(AbsolutePath(schemeName, relativeTo: schemesDir)) { stream in
248248
legacySchemeGenerator(
249249
container: schemeContainer,
250250
graph: graph,

0 commit comments

Comments
 (0)