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/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