From 2002fb2782d205e5c2a3a57b73aed41325336949 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 28 Nov 2018 16:09:43 +0100 Subject: [PATCH] follow symlinks when initializing FS state for a build target (IDEA-202775) --- .../intellij/compiler/JavaCompilerBasicTest.java | 16 ++++++++++++++++ .../jetbrains/jps/incremental/FSOperations.java | 5 +++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/java/compiler/tests/com/intellij/compiler/JavaCompilerBasicTest.java b/java/compiler/tests/com/intellij/compiler/JavaCompilerBasicTest.java index 7d3808b65afd..99a8c5dcf22e 100644 --- a/java/compiler/tests/com/intellij/compiler/JavaCompilerBasicTest.java +++ b/java/compiler/tests/com/intellij/compiler/JavaCompilerBasicTest.java @@ -8,6 +8,9 @@ import com.intellij.openapi.vfs.VirtualFile; import java.io.File; import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collections; import static com.intellij.util.io.TestFileSystemItem.fs; @@ -38,4 +41,17 @@ public class JavaCompilerBasicTest extends BaseCompilerTestCase { make(module); assertOutput(module, fs().file("B.class")); } + + + public void testSymlinksInSources() throws IOException { + final VirtualFile file = createFile("src/A.java", "public class A {}"); + VirtualFile srcRoot = file.getParent(); + final File linkFile = new File(srcRoot.getParent().getPath(), "src-link"); + FileUtil.delete(linkFile); // ensure the link does not exist + final Path symlink = Files.createSymbolicLink(linkFile.toPath(), FileSystems.getDefault().getPath(srcRoot.getPath())); + + final Module module = addModule("a", srcRoot.getParent().findChild(symlink.getFileName().toString())); + make(module); + assertOutput(module, fs().file("A.class")); + } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java index ac16513c0c44..14b80796a7c6 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java @@ -42,6 +42,7 @@ import java.io.FileFilter; import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; +import java.util.EnumSet; import java.util.HashSet; import java.util.Set; @@ -251,7 +252,7 @@ public class FSOperations { final BuildRootIndex rootIndex = context.getProjectDescriptor().getBuildRootIndex(); final Ref allFilesMarked = Ref.create(Boolean.TRUE); - Files.walkFileTree(file.toPath(), new SimpleFileVisitor() { + Files.walkFileTree(file.toPath(), EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, new SimpleFileVisitor() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { return rootIndex.isDirectoryAccepted(dir.toFile(), rd)? FileVisitResult.CONTINUE : FileVisitResult.SKIP_SUBTREE; @@ -270,7 +271,7 @@ public class FSOperations { boolean markDirty = forceDirty; if (!markDirty) { // for symlinks the attr structure reflects the symlink's timestamp and not symlink's target timestamp - markDirty = tsStorage.getStamp(_file, rd.getTarget()) != (attrs.isRegularFile()? attrs.lastModifiedTime().toMillis() : lastModified(f)); + markDirty = tsStorage.getStamp(_file, rd.getTarget()) != attrs.lastModifiedTime().toMillis(); } if (markDirty) { // if it is full project rebuild, all storages are already completely cleared;