Skip to content

Commit a279f53

Browse files
committed
Various improvements
1 parent 8fd9767 commit a279f53

File tree

1 file changed

+25
-8
lines changed

1 file changed

+25
-8
lines changed

Sources/TSCBasic/Path.swift

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -434,12 +434,17 @@ private struct UNIXPath: Path {
434434
static let root = UNIXPath(string: "/")
435435

436436
static func isValidComponent(_ name: String) -> Bool {
437+
#if os(Windows)
438+
if name.contains("\\") {
439+
return false
440+
}
441+
#endif
437442
return name != "" && name != "." && name != ".." && !name.contains("/")
438443
}
439444

440445
#if os(Windows)
441446
static func isAbsolutePath(_ path: String) -> Bool {
442-
return !path.withCString(encodedAs: UTF16.self, PathIsRelativeW)
447+
return !path.prenormalized().withCString(encodedAs: UTF16.self, PathIsRelativeW)
443448
}
444449
#endif
445450

@@ -541,13 +546,13 @@ private struct UNIXPath: Path {
541546

542547
init(normalizingAbsolutePath path: String) {
543548
#if os(Windows)
544-
var result: PWSTR?
549+
var result: [WCHAR] = Array<WCHAR>(repeating: 0, count: Int(MAX_PATH + 1))
545550
defer { LocalFree(result) }
546551

547-
_ = path.withCString(encodedAs: UTF16.self) {
548-
PathAllocCanonicalize($0, ULONG(PATHCCH_ALLOW_LONG_PATHS.rawValue), &result)
552+
_ = path.prenormalized().withCString(encodedAs: UTF16.self) {
553+
PathCchCanonicalize($0, result.length, $0)
549554
}
550-
self.init(string: String(decodingCString: result!, as: UTF16.self))
555+
self.init(string: String(decodingCString: result, as: UTF16.self))
551556
#else
552557
precondition(path.first == "/", "Failure normalizing \(path), absolute paths should start with '/'")
553558

@@ -615,7 +620,7 @@ private struct UNIXPath: Path {
615620
let pathSeparator: Character
616621
#if os(Windows)
617622
pathSeparator = "\\"
618-
let path = path.replacingOccurrences(of: "/", with: "\\")
623+
let path = path.prenormalized()
619624
#else
620625
pathSeparator = "/"
621626
#endif
@@ -683,7 +688,9 @@ private struct UNIXPath: Path {
683688

684689
init(validatingAbsolutePath path: String) throws {
685690
#if os(Windows)
686-
guard path != "" else {
691+
// Explicitly handle the empty path, since retrieving
692+
// `fileSystemRepresentation` of it is illegal.
693+
guard !path.isEmpty else {
687694
throw PathValidationError.invalidAbsolutePath(path)
688695
}
689696
let fsr: UnsafePointer<Int8> = path.fileSystemRepresentation
@@ -708,7 +715,9 @@ private struct UNIXPath: Path {
708715

709716
init(validatingRelativePath path: String) throws {
710717
#if os(Windows)
711-
guard path != "" else {
718+
// Explicitly handle the empty path, since retrieving
719+
// `fileSystemRepresentation` of it is illegal.
720+
guard !path.isEmpty else {
712721
self.init(normalizingRelativePath: path)
713722
return
714723
}
@@ -946,3 +955,11 @@ private func mayNeedNormalization(absolute string: String) -> Bool {
946955
}
947956
return false
948957
}
958+
959+
#if os(Windows)
960+
fileprivate extension String {
961+
func prenormalized() -> String {
962+
return self.replacingOccurrences(of: "/", with: "\\")
963+
}
964+
}
965+
#endif

0 commit comments

Comments
 (0)