aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/cpp/util/path_platform.h10
-rw-r--r--src/main/cpp/util/path_posix.cc5
-rw-r--r--src/main/cpp/util/path_windows.cc27
-rw-r--r--src/test/cpp/util/BUILD1
-rw-r--r--src/test/cpp/util/path_posix_test.cc11
-rw-r--r--src/test/cpp/util/path_windows_test.cc29
6 files changed, 82 insertions, 1 deletions
diff --git a/src/main/cpp/util/path_platform.h b/src/main/cpp/util/path_platform.h
index 9653a676bb..3c4671f004 100644
--- a/src/main/cpp/util/path_platform.h
+++ b/src/main/cpp/util/path_platform.h
@@ -54,6 +54,16 @@ bool IsAbsolute(const std::string &path);
// MakeAbsolute("C:/foo") ---> "C:/foo"
std::string MakeAbsolute(const std::string &path);
+// Returns the given path in absolute form, taking into account a possible
+// starting environment variable on the windows platform, so that we can
+// accept standard path variables like %USERPROFILE%. We do not support
+// unix-style envvars here: recreating that logic is error-prone and not
+// worthwhile, since they are less critical to standard paths as in Windows.
+//
+// MakeAbsolute("foo") in wd "/bar" --> "/bar/foo"
+// MakeAbsolute("%USERPROFILE%/foo") --> "C:\Users\bazel-user\foo"
+std::string MakeAbsoluteAndResolveWindowsEnvvars(const std::string &path);
+
// TODO(bazel-team) consider changing the path(_platform) header split to be a
// path.h and path_windows.h split, which would make it clearer what functions
// are included by an import statement. The downside to this gain in clarity
diff --git a/src/main/cpp/util/path_posix.cc b/src/main/cpp/util/path_posix.cc
index 267dc22931..9c0b440d11 100644
--- a/src/main/cpp/util/path_posix.cc
+++ b/src/main/cpp/util/path_posix.cc
@@ -66,4 +66,9 @@ std::string MakeAbsolute(const std::string &path) {
return JoinPath(blaze_util::GetCwd(), path);
}
+
+std::string MakeAbsoluteAndResolveWindowsEnvvars(const std::string &path) {
+ return MakeAbsolute(path);
+}
+
} // namespace blaze_util
diff --git a/src/main/cpp/util/path_windows.cc b/src/main/cpp/util/path_windows.cc
index 041a0e847e..15dd0ddce6 100644
--- a/src/main/cpp/util/path_windows.cc
+++ b/src/main/cpp/util/path_windows.cc
@@ -14,6 +14,7 @@
#include "src/main/cpp/util/path_platform.h"
+#include <assert.h>
#include <wchar.h> // wcslen
#include <windows.h>
@@ -87,6 +88,32 @@ std::string MakeAbsolute(const std::string& path) {
WstringToCstring(RemoveUncPrefixMaybe(wpath.c_str())).get());
}
+std::string MakeAbsoluteAndResolveWindowsEnvvars(const std::string& path) {
+ // Get the size of the expanded string, so we know how big of a buffer to
+ // provide. The returned size includes the null terminator.
+ std::unique_ptr<CHAR[]> resolved(new CHAR[MAX_PATH]);
+ DWORD size =
+ ::ExpandEnvironmentStrings(path.c_str(), resolved.get(), MAX_PATH);
+ if (size == 0) {
+ BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
+ << "MakeAbsoluteAndResolveWindowsEnvvars(" << path
+ << "): ExpandEnvironmentStrings failed: " << GetLastErrorString();
+ } else if (size > MAX_PATH) {
+ // Try again with a buffer bigger than MAX_PATH.
+ resolved.reset(new CHAR[size]);
+ DWORD second_size =
+ ::ExpandEnvironmentStrings(path.c_str(), resolved.get(), size);
+ if (second_size == 0) {
+ BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
+ << "MakeAbsoluteAndResolveWindowsEnvvars(" << path
+ << "): ExpandEnvironmentStrings failed with second buffer: "
+ << GetLastErrorString();
+ }
+ assert(second_size <= size);
+ }
+ return MakeAbsolute(std::string(resolved.get()));
+}
+
bool CompareAbsolutePaths(const std::string& a, const std::string& b) {
return ConvertPath(a) == ConvertPath(b);
}
diff --git a/src/test/cpp/util/BUILD b/src/test/cpp/util/BUILD
index 455994f3d9..1a86b0d0c6 100644
--- a/src/test/cpp/util/BUILD
+++ b/src/test/cpp/util/BUILD
@@ -60,6 +60,7 @@ cc_test(
] + select({
"//src/conditions:windows": [
":windows_test_util",
+ "//src/main/cpp:blaze_util",
"//src/main/native/windows:lib-file",
],
"//conditions:default": [],
diff --git a/src/test/cpp/util/path_posix_test.cc b/src/test/cpp/util/path_posix_test.cc
index f1262cdda1..df79b59c1e 100644
--- a/src/test/cpp/util/path_posix_test.cc
+++ b/src/test/cpp/util/path_posix_test.cc
@@ -159,4 +159,15 @@ TEST(PathPosixTest, MakeAbsolute) {
EXPECT_EQ(MakeAbsolute(""), "");
}
+TEST(PathPosixTest, MakeAbsoluteAndResolveWindowsEnvvars) {
+ // Check that Unix-style envvars are not resolved.
+ EXPECT_EQ(MakeAbsoluteAndResolveWindowsEnvvars("$PATH"),
+ JoinPath(GetCwd(), "$PATH"));
+ EXPECT_EQ(MakeAbsoluteAndResolveWindowsEnvvars("${PATH}"),
+ JoinPath(GetCwd(), "${PATH}"));
+ // Check that Windows-style envvars are not resolved when not on Windows.
+ EXPECT_EQ(MakeAbsoluteAndResolveWindowsEnvvars("%PATH%"),
+ JoinPath(GetCwd(), "%PATH%"));
+}
+
} // namespace blaze_util
diff --git a/src/test/cpp/util/path_windows_test.cc b/src/test/cpp/util/path_windows_test.cc
index 15875603f7..c78c4ab012 100644
--- a/src/test/cpp/util/path_windows_test.cc
+++ b/src/test/cpp/util/path_windows_test.cc
@@ -20,6 +20,7 @@
#include <string>
#include "gtest/gtest.h"
+#include "src/main/cpp/blaze_util_platform.h"
#include "src/main/cpp/util/file_platform.h"
#include "src/main/cpp/util/path.h"
#include "src/main/cpp/util/path_platform.h"
@@ -298,7 +299,7 @@ TEST(PathWindowsTest, ConvertPathTest) {
EXPECT_EQ("c:\\foo\\bar", ConvertPath("c:/../foo\\BAR\\.\\"));
}
-TEST(PathWindowsTest, TestMakeAbsolute) {
+TEST(PathWindowsTest, MakeAbsolute) {
EXPECT_EQ("c:\\foo\\bar", MakeAbsolute("C:\\foo\\BAR"));
EXPECT_EQ("c:\\foo\\bar", MakeAbsolute("C:/foo/bar"));
EXPECT_EQ("c:\\foo\\bar", MakeAbsolute("C:\\foo\\bar\\"));
@@ -314,4 +315,30 @@ TEST(PathWindowsTest, TestMakeAbsolute) {
EXPECT_EQ("", MakeAbsolute(""));
}
+TEST(PathWindowsTest, MakeAbsoluteAndResolveWindowsEnvvars_WithTmpdir) {
+ // We cannot test the system-default paths like %ProgramData% because these
+ // are wiped from the test environment. TestTmpdir is set by Bazel though,
+ // so serves as a fine substitute.
+ char buf[MAX_PATH] = {0};
+ DWORD len = ::GetEnvironmentVariableA("TEST_TMPDIR", buf, MAX_PATH);
+ const std::string tmpdir = buf;
+ const std::string expected_tmpdir_bar = ConvertPath(tmpdir + "\\bar");
+
+ EXPECT_EQ(expected_tmpdir_bar,
+ MakeAbsoluteAndResolveWindowsEnvvars("%TEST_TMPDIR%\\bar"));
+ EXPECT_EQ(expected_tmpdir_bar,
+ MakeAbsoluteAndResolveWindowsEnvvars("%Test_Tmpdir%\\bar"));
+ EXPECT_EQ(expected_tmpdir_bar,
+ MakeAbsoluteAndResolveWindowsEnvvars("%test_tmpdir%\\bar"));
+ EXPECT_EQ(expected_tmpdir_bar,
+ MakeAbsoluteAndResolveWindowsEnvvars("%test_tmpdir%/bar"));
+}
+
+TEST(PathWindowsTest, MakeAbsoluteAndResolveWindowsEnvvars_LongPaths) {
+ const std::string long_path = "c:\\" + std::string(MAX_PATH, 'a');
+ blaze::SetEnv("long", long_path);
+
+ EXPECT_EQ(long_path, MakeAbsoluteAndResolveWindowsEnvvars("%long%"));
+}
+
} // namespace blaze_util