Skip to content

Commit 445d2dc

Browse files
committed
WIP/SwiftLintCore: port the glob function to Windows
Windows does not support `glob` as a standard C library function as that is not part of the C standard. Attempt to emulate that through the use of `FindFirstFileW` and `FindNextFile` to iterate the matching files given a pattern. This should allow us to start enumerating the files as if we had `glob` available.
1 parent 9b1f56b commit 445d2dc

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed

Source/SwiftLintCore/Helpers/Glob.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,16 @@ private let globFunction = Darwin.glob
88
import Glibc
99

1010
private let globFunction = Glibc.glob
11+
#elseif canImport(ucrt)
12+
import ucrt
1113
#else
1214
#error("Unsupported platform")
1315
#endif
1416

17+
#if os(Windows)
18+
import WinSDK
19+
#endif
20+
1521
// Adapted from https://gist.github.com/efirestone/ce01ae109e08772647eb061b3bb387c3
1622

1723
struct Glob {
@@ -23,12 +29,35 @@ struct Glob {
2329

2430
return expandGlobstar(pattern: pattern)
2531
.reduce(into: [String]()) { paths, pattern in
32+
#if os(Windows)
33+
URL(fileURLWithPath: pattern).withUnsafeFileSystemRepresentation {
34+
var ffd: WIN32_FIND_DATAW = WIN32_FIND_DATAW()
35+
36+
let hDirectory: HANDLE = String(cString: $0!).withCString(encodedAs: UTF16.self) {
37+
FindFirstFileW($0, &ffd)
38+
}
39+
if hDirectory == INVALID_HANDLE_VALUE { return }
40+
defer { FindClose(hDirectory) }
41+
42+
repeat {
43+
let path: String = withUnsafePointer(to: &ffd.cFileName) {
44+
$0.withMemoryRebound(to: UInt16.self, capacity: MemoryLayout.size(ofValue: $0) / MemoryLayout<WCHAR>.size) {
45+
String(decodingCString: $0, as: UTF16.self)
46+
}
47+
}
48+
if path != "." && path != ".." {
49+
paths.append(path)
50+
}
51+
} while FindNextFileW(hDirectory, &ffd)
52+
}
53+
#else
2654
var globResult = glob_t()
2755
defer { globfree(&globResult) }
2856

2957
if globFunction(pattern, GLOB_TILDE | GLOB_BRACE | GLOB_MARK, nil, &globResult) == 0 {
3058
paths.append(contentsOf: populateFiles(globResult: globResult))
3159
}
60+
#endif
3261
}
3362
.unique
3463
.sorted()
@@ -91,6 +120,7 @@ struct Glob {
91120
return isDirectory && isDirectoryBool.boolValue
92121
}
93122

123+
#if !os(Windows)
94124
private static func populateFiles(globResult: glob_t) -> [String] {
95125
#if os(Linux)
96126
let matchCount = globResult.gl_pathc
@@ -101,4 +131,5 @@ struct Glob {
101131
globResult.gl_pathv[index].flatMap { String(validatingUTF8: $0) }
102132
}
103133
}
134+
#endif
104135
}

0 commit comments

Comments
 (0)