diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ProjectDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ProjectDescriptor.java index 480a149d6d8d..d5a6aa41d448 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ProjectDescriptor.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ProjectDescriptor.java @@ -86,6 +86,9 @@ public final class ProjectDescriptor { myTargetsState = targetsState; } + /** + * @Deprecated not used after file traversal rewrite to NIO + */ @NotNull public FSCache getFSCache() { return myFSCache; diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java index 476c02074c01..3f2fbd831d44 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java @@ -36,6 +36,11 @@ import org.jetbrains.jps.incremental.storage.Timestamps; import java.io.File; import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.util.*; /** @@ -212,17 +217,26 @@ public class BuildOperations { return deleted; } - private static boolean deleteRecursively(File file, Collection deletedPaths) { - File[] children = file.listFiles(); - if (children != null) { - for (File child : children) { - deleteRecursively(child, deletedPaths); - } + private static boolean deleteRecursively(final File file, final Collection deletedPaths) { + try { + Files.walkFileTree(file.toPath(), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path f, BasicFileAttributes attrs) throws IOException { + Files.delete(f); + deletedPaths.add(FileUtil.toSystemIndependentName(f.toString())); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + return true; } - boolean deleted = file.delete(); - if (deleted && children == null) { - deletedPaths.add(FileUtil.toSystemIndependentName(file.getPath())); + catch (IOException e) { + return false; } - return deleted; } } \ No newline at end of file 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 1b625a8bea50..93d03b2233d5 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java @@ -15,7 +15,7 @@ */ package org.jetbrains.jps.incremental; -import com.intellij.openapi.util.io.FileSystemUtil; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; @@ -39,6 +39,11 @@ import org.jetbrains.jps.model.module.JpsModule; import java.io.File; import java.io.FileFilter; import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.util.HashSet; import java.util.Set; @@ -222,8 +227,8 @@ public class FSOperations { if (filter == null) { context.getProjectDescriptor().fsState.clearRecompile(rd); } - final FSCache fsCache = rd.canUseFileCache() ? context.getProjectDescriptor().getFSCache() : FSCache.NO_CACHE; - completelyMarkedDirty &= traverseRecursively(context, rd, round, rd.getRootFile(), timestamps, forceMarkDirty, currentFiles, filter, fsCache); + //final FSCache fsCache = rd.canUseFileCache() ? context.getProjectDescriptor().getFSCache() : FSCache.NO_CACHE; + completelyMarkedDirty &= traverseRecursively(context, rd, round, rd.getRootFile(), timestamps, forceMarkDirty, currentFiles, filter); } if (completelyMarkedDirty) { @@ -242,41 +247,50 @@ public class FSOperations { final File file, @NotNull final Timestamps tsStorage, final boolean forceDirty, - @Nullable Set currentFiles, @Nullable FileFilter filter, @NotNull FSCache fsCache) throws IOException { - BuildRootIndex rootIndex = context.getProjectDescriptor().getBuildRootIndex(); - final File[] children = fsCache.getChildren(file); - if (children != null) { // is directory - boolean allMarkedDirty = true; - if (children.length > 0 && rootIndex.isDirectoryAccepted(file, rd)) { - for (File child : children) { - allMarkedDirty &= traverseRecursively(context, rd, round, child, tsStorage, forceDirty, currentFiles, filter, fsCache); - } + @Nullable Set currentFiles, @Nullable FileFilter filter) throws IOException { + + final BuildRootIndex rootIndex = context.getProjectDescriptor().getBuildRootIndex(); + final Ref allFilesMarked = Ref.create(Boolean.TRUE); + + Files.walkFileTree(file.toPath(), new SimpleFileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + return rootIndex.isDirectoryAccepted(dir.toFile(), rd)? FileVisitResult.CONTINUE : FileVisitResult.SKIP_SUBTREE; } - return allMarkedDirty; - } - // is file - if (!rootIndex.isFileAccepted(file, rd)) { - return true; - } - if (filter != null && !filter.accept(file)) { - return false; - } + @Override + public FileVisitResult visitFile(Path f, BasicFileAttributes attrs) throws IOException { + final File _file = f.toFile(); + if (!rootIndex.isFileAccepted(_file, rd)) { // ignored file + return FileVisitResult.CONTINUE; + } + if (filter != null && !filter.accept(_file)) { + allFilesMarked.set(Boolean.FALSE); + } + else { + boolean markDirty = forceDirty; + if (!markDirty) { + markDirty = tsStorage.getStamp(_file, rd.getTarget()) != attrs.lastModifiedTime().toMillis(); + } + if (markDirty) { + // if it is full project rebuild, all storages are already completely cleared; + // so passing null because there is no need to access the storage to clear non-existing data + final Timestamps marker = context.isProjectRebuild() ? null : tsStorage; + context.getProjectDescriptor().fsState.markDirty(context, round, _file, rd, marker, false); + } + if (currentFiles != null) { + currentFiles.add(_file); + } + if (!markDirty) { + allFilesMarked.set(Boolean.FALSE); + } + } + return FileVisitResult.CONTINUE; + } - boolean markDirty = forceDirty; - if (!markDirty) { - markDirty = tsStorage.getStamp(file, rd.getTarget()) != FileSystemUtil.lastModified(file); - } - if (markDirty) { - // if it is full project rebuild, all storages are already completely cleared; - // so passing null because there is no need to access the storage to clear non-existing data - final Timestamps marker = context.isProjectRebuild() ? null : tsStorage; - context.getProjectDescriptor().fsState.markDirty(context, round, file, rd, marker, false); - } - if (currentFiles != null) { - currentFiles.add(file); - } - return markDirty; + }); + + return allFilesMarked.get(); } public static void pruneEmptyDirs(CompileContext context, @Nullable final Set dirsToDelete) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java index 2208dcfaac46..1a6a77d4b0e8 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java @@ -34,6 +34,10 @@ import org.jetbrains.jps.model.module.JpsModule; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; import java.util.*; /** @@ -65,25 +69,26 @@ public class ResourcesBuilder extends TargetBuilder skippedRoots = new HashMap<>(); - holder.processDirtyFiles((target_, file, sourceRoot) -> { - Boolean isSkipped = skippedRoots.get(sourceRoot); + final Map skippedRoots = new HashMap<>(); + holder.processDirtyFiles((t, f, srcRoot) -> { + Boolean isSkipped = skippedRoots.get(srcRoot); if (isSkipped == null) { - File outputDir = target_.getOutputDir(); - isSkipped = Boolean.valueOf(outputDir == null || FileUtil.filesEqual(outputDir, sourceRoot.getRootFile())); - skippedRoots.put(sourceRoot, isSkipped); + File outputDir = t.getOutputDir(); + isSkipped = Boolean.valueOf(outputDir == null || FileUtil.filesEqual(outputDir, srcRoot.getRootFile())); + skippedRoots.put(srcRoot, isSkipped); } if (isSkipped.booleanValue()) { return true; } try { - copyResource(context, sourceRoot, file, outputConsumer); + copyResource(context, srcRoot, f, outputConsumer); return !context.getCancelStatus().isCanceled(); } catch (IOException e) { LOG.info(e); - String sourcePath = FileUtil.toSystemIndependentName(file.getPath()); - context.processMessage(new CompilerMessage("resources", BuildMessage.Kind.ERROR, e.getMessage(), sourcePath)); + context.processMessage( + new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, e.getMessage(), FileUtil.toSystemIndependentName(f.getPath())) + ); return false; } }); @@ -129,19 +134,28 @@ public class ResourcesBuilder extends TargetBuilder