aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/cpp/util
diff options
context:
space:
mode:
authorGravatar Laszlo Csomor <laszlocsomor@google.com>2017-01-12 13:09:35 +0000
committerGravatar Marcel Hlopko <hlopko@google.com>2017-01-12 14:08:41 +0000
commitf257130b7701c37585d8015f27e1d75131b37166 (patch)
tree4d0215f13c366f2719096a19eed20e02892f2e9c /src/main/cpp/util
parent45f15aa2b365d8dc2253ded5758cf22c81ebfc1f (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.cc12
-rw-r--r--src/main/cpp/util/file_windows.cc54
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(), &times) == 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);