aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main
diff options
context:
space:
mode:
authorGravatar Laszlo Csomor <laszlocsomor@google.com>2017-01-20 10:05:18 +0000
committerGravatar Vladimir Moskva <vladmos@google.com>2017-01-20 12:21:39 +0000
commitd5527469ca629f806a7576783289cc0613bf418b (patch)
treecc2716786b0e2f6092ba5515f9af997ef7a98705 /src/main
parent9a338502f625756a046301a98f209cae8ec675aa (diff)
Bazel client, Windows: impl. ForEachDirectoryEntry
Implement ForEachDirectoryEntry on Windows using FindFirstFileW / FindNextFileW. Supports long paths and traversing junctions. See https://github.com/bazelbuild/bazel/issues/2107 See https://github.com/bazelbuild/bazel/issues/2181 -- PiperOrigin-RevId: 145062749 MOS_MIGRATED_REVID=145062749
Diffstat (limited to 'src/main')
-rw-r--r--src/main/cpp/util/file_posix.cc2
-rw-r--r--src/main/cpp/util/file_windows.cc33
2 files changed, 29 insertions, 6 deletions
diff --git a/src/main/cpp/util/file_posix.cc b/src/main/cpp/util/file_posix.cc
index a1d806a9d9..c45eb3915c 100644
--- a/src/main/cpp/util/file_posix.cc
+++ b/src/main/cpp/util/file_posix.cc
@@ -364,7 +364,6 @@ string GetCwd() {
bool ChangeDirectory(const string& path) {
return chdir(path.c_str()) == 0;
}
-#endif // not __CYGWIN__
void ForEachDirectoryEntry(const string &path,
DirectoryEntryConsumer *consume) {
@@ -398,5 +397,6 @@ void ForEachDirectoryEntry(const string &path,
closedir(dir);
}
+#endif // not __CYGWIN__
} // namespace blaze_util
diff --git a/src/main/cpp/util/file_windows.cc b/src/main/cpp/util/file_windows.cc
index b1fadddf4a..bea092d9ff 100644
--- a/src/main/cpp/util/file_windows.cc
+++ b/src/main/cpp/util/file_windows.cc
@@ -993,14 +993,37 @@ bool ChangeDirectory(const string& path) {
return true;
}
-#ifdef COMPILER_MSVC
void ForEachDirectoryEntry(const string &path,
DirectoryEntryConsumer *consume) {
- // TODO(bazel-team): implement this.
- pdie(255, "blaze_util::ForEachDirectoryEntry is not implemented on Windows");
+ wstring wpath;
+ if (path.empty() || IsDevNull(path)) {
+ return;
+ }
+ if (!AsWindowsPath(path, &wpath)) {
+ pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
+ "ForEachDirectoryEntry(%s): AsWindowsPath failed", path.c_str());
+ }
+
+ static const wstring kDot(L".");
+ static const wstring kDotDot(L"..");
+
+ wpath = L"\\\\?\\" + wpath + L"\\";
+ WIN32_FIND_DATAW metadata;
+ windows_util::AutoHandle handle(
+ FindFirstFileW((wpath + L"*").c_str(), &metadata));
+ if (handle.handle == INVALID_HANDLE_VALUE) {
+ return; // directory does not exist or is empty
+ }
+
+ do {
+ if (kDot != metadata.cFileName && kDotDot != metadata.cFileName) {
+ wstring wname = wpath + metadata.cFileName;
+ string name(WstringToCstring(/* omit prefix */ 4 + wname.c_str()).get());
+ bool is_dir = (metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
+ consume->Consume(name, is_dir);
+ }
+ } while (FindNextFileW(handle.handle, &metadata));
}
-#else // not COMPILER_MSVC
-#endif // COMPILER_MSVC
string NormalizeWindowsPath(string path) {
if (path.empty()) {