mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
rewrite file traversal, output files deletion and resource copying with NIO
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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<String> deletedPaths) {
|
||||
File[] children = file.listFiles();
|
||||
if (children != null) {
|
||||
for (File child : children) {
|
||||
deleteRecursively(child, deletedPaths);
|
||||
}
|
||||
private static boolean deleteRecursively(final File file, final Collection<String> deletedPaths) {
|
||||
try {
|
||||
Files.walkFileTree(file.toPath(), new SimpleFileVisitor<Path>() {
|
||||
@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;
|
||||
}
|
||||
}
|
||||
@@ -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<File> 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<File> currentFiles, @Nullable FileFilter filter) throws IOException {
|
||||
|
||||
final BuildRootIndex rootIndex = context.getProjectDescriptor().getBuildRootIndex();
|
||||
final Ref<Boolean> allFilesMarked = Ref.create(Boolean.TRUE);
|
||||
|
||||
Files.walkFileTree(file.toPath(), new SimpleFileVisitor<Path>() {
|
||||
@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<File> dirsToDelete) {
|
||||
|
||||
+28
-14
@@ -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<ResourceRootDescriptor, Reso
|
||||
}
|
||||
|
||||
try {
|
||||
Map<ResourceRootDescriptor, Boolean> skippedRoots = new HashMap<>();
|
||||
holder.processDirtyFiles((target_, file, sourceRoot) -> {
|
||||
Boolean isSkipped = skippedRoots.get(sourceRoot);
|
||||
final Map<ResourceRootDescriptor, Boolean> 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<ResourceRootDescriptor, Reso
|
||||
|
||||
context.processMessage(new ProgressMessage("Copying resources... [" + rd.getTarget().getModule().getName() + "]"));
|
||||
|
||||
final String outputPath = targetPath.toString();
|
||||
final File targetFile = new File(outputPath);
|
||||
FileUtil.copyContent(file, targetFile);
|
||||
final File targetFile = new File(targetPath.toString());
|
||||
try {
|
||||
final Path from = file.toPath();
|
||||
final Path to = targetFile.toPath();
|
||||
try {
|
||||
Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
catch (NoSuchFileException e) {
|
||||
final File parent = targetFile.getParentFile();
|
||||
if (parent != null && parent.mkdirs()) {
|
||||
Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING); // repeat on successful target dir creation
|
||||
}
|
||||
}
|
||||
outputConsumer.registerOutputFile(targetFile, Collections.singletonList(file.getPath()));
|
||||
}
|
||||
catch (Exception e) {
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, e));
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, CompilerMessage.getTextFromThrowable(e)));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getPresentableName() {
|
||||
return "Resource Compiler";
|
||||
return BUILDER_NAME;
|
||||
}
|
||||
}
|
||||
+15
-1
@@ -31,6 +31,10 @@ import org.jetbrains.jps.model.JpsEncodingProjectConfiguration;
|
||||
import org.jetbrains.jps.model.JpsProject;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
@@ -77,7 +81,17 @@ public class MavenResourceFileProcessor {
|
||||
copyWithFiltering(file, targetFile);
|
||||
}
|
||||
else {
|
||||
FileUtil.copyContent(file, targetFile);
|
||||
final Path from = file.toPath();
|
||||
final Path to = targetFile.toPath();
|
||||
try {
|
||||
Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
catch (NoSuchFileException e) {
|
||||
final File parent = targetFile.getParentFile();
|
||||
if (parent != null && parent.mkdirs()) {
|
||||
Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING); // repeat on successful target dir creation
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user