summaryrefslogtreecommitdiffstats
path: root/sonar-batch/src/main/java
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2016-03-14 10:13:26 +0100
committerDuarte Meneses <duarte.meneses@sonarsource.com>2016-03-15 11:51:50 +0100
commit717e75bc7827bc798ad455543e6d81bce7be4b9e (patch)
tree45dd02a797422f49823821416eb10017286d78a9 /sonar-batch/src/main/java
parent55039a7a500530ae049b4b4c991bafa75faf1ac7 (diff)
downloadsonarqube-717e75bc7827bc798ad455543e6d81bce7be4b9e.tar.gz
sonarqube-717e75bc7827bc798ad455543e6d81bce7be4b9e.zip
SONAR-7328 Ignore "recursive" folder indexation caused by symlink
Diffstat (limited to 'sonar-batch/src/main/java')
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectLock.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java87
2 files changed, 72 insertions, 17 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectLock.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectLock.java
index a9a0e2a4d41..d37987adfe6 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectLock.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectLock.java
@@ -29,7 +29,7 @@ import java.nio.channels.OverlappingFileLockException;
import java.nio.file.Path;
public class ProjectLock implements Startable {
- static final String LOCK_FILE_NAME = ".sonar_lock";
+ public static final String LOCK_FILE_NAME = ".sonar_lock";
private DirectoryLock lock;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java
index 2dd548a7c86..ad825731593 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java
@@ -20,27 +20,32 @@
package org.sonar.batch.scan.filesystem;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.filefilter.FileFilterUtils;
-import org.apache.commons.io.filefilter.HiddenFileFilter;
-import org.apache.commons.io.filefilter.IOFileFilter;
+import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.BatchSide;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputFile.Type;
import org.sonar.api.batch.fs.InputFileFilter;
import org.sonar.api.batch.fs.internal.DefaultInputDir;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.api.utils.MessageException;
+import org.sonar.batch.scan.ProjectLock;
import org.sonar.batch.util.ProgressReport;
import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileSystemLoopException;
+import java.nio.file.FileVisitOption;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
-import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -58,10 +63,6 @@ import java.util.concurrent.TimeUnit;
public class FileIndexer {
private static final Logger LOG = LoggerFactory.getLogger(FileIndexer.class);
-
- private static final IOFileFilter DIR_FILTER = FileFilterUtils.and(HiddenFileFilter.VISIBLE, FileFilterUtils.notFileFilter(FileFilterUtils.prefixFileFilter(".")));
- private static final IOFileFilter FILE_FILTER = FileFilterUtils.and(HiddenFileFilter.VISIBLE, FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter(".sonar_lock")));
-
private final List<InputFileFilter> filters;
private final boolean isAggregator;
private final ExclusionFilters exclusionFilters;
@@ -123,18 +124,22 @@ public class FileIndexer {
private void indexFiles(DefaultModuleFileSystem fileSystem, Progress progress, InputFileBuilder inputFileBuilder, List<File> sources, InputFile.Type type) {
for (File dirOrFile : sources) {
if (dirOrFile.isDirectory()) {
- indexDirectory(inputFileBuilder, fileSystem, progress, dirOrFile, type);
+ try {
+ indexDirectory(inputFileBuilder, fileSystem, progress, dirOrFile, type);
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to index files", e);
+ }
} else {
indexFile(inputFileBuilder, fileSystem, progress, dirOrFile, type);
}
}
}
- private void indexDirectory(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fileSystem, Progress status, File dirToIndex, InputFile.Type type) {
- Collection<File> files = FileUtils.listFiles(dirToIndex, FILE_FILTER, DIR_FILTER);
- for (File file : files) {
- indexFile(inputFileBuilder, fileSystem, status, file, type);
- }
+ private void indexDirectory(final InputFileBuilder inputFileBuilder, final DefaultModuleFileSystem fileSystem, final Progress status,
+ final File dirToIndex, final InputFile.Type type) throws IOException {
+ final Path absDir = dirToIndex.toPath().normalize();
+ Files.walkFileTree(absDir, Collections.singleton(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
+ new IndexFileVisitor(inputFileBuilder, fileSystem, status, type));
}
private void indexFile(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fileSystem, Progress progress, File sourceFile, InputFile.Type type) {
@@ -183,6 +188,56 @@ public class FileIndexer {
return true;
}
+ private class IndexFileVisitor implements FileVisitor<Path> {
+ private InputFileBuilder inputFileBuilder;
+ private DefaultModuleFileSystem fileSystem;
+ private Progress status;
+ private Type type;
+
+ IndexFileVisitor(InputFileBuilder inputFileBuilder, DefaultModuleFileSystem fileSystem, Progress status, InputFile.Type type) {
+ this.inputFileBuilder = inputFileBuilder;
+ this.fileSystem = fileSystem;
+ this.status = status;
+ this.type = type;
+ }
+
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+ Path fileName = dir.getFileName();
+
+ if (fileName != null && StringUtils.isNotEmpty(fileName.toString()) && fileName.toString().charAt(0) == '.') {
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ if (Files.isHidden(dir)) {
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ if (!Files.isHidden(file) && !ProjectLock.LOCK_FILE_NAME.equals(file.getFileName().toString())) {
+ indexFile(inputFileBuilder, fileSystem, status, file.toFile(), type);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
+ if (exc != null && exc instanceof FileSystemLoopException) {
+ LOG.warn("Not indexing due to symlink loop: {}", file.toFile());
+ return FileVisitResult.CONTINUE;
+ }
+
+ throw exc;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+ }
+
private class Progress {
private final Set<Path> indexed = new HashSet<>();
private int excludedByPatternsCount = 0;