Skip to content

Commit a76104d

Browse files
authored
[windows] path: drop the trailing backslash before invoking PathCchRe… (#479)
1 parent 12fa2cf commit a76104d

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

Sources/TSCBasic/Path.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,21 @@ private struct WindowsPath: Path, Sendable {
461461
let fsr: UnsafePointer<Int8> = self.string.fileSystemRepresentation
462462
defer { fsr.deallocate() }
463463

464-
let path: String = String(cString: fsr)
464+
var path: String = String(cString: fsr)
465+
// PathCchRemoveFileSpec removes trailing '\' for a
466+
// path like 'c:\root\path\', which doesn't give us the parent
467+
// directory name. Thus, drop the trailing '\' before calling
468+
// PathCchRemoveFileSpec.
469+
var substring = path[path.startIndex..<path.endIndex]
470+
while !substring.isEmpty && substring.utf8.last == UInt8(ascii: "\\") {
471+
substring = substring.dropLast()
472+
}
473+
if !substring.isEmpty && substring.last != ":" {
474+
// Drop the trailing '\', unless the string path only
475+
// has '\', and unless the slashes are right after the drive letter.
476+
path = String(substring)
477+
}
478+
465479
return path.withCString(encodedAs: UTF16.self) {
466480
let data = UnsafeMutablePointer(mutating: $0)
467481
PathCchRemoveFileSpec(data, path.count)

Tests/TSCBasicTests/PathTests.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,15 @@ class PathTests: XCTestCase {
131131
XCTAssertEqual(RelativePath("abc").dirname, ".")
132132
XCTAssertEqual(RelativePath("").dirname, ".")
133133
XCTAssertEqual(RelativePath(".").dirname, ".")
134+
#if os(Windows)
135+
XCTAssertEqual(AbsolutePath("C:\\a\\b").dirname, "C:\\a")
136+
XCTAssertEqual(AbsolutePath("C:\\").dirname, "C:\\")
137+
XCTAssertEqual(AbsolutePath("C:\\\\").dirname, "C:\\")
138+
XCTAssertEqual(AbsolutePath("C:\\\\\\").dirname, "C:\\")
139+
XCTAssertEqual(AbsolutePath("C:\\a\\b\\").dirname, "C:\\a")
140+
XCTAssertEqual(AbsolutePath("C:\\a\\b\\\\").dirname, "C:\\a")
141+
XCTAssertEqual(AbsolutePath("C:\\a\\").dirname, "C:\\")
142+
#endif
134143
}
135144

136145
func testBaseNameExtraction() {

0 commit comments

Comments
 (0)