diff options
author | 2017-01-12 13:09:35 +0000 | |
---|---|---|
committer | 2017-01-12 14:08:41 +0000 | |
commit | f257130b7701c37585d8015f27e1d75131b37166 (patch) | |
tree | 4d0215f13c366f2719096a19eed20e02892f2e9c /src/main/cpp/util | |
parent | 45f15aa2b365d8dc2253ded5758cf22c81ebfc1f (diff) |
Bazel client, Windows: implement MakeDirectories
See https://github.com/bazelbuild/bazel/issues/2107
See https://github.com/bazelbuild/bazel/issues/1744
--
PiperOrigin-RevId: 144313301
MOS_MIGRATED_REVID=144313301
Diffstat (limited to 'src/main/cpp/util')
-rw-r--r-- | src/main/cpp/util/file_posix.cc | 12 | ||||
-rw-r--r-- | src/main/cpp/util/file_windows.cc | 54 |
2 files changed, 53 insertions, 13 deletions
diff --git a/src/main/cpp/util/file_posix.cc b/src/main/cpp/util/file_posix.cc index 02c0fa8055..55d62a2211 100644 --- a/src/main/cpp/util/file_posix.cc +++ b/src/main/cpp/util/file_posix.cc @@ -34,6 +34,11 @@ 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` @@ -119,11 +124,6 @@ static bool MakeDirectories(const string &path, mode_t mode, bool childmost) { return stat_succeeded; } -// 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__ class PosixPipe : public IPipe { public: PosixPipe(int recv_socket, int send_socket) @@ -295,6 +295,7 @@ bool SetMtimeMillisec(const string& path, time_t mtime) { return utime(path.c_str(), ×) == 0; } +#ifndef __CYGWIN__ // mkdir -p path. Returns true if the path was created or already exists and // could // be chmod-ed to exactly the given permissions. If final part of the path is a @@ -305,7 +306,6 @@ bool MakeDirectories(const string &path, unsigned int mode) { return MakeDirectories(path, mode, true); } -#ifndef __CYGWIN__ string GetCwd() { char cwdbuf[PATH_MAX]; if (getcwd(cwdbuf, sizeof cwdbuf) == NULL) { diff --git a/src/main/cpp/util/file_windows.cc b/src/main/cpp/util/file_windows.cc index d213b64179..3b2553ad1b 100644 --- a/src/main/cpp/util/file_windows.cc +++ b/src/main/cpp/util/file_windows.cc @@ -28,6 +28,7 @@ namespace blaze_util { +using std::basic_string; using std::pair; using std::string; using std::unique_ptr; @@ -54,6 +55,10 @@ static bool UnlinkPathW(const wstring& path); // Like `AsWindowsPath` but the result is absolute and has UNC prefix if needed. static bool AsWindowsPathWithUncPrefix(const string& path, wstring* wpath); +static bool IsRootDirectoryW(const wstring& path); + +static bool MakeDirectoriesW(const wstring& path); + // Returns a normalized form of the input `path`. // // `path` must be a relative or absolute Windows path, it may use "/" instead of @@ -161,7 +166,9 @@ IPipe* CreatePipe() { // If `must_be_root` is true, then in addition to being absolute, the path must // also be just the root part, no other components, e.g. "c:\" is both absolute // and root, but "c:\foo" is just absolute. -static bool IsRootOrAbsolute(const string& path, bool must_be_root) { +template <typename char_type> +static bool IsRootOrAbsolute(const basic_string<char_type>& path, + bool must_be_root) { // An absolute path is one that starts with "/", "\", "c:/", "c:\", // "\\?\c:\", or rarely "\??\c:\" or "\\.\c:\". // @@ -693,14 +700,47 @@ bool SetMtimeMillisec(const string& path, time_t mtime) { #else // not COMPILER_MSVC #endif // COMPILER_MSVC -#ifdef COMPILER_MSVC +static bool IsRootDirectoryW(const wstring& path) { + return IsRootOrAbsolute(path, true); +} + +static bool MakeDirectoriesW(const wstring& path) { + if (path.empty()) { + return false; + } + if (IsRootDirectoryW(path) || IsDirectoryW(path)) { + return true; + } + int last_separator = path.rfind(L"\\"); + if (last_separator < 0) { + // Since `path` is not a root directory, there must be at least one + // directory above it. + pdie(255, "MakeDirectoriesW(%S), could not find dirname", path.c_str()); + } + wstring parent = path.substr(0, last_separator); + if (!MakeDirectoriesW(parent)) { + return false; + } + if (!::CreateDirectoryW(path.c_str(), nullptr)) { + PrintError("MakeDirectoriesW(%S), CreateDirectoryW failed, err=%d", + path.c_str(), GetLastError()); + return false; + } + return true; +} + bool MakeDirectories(const string& path, unsigned int mode) { - // TODO(bazel-team): implement this. - pdie(255, "blaze::MakeDirectories is not implemented on Windows"); - return false; + // TODO(laszlocsomor): respect `mode` to the extent that it's possible on + // Windows; it's currently ignored. + if (path.empty() || IsDevNull(path) || IsRootDirectory(path)) { + return false; + } + wstring wpath; + if (!AsWindowsPathWithUncPrefix(path, &wpath)) { + return false; + } + return MakeDirectoriesW(wpath); } -#else // not COMPILER_MSVC -#endif // COMPILER_MSVC static unique_ptr<WCHAR[]> GetCwdW() { DWORD len = ::GetCurrentDirectoryW(0, nullptr); |