From fa18bddf8e2a92e24f6c0d489f097fedb3dba42f Mon Sep 17 00:00:00 2001 From: Dave Inglis Date: Fri, 5 Dec 2025 12:44:26 -0500 Subject: [PATCH] Fix some cases where AbsolutePath::relative(to: AbsolutePath) would assert - there where a couple case where relative(to:) would assert on windows when a path was long (>206) and when tailing slashes where not removed in some cases. --- Sources/TSCBasic/Path.swift | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Sources/TSCBasic/Path.swift b/Sources/TSCBasic/Path.swift index 208f9819..0be6cccc 100644 --- a/Sources/TSCBasic/Path.swift +++ b/Sources/TSCBasic/Path.swift @@ -515,13 +515,25 @@ private struct WindowsPath: Path, Sendable { } init(string: String) { + var path: String if string.first?.isASCII ?? false, string.first?.isLetter ?? false, string.first?.isLowercase ?? false, string.count > 1, string[string.index(string.startIndex, offsetBy: 1)] == ":" { - self.string = "\(string.first!.uppercased())\(string.dropFirst(1))" + path = "\(string.first!.uppercased())\(string.dropFirst(1))" } else { - self.string = string + path = string } + // There seems to be many assumptions around paths and trailing '\' + var substring = path[path.startIndex.. String { @@ -568,6 +580,7 @@ private struct WindowsPath: Path, Sendable { _ = string.withCString(encodedAs: UTF16.self) { root in name.withCString(encodedAs: UTF16.self) { path in PathAllocCombine(root, path, ULONG(PATHCCH_ALLOW_LONG_PATHS.rawValue), &result) + _ = PathCchStripPrefix(result, wcslen(result)) } } defer { LocalFree(result) } @@ -579,6 +592,7 @@ private struct WindowsPath: Path, Sendable { _ = string.withCString(encodedAs: UTF16.self) { root in relativePath.string.withCString(encodedAs: UTF16.self) { path in PathAllocCombine(root, path, ULONG(PATHCCH_ALLOW_LONG_PATHS.rawValue), &result) + _ = PathCchStripPrefix(result, wcslen(result)) } } defer { LocalFree(result) } @@ -965,8 +979,7 @@ extension AbsolutePath { preconditionFailure("invalid relative path computed from \(pathString)") } } - - assert(AbsolutePath(base, result) == self) + assert(AbsolutePath(base, result) == self, "\(AbsolutePath(base, result)) != \(self)") return result }