diff options
Diffstat (limited to 'src/main/cpp')
-rw-r--r-- | src/main/cpp/util/BUILD | 4 | ||||
-rw-r--r-- | src/main/cpp/util/file_posix.cc | 6 | ||||
-rw-r--r-- | src/main/cpp/util/file_windows.cc | 40 |
3 files changed, 35 insertions, 15 deletions
diff --git a/src/main/cpp/util/BUILD b/src/main/cpp/util/BUILD index b044d19537..b5c7b79d54 100644 --- a/src/main/cpp/util/BUILD +++ b/src/main/cpp/util/BUILD @@ -27,10 +27,6 @@ cc_library( name = "file", srcs = ["file.cc"] + select({ "//src:windows": [ - # TODO(bazel-team): implement functions in file_windows.cc and use - # more and more of them under MSYS until we can completely stop - # using file_posix.cc at which point remove it from this list. - "file_posix.cc", "file_windows.cc", ], "//src:windows_msvc": [ diff --git a/src/main/cpp/util/file_posix.cc b/src/main/cpp/util/file_posix.cc index b59618201b..30fd8cd9e3 100644 --- a/src/main/cpp/util/file_posix.cc +++ b/src/main/cpp/util/file_posix.cc @@ -34,11 +34,6 @@ namespace blaze_util { using std::pair; using std::string; -// TODO(bazel-team): implement all functions in file_windows.cc, use them from -// MSYS, remove file_posix.cc from the `srcs` of -// //src/main/cpp/util:file when building for MSYS, and remove all -// #ifndef __CYGWIN__ directives. -#ifndef __CYGWIN__ // Runs "stat" on `path`. Returns -1 and sets errno if stat fails or // `path` isn't a directory. If check_perms is true, this will also // make sure that `path` is owned by the current user and has `mode` @@ -371,7 +366,6 @@ string GetCwd() { bool ChangeDirectory(const string& path) { return chdir(path.c_str()) == 0; } -#endif // not __CYGWIN__ void ForEachDirectoryEntry(const string &path, DirectoryEntryConsumer *consume) { diff --git a/src/main/cpp/util/file_windows.cc b/src/main/cpp/util/file_windows.cc index c92b76ba7c..26cc47df65 100644 --- a/src/main/cpp/util/file_windows.cc +++ b/src/main/cpp/util/file_windows.cc @@ -1074,14 +1074,44 @@ 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 kUncPrefix(L"\\\\?\\"); + static const wstring kDot(L"."); + static const wstring kDotDot(L".."); + // Always add an UNC prefix to ensure we can work with long paths. + if (!windows_util::HasUncPrefix(wpath.c_str())) { + wpath = kUncPrefix + wpath; + } + // Unconditionally add a trailing backslash. We know `wpath` has no trailing + // backslash because it comes from AsWindowsPath whose output is always + // normalized (see NormalizeWindowsPath). + wpath.append(L"\\"); + WIN32_FIND_DATAW metadata; + HANDLE handle = ::FindFirstFileW((wpath + L"*").c_str(), &metadata); + if (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, &metadata)); + ::FindClose(handle); } -#else // not COMPILER_MSVC -#endif // COMPILER_MSVC string NormalizeWindowsPath(string path) { if (path.empty()) { |