Windows: recognize symlinks, not just junctions
In this PR:
- The isJunction JNI method now recognizes
symlinks, not just junctions. The method now
reports errors via return codes.
- WindowsFileSystem.fileIsSymbolicLink and
WindowsFileSystem.isSymlinkOrJunction now
recognize symlinks.
See https://github.com/bazelbuild/bazel/issues/7907
Closes #7931.
PiperOrigin-RevId: 241927717
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
index ee457b7..5b3669b 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
@@ -108,7 +108,7 @@
@Override
protected boolean fileIsSymbolicLink(File file) {
try {
- if (isJunction(file)) {
+ if (isSymlinkOrJunction(file)) {
return true;
}
} catch (IOException e) {
@@ -184,7 +184,7 @@
protected boolean isDirectory(Path path, boolean followSymlinks) {
if (!followSymlinks) {
try {
- if (isJunction(getIoFile(path))) {
+ if (isSymlinkOrJunction(getIoFile(path))) {
return false;
}
} catch (IOException e) {
@@ -214,8 +214,8 @@
* they are dangling), though only directory junctions and directory symlinks are useful.
*/
@VisibleForTesting
- static boolean isJunction(File file) throws IOException {
- return WindowsFileOperations.isJunction(file.getPath());
+ static boolean isSymlinkOrJunction(File file) throws IOException {
+ return WindowsFileOperations.isSymlinkOrJunction(file.getPath());
}
private static DosFileAttributes getAttribs(File file, boolean followSymlinks)
diff --git a/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsFileOperations.java b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsFileOperations.java
index 8208618..ba82a4f 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsFileOperations.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsFileOperations.java
@@ -44,10 +44,10 @@
private static final int MAX_PATH = 260;
- // Keep IS_JUNCTION_* values in sync with src/main/native/windows/file.h.
- private static final int IS_JUNCTION_YES = 0;
- private static final int IS_JUNCTION_NO = 1;
- // IS_JUNCTION_ERROR = 2;
+ // Keep IS_SYMLINK_OR_JUNCTION_* values in sync with src/main/native/windows/file.cc.
+ private static final int IS_SYMLINK_OR_JUNCTION_SUCCESS = 0;
+ // IS_SYMLINK_OR_JUNCTION_ERROR = 1;
+ private static final int IS_SYMLINK_OR_JUNCTION_DOES_NOT_EXIST = 2;
// Keep CREATE_JUNCTION_* values in sync with src/main/native/windows/file.h.
private static final int CREATE_JUNCTION_SUCCESS = 0;
@@ -73,7 +73,8 @@
private static final int READ_SYMLINK_OR_JUNCTION_NOT_A_LINK = 4;
private static final int READ_SYMLINK_OR_JUNCTION_UNKNOWN_LINK_TYPE = 5;
- private static native int nativeIsJunction(String path, String[] error);
+ private static native int nativeIsSymlinkOrJunction(
+ String path, boolean[] result, String[] error);
private static native boolean nativeGetLongPath(String path, String[] result, String[] error);
@@ -85,18 +86,22 @@
private static native int nativeDeletePath(String path, String[] error);
/** Determines whether `path` is a junction point or directory symlink. */
- public static boolean isJunction(String path) throws IOException {
+ public static boolean isSymlinkOrJunction(String path) throws IOException {
WindowsJniLoader.loadJni();
+ boolean[] result = new boolean[] {false};
String[] error = new String[] {null};
- switch (nativeIsJunction(asLongPath(path), error)) {
- case IS_JUNCTION_YES:
- return true;
- case IS_JUNCTION_NO:
- return false;
+ switch (nativeIsSymlinkOrJunction(asLongPath(path), result, error)) {
+ case IS_SYMLINK_OR_JUNCTION_SUCCESS:
+ return result[0];
+ case IS_SYMLINK_OR_JUNCTION_DOES_NOT_EXIST:
+ error[0] = "path does not exist";
+ break;
default:
- // This is IS_JUNCTION_ERROR. The JNI code puts a custom message in 'error[0]'.
- throw new IOException(error[0]);
+ // This is IS_SYMLINK_OR_JUNCTION_ERROR (1). The JNI code puts a custom message in
+ // 'error[0]'.
+ break;
}
+ throw new IOException(String.format("Cannot tell if '%s' is link: %s", path, error[0]));
}
/**
diff --git a/src/main/native/windows/file-jni.cc b/src/main/native/windows/file-jni.cc
index 3befe0f..63d81d8 100644
--- a/src/main/native/windows/file-jni.cc
+++ b/src/main/native/windows/file-jni.cc
@@ -40,20 +40,26 @@
}
extern "C" JNIEXPORT jint JNICALL
-Java_com_google_devtools_build_lib_windows_jni_WindowsFileOperations_nativeIsJunction(
- JNIEnv* env, jclass clazz, jstring path, jobjectArray error_msg_holder) {
+Java_com_google_devtools_build_lib_windows_jni_WindowsFileOperations_nativeIsSymlinkOrJunction(
+ JNIEnv* env, jclass clazz, jstring path, jbooleanArray result_holder,
+ jobjectArray error_msg_holder) {
std::wstring wpath(bazel::windows::GetJavaWstring(env, path));
std::wstring error;
+ bool is_sym = false;
int result =
- bazel::windows::IsJunctionOrDirectorySymlink(wpath.c_str(), &error);
- if (result == bazel::windows::IS_JUNCTION_ERROR &&
- CanReportError(env, error_msg_holder)) {
- ReportLastError(
- bazel::windows::MakeErrorMessage(WSTR(__FILE__), __LINE__,
- L"nativeIsJunction", wpath, error),
- env, error_msg_holder);
+ bazel::windows::IsSymlinkOrJunction(wpath.c_str(), &is_sym, &error);
+ if (result == bazel::windows::IsSymlinkOrJunctionResult::kSuccess) {
+ jboolean is_sym_jbool = is_sym ? JNI_TRUE : JNI_FALSE;
+ env->SetBooleanArrayRegion(result_holder, 0, 1, &is_sym_jbool);
+ } else {
+ if (!error.empty() && CanReportError(env, error_msg_holder)) {
+ ReportLastError(
+ bazel::windows::MakeErrorMessage(WSTR(__FILE__), __LINE__,
+ L"nativeIsJunction", wpath, error),
+ env, error_msg_holder);
+ }
}
- return result;
+ return static_cast<jint>(result);
}
extern "C" JNIEXPORT jboolean JNICALL
diff --git a/src/main/native/windows/file.cc b/src/main/native/windows/file.cc
index e7cf81a..04ec6c5 100644
--- a/src/main/native/windows/file.cc
+++ b/src/main/native/windows/file.cc
@@ -78,31 +78,31 @@
return wstring(attr_str, 8);
}
-int IsJunctionOrDirectorySymlink(const WCHAR* path, wstring* error) {
+int IsSymlinkOrJunction(const WCHAR* path, bool* result, wstring* error) {
if (!IsAbsoluteNormalizedWindowsPath(path)) {
if (error) {
- *error = MakeErrorMessage(WSTR(__FILE__), __LINE__,
- L"IsJunctionOrDirectorySymlink", path,
- L"expected an absolute Windows path");
+ *error =
+ MakeErrorMessage(WSTR(__FILE__), __LINE__, L"IsSymlinkOrJunction",
+ path, L"expected an absolute Windows path");
}
- return IS_JUNCTION_ERROR;
+ return IsSymlinkOrJunctionResult::kError;
}
DWORD attrs = ::GetFileAttributesW(path);
if (attrs == INVALID_FILE_ATTRIBUTES) {
DWORD err = GetLastError();
+ if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
+ return IsSymlinkOrJunctionResult::kDoesNotExist;
+ }
+
if (error) {
*error = MakeErrorMessage(WSTR(__FILE__), __LINE__,
- L"IsJunctionOrDirectorySymlink", path, err);
+ L"IsSymlinkOrJunction", path, err);
}
- return IS_JUNCTION_ERROR;
+ return IsSymlinkOrJunctionResult::kError;
} else {
- if ((attrs & FILE_ATTRIBUTE_DIRECTORY) &&
- (attrs & FILE_ATTRIBUTE_REPARSE_POINT)) {
- return IS_JUNCTION_YES;
- } else {
- return IS_JUNCTION_NO;
- }
+ *result = (attrs & FILE_ATTRIBUTE_REPARSE_POINT);
+ return IsSymlinkOrJunctionResult::kSuccess;
}
}
diff --git a/src/main/native/windows/file.h b/src/main/native/windows/file.h
index 87d5f0a..0e0c415 100644
--- a/src/main/native/windows/file.h
+++ b/src/main/native/windows/file.h
@@ -48,10 +48,12 @@
bool IsAbsoluteNormalizedWindowsPath(const std::wstring& p);
// Keep in sync with j.c.g.devtools.build.lib.windows.WindowsFileOperations
-enum {
- IS_JUNCTION_YES = 0,
- IS_JUNCTION_NO = 1,
- IS_JUNCTION_ERROR = 2,
+struct IsSymlinkOrJunctionResult {
+ enum {
+ kSuccess = 0,
+ kError = 1,
+ kDoesNotExist = 2,
+ };
};
// Keep in sync with j.c.g.devtools.build.lib.windows.WindowsFileOperations
@@ -97,16 +99,7 @@
//
// To read about differences between junctions and directory symlinks,
// see http://superuser.com/a/343079. In Bazel we only ever create junctions.
-//
-// Returns:
-// - IS_JUNCTION_YES, if `path` exists and is either a directory junction or a
-// directory symlink
-// - IS_JUNCTION_NO, if `path` exists but is neither a directory junction nor a
-// directory symlink; also when `path` is a symlink to a directory but it was
-// created using "mklink" instead of "mklink /d", as such symlinks don't
-// behave the same way as directories (e.g. they can't be listed)
-// - IS_JUNCTION_ERROR, if `path` doesn't exist or some error occurred
-int IsJunctionOrDirectorySymlink(const WCHAR* path, std::wstring* error);
+int IsSymlinkOrJunction(const WCHAR* path, bool* result, wstring* error);
// Computes the long version of `path` if it has any 8dot3 style components.
// Returns the empty string upon success, or a human-readable error message upon
diff --git a/src/test/java/com/google/devtools/build/lib/windows/WindowsFileOperationsTest.java b/src/test/java/com/google/devtools/build/lib/windows/WindowsFileOperationsTest.java
index c5a50d3..9c04f8b 100644
--- a/src/test/java/com/google/devtools/build/lib/windows/WindowsFileOperationsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/windows/WindowsFileOperationsTest.java
@@ -90,32 +90,33 @@
testUtil.createJunctions(junctions);
- assertThat(WindowsFileOperations.isJunction(root + "\\shrtpath\\a")).isTrue();
- assertThat(WindowsFileOperations.isJunction(root + "\\shrtpath\\b")).isTrue();
- assertThat(WindowsFileOperations.isJunction(root + "\\shrtpath\\c")).isTrue();
- assertThat(WindowsFileOperations.isJunction(root + "\\longlinkpath\\a")).isTrue();
- assertThat(WindowsFileOperations.isJunction(root + "\\longlinkpath\\b")).isTrue();
- assertThat(WindowsFileOperations.isJunction(root + "\\longlinkpath\\c")).isTrue();
- assertThat(WindowsFileOperations.isJunction(root + "\\longli~1\\a")).isTrue();
- assertThat(WindowsFileOperations.isJunction(root + "\\longli~1\\b")).isTrue();
- assertThat(WindowsFileOperations.isJunction(root + "\\longli~1\\c")).isTrue();
- assertThat(WindowsFileOperations.isJunction(root + "\\abbreviated\\a")).isTrue();
- assertThat(WindowsFileOperations.isJunction(root + "\\abbreviated\\b")).isTrue();
- assertThat(WindowsFileOperations.isJunction(root + "\\abbreviated\\c")).isTrue();
- assertThat(WindowsFileOperations.isJunction(root + "\\abbrev~1\\a")).isTrue();
- assertThat(WindowsFileOperations.isJunction(root + "\\abbrev~1\\b")).isTrue();
- assertThat(WindowsFileOperations.isJunction(root + "\\abbrev~1\\c")).isTrue();
- assertThat(WindowsFileOperations.isJunction(root + "\\control\\a")).isFalse();
- assertThat(WindowsFileOperations.isJunction(root + "\\control\\b")).isFalse();
- assertThat(WindowsFileOperations.isJunction(root + "\\control\\c")).isFalse();
- assertThat(WindowsFileOperations.isJunction(root + "\\shrttrgt\\file1.txt")).isFalse();
- assertThat(WindowsFileOperations.isJunction(root + "\\longtargetpath\\file2.txt")).isFalse();
- assertThat(WindowsFileOperations.isJunction(root + "\\longta~1\\file2.txt")).isFalse();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\shrtpath\\a")).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\shrtpath\\b")).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\shrtpath\\c")).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\longlinkpath\\a")).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\longlinkpath\\b")).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\longlinkpath\\c")).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\longli~1\\a")).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\longli~1\\b")).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\longli~1\\c")).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\abbreviated\\a")).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\abbreviated\\b")).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\abbreviated\\c")).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\abbrev~1\\a")).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\abbrev~1\\b")).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\abbrev~1\\c")).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\control\\a")).isFalse();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\control\\b")).isFalse();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\control\\c")).isFalse();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\shrttrgt\\file1.txt")).isFalse();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\longtargetpath\\file2.txt"))
+ .isFalse();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(root + "\\longta~1\\file2.txt")).isFalse();
try {
- WindowsFileOperations.isJunction(root + "\\non-existent");
+ WindowsFileOperations.isSymlinkOrJunction(root + "\\non-existent");
fail("expected to throw");
} catch (IOException e) {
- assertThat(e.getMessage()).contains("nativeIsJunction");
+ assertThat(e.getMessage()).contains("path does not exist");
}
assertThat(Arrays.asList(new File(root + "/shrtpath/a").list())).containsExactly("file1.txt");
assertThat(Arrays.asList(new File(root + "/shrtpath/b").list())).containsExactly("file2.txt");
@@ -141,14 +142,14 @@
File linkPath = new File(helloPath.getParent().getParent().toFile(), "link");
assertThat(Arrays.asList(linkPath.list())).containsExactly("hello.txt");
- assertThat(WindowsFileOperations.isJunction(linkPath.getAbsolutePath())).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(linkPath.getAbsolutePath())).isTrue();
assertThat(helloPath.toFile().delete()).isTrue();
assertThat(helloPath.getParent().toFile().delete()).isTrue();
assertThat(helloPath.getParent().toFile().exists()).isFalse();
assertThat(Arrays.asList(linkPath.getParentFile().list())).containsExactly("link");
- assertThat(WindowsFileOperations.isJunction(linkPath.getAbsolutePath())).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(linkPath.getAbsolutePath())).isTrue();
assertThat(
Files.exists(
linkPath.toPath(), WindowsFileSystem.symlinkOpts(/* followSymlinks */ false)))
@@ -167,22 +168,22 @@
// Assert that a file is identified as not a junction.
String longPath = helloFile.getAbsolutePath();
String shortPath = new File(helloFile.getParentFile(), "hellow~1.txt").getAbsolutePath();
- assertThat(WindowsFileOperations.isJunction(longPath)).isFalse();
- assertThat(WindowsFileOperations.isJunction(shortPath)).isFalse();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(longPath)).isFalse();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(shortPath)).isFalse();
// Assert that after deleting the file and creating a junction with the same path, it is
// identified as a junction.
assertThat(helloFile.delete()).isTrue();
testUtil.createJunctions(ImmutableMap.of("target\\helloworld.txt", "target"));
- assertThat(WindowsFileOperations.isJunction(longPath)).isTrue();
- assertThat(WindowsFileOperations.isJunction(shortPath)).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(longPath)).isTrue();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(shortPath)).isTrue();
// Assert that after deleting the file and creating a directory with the same path, it is
// identified as not a junction.
assertThat(helloFile.delete()).isTrue();
assertThat(helloFile.mkdir()).isTrue();
- assertThat(WindowsFileOperations.isJunction(longPath)).isFalse();
- assertThat(WindowsFileOperations.isJunction(shortPath)).isFalse();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(longPath)).isFalse();
+ assertThat(WindowsFileOperations.isSymlinkOrJunction(shortPath)).isFalse();
}
@Test
diff --git a/src/test/java/com/google/devtools/build/lib/windows/WindowsFileSystemTest.java b/src/test/java/com/google/devtools/build/lib/windows/WindowsFileSystemTest.java
index b0c9454..7ca6e57 100644
--- a/src/test/java/com/google/devtools/build/lib/windows/WindowsFileSystemTest.java
+++ b/src/test/java/com/google/devtools/build/lib/windows/WindowsFileSystemTest.java
@@ -141,35 +141,35 @@
testUtil.createJunctions(junctions);
- assertThat(WindowsFileSystem.isJunction(new File(root, "shrtpath/a"))).isTrue();
- assertThat(WindowsFileSystem.isJunction(new File(root, "shrtpath/b"))).isTrue();
- assertThat(WindowsFileSystem.isJunction(new File(root, "shrtpath/c"))).isTrue();
- assertThat(WindowsFileSystem.isJunction(new File(root, "longlinkpath/a"))).isTrue();
- assertThat(WindowsFileSystem.isJunction(new File(root, "longlinkpath/b"))).isTrue();
- assertThat(WindowsFileSystem.isJunction(new File(root, "longlinkpath/c"))).isTrue();
- assertThat(WindowsFileSystem.isJunction(new File(root, "longli~1/a"))).isTrue();
- assertThat(WindowsFileSystem.isJunction(new File(root, "longli~1/b"))).isTrue();
- assertThat(WindowsFileSystem.isJunction(new File(root, "longli~1/c"))).isTrue();
- assertThat(WindowsFileSystem.isJunction(new File(root, "abbreviated/a"))).isTrue();
- assertThat(WindowsFileSystem.isJunction(new File(root, "abbreviated/b"))).isTrue();
- assertThat(WindowsFileSystem.isJunction(new File(root, "abbreviated/c"))).isTrue();
- assertThat(WindowsFileSystem.isJunction(new File(root, "abbrev~1/a"))).isTrue();
- assertThat(WindowsFileSystem.isJunction(new File(root, "abbrev~1/b"))).isTrue();
- assertThat(WindowsFileSystem.isJunction(new File(root, "abbrev~1/c"))).isTrue();
- assertThat(WindowsFileSystem.isJunction(new File(root, "control/a"))).isFalse();
- assertThat(WindowsFileSystem.isJunction(new File(root, "control/b"))).isFalse();
- assertThat(WindowsFileSystem.isJunction(new File(root, "control/c"))).isFalse();
- assertThat(WindowsFileSystem.isJunction(new File(root, "shrttrgt/file1.txt")))
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "shrtpath/a"))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "shrtpath/b"))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "shrtpath/c"))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "longlinkpath/a"))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "longlinkpath/b"))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "longlinkpath/c"))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "longli~1/a"))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "longli~1/b"))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "longli~1/c"))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "abbreviated/a"))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "abbreviated/b"))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "abbreviated/c"))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "abbrev~1/a"))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "abbrev~1/b"))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "abbrev~1/c"))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "control/a"))).isFalse();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "control/b"))).isFalse();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "control/c"))).isFalse();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "shrttrgt/file1.txt")))
.isFalse();
- assertThat(WindowsFileSystem.isJunction(new File(root, "longtargetpath/file2.txt")))
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "longtargetpath/file2.txt")))
.isFalse();
- assertThat(WindowsFileSystem.isJunction(new File(root, "longta~1/file2.txt")))
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(root, "longta~1/file2.txt")))
.isFalse();
try {
- WindowsFileSystem.isJunction(new File(root, "non-existent"));
+ WindowsFileSystem.isSymlinkOrJunction(new File(root, "non-existent"));
fail("expected failure");
} catch (IOException e) {
- assertThat(e.getMessage()).contains("cannot find");
+ assertThat(e.getMessage()).contains("path does not exist");
}
assertThat(Arrays.asList(new File(root + "/shrtpath/a").list())).containsExactly("file1.txt");
@@ -196,14 +196,14 @@
File linkPath = new File(helloPath.getParent().getParent().toFile(), "link");
assertThat(Arrays.asList(linkPath.list())).containsExactly("hello.txt");
- assertThat(WindowsFileSystem.isJunction(linkPath)).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(linkPath)).isTrue();
assertThat(helloPath.toFile().delete()).isTrue();
assertThat(helloPath.getParent().toFile().delete()).isTrue();
assertThat(helloPath.getParent().toFile().exists()).isFalse();
assertThat(Arrays.asList(linkPath.getParentFile().list())).containsExactly("link");
- assertThat(WindowsFileSystem.isJunction(linkPath)).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(linkPath)).isTrue();
assertThat(
Files.exists(
linkPath.toPath(), WindowsFileSystem.symlinkOpts(/* followSymlinks */ false)))
@@ -219,18 +219,18 @@
File longPath =
testUtil.scratchFile("target\\helloworld.txt", "hello").toAbsolutePath().toFile();
File shortPath = new File(longPath.getParentFile(), "hellow~1.txt");
- assertThat(WindowsFileSystem.isJunction(longPath)).isFalse();
- assertThat(WindowsFileSystem.isJunction(shortPath)).isFalse();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(longPath)).isFalse();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(shortPath)).isFalse();
assertThat(longPath.delete()).isTrue();
testUtil.createJunctions(ImmutableMap.of("target\\helloworld.txt", "target"));
- assertThat(WindowsFileSystem.isJunction(longPath)).isTrue();
- assertThat(WindowsFileSystem.isJunction(shortPath)).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(longPath)).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(shortPath)).isTrue();
assertThat(longPath.delete()).isTrue();
assertThat(longPath.mkdir()).isTrue();
- assertThat(WindowsFileSystem.isJunction(longPath)).isFalse();
- assertThat(WindowsFileSystem.isJunction(shortPath)).isFalse();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(longPath)).isFalse();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(shortPath)).isFalse();
}
@Test
@@ -311,7 +311,7 @@
fs.createSymbolicLink(link4, fs.getPath(scratchRoot).getRelative("bar.txt").asFragment());
// Assert that link1 and link2 are true junctions and have the right contents.
for (Path p : ImmutableList.of(link1, link2)) {
- assertThat(WindowsFileSystem.isJunction(new File(p.getPathString()))).isTrue();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(p.getPathString()))).isTrue();
assertThat(p.isSymbolicLink()).isTrue();
assertThat(
Iterables.transform(
@@ -326,7 +326,7 @@
}
// Assert that link3 and link4 are copies of files.
for (Path p : ImmutableList.of(link3, link4)) {
- assertThat(WindowsFileSystem.isJunction(new File(p.getPathString()))).isFalse();
+ assertThat(WindowsFileSystem.isSymlinkOrJunction(new File(p.getPathString()))).isFalse();
assertThat(p.isSymbolicLink()).isFalse();
assertThat(p.isFile()).isTrue();
}
diff --git a/src/test/native/windows/file_test.cc b/src/test/native/windows/file_test.cc
index ca7604d..c4a9022 100644
--- a/src/test/native/windows/file_test.cc
+++ b/src/test/native/windows/file_test.cc
@@ -81,8 +81,10 @@
wstring file1(target + L"\\foo");
EXPECT_TRUE(blaze_util::CreateDummyFile(file1));
- EXPECT_EQ(IS_JUNCTION_NO,
- IsJunctionOrDirectorySymlink(target.c_str(), nullptr));
+ bool is_link = true;
+ EXPECT_EQ(IsSymlinkOrJunctionResult::kSuccess,
+ IsSymlinkOrJunction(target.c_str(), &is_link, nullptr));
+ EXPECT_FALSE(is_link);
EXPECT_NE(INVALID_FILE_ATTRIBUTES, ::GetFileAttributesW(file1.c_str()));
wstring name(tmp + L"\\junc_name");
@@ -99,14 +101,22 @@
CreateJunctionResult::kSuccess);
// Assert creation of the junctions.
- ASSERT_EQ(IS_JUNCTION_YES,
- IsJunctionOrDirectorySymlink((name + L"1").c_str(), nullptr));
- ASSERT_EQ(IS_JUNCTION_YES,
- IsJunctionOrDirectorySymlink((name + L"2").c_str(), nullptr));
- ASSERT_EQ(IS_JUNCTION_YES,
- IsJunctionOrDirectorySymlink((name + L"3").c_str(), nullptr));
- ASSERT_EQ(IS_JUNCTION_YES,
- IsJunctionOrDirectorySymlink((name + L"4").c_str(), nullptr));
+ is_link = false;
+ ASSERT_EQ(IsSymlinkOrJunctionResult::kSuccess,
+ IsSymlinkOrJunction((name + L"1").c_str(), &is_link, nullptr));
+ ASSERT_TRUE(is_link);
+ is_link = false;
+ ASSERT_EQ(IsSymlinkOrJunctionResult::kSuccess,
+ IsSymlinkOrJunction((name + L"2").c_str(), &is_link, nullptr));
+ ASSERT_TRUE(is_link);
+ is_link = false;
+ ASSERT_EQ(IsSymlinkOrJunctionResult::kSuccess,
+ IsSymlinkOrJunction((name + L"3").c_str(), &is_link, nullptr));
+ ASSERT_TRUE(is_link);
+ is_link = false;
+ ASSERT_EQ(IsSymlinkOrJunctionResult::kSuccess,
+ IsSymlinkOrJunction((name + L"4").c_str(), &is_link, nullptr));
+ ASSERT_TRUE(is_link);
// Assert that the file is visible under all junctions.
ASSERT_NE(INVALID_FILE_ATTRIBUTES,