diff options
author | 2017-02-16 18:11:19 +0000 | |
---|---|---|
committer | 2017-02-17 14:51:57 +0000 | |
commit | 748f8af16b2648faa9569ae7bc77d93a7a2fbd67 (patch) | |
tree | a0038e8dd57bf1f0134e156f399476f5c55a6c0d /src/main/cpp | |
parent | 1210a2053fd44497bc04bba0bbd434d907cfe486 (diff) |
Bazel client, Windows: impl. ForEachDirectoryEntry
This is the last function we needed from
file_posix for MSYS, so now we can remove that
from the compilation.
Fixes https://github.com/bazelbuild/bazel/issues/2386
The problem originally was that I used CloseHandle
to close the HANDLE, instead of using FindClose,
so we were holding on to open directory HANDLEs,
so we couldn't rename the installation directory.
See https://github.com/bazelbuild/bazel/issues/2107
--
Change-Id: If6c1b3c99cf386d82e829dbee2323e6bce5f6b46
Reviewed-on: https://cr.bazel.build/8952
PiperOrigin-RevId: 147734165
MOS_MIGRATED_REVID=147734165
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()) { |