/*
* This file is part of Fim - File Integrity Manager
*
* Copyright (C) 2017 Etienne Vrignaud
*
* Fim is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fim is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Fim. If not, see <http://www.gnu.org/licenses/>.
*/
package org.fim.internal;
import org.fim.model.Context;
import org.fim.model.FileToIgnore;
import org.fim.model.FimIgnore;
import org.fim.util.FileUtil;
import org.fim.util.Logger;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
public class FimIgnoreManager {
public static final String DOT_FIM_IGNORE = ".fimignore";
public static final String ALL_DIRECTORIES_PATTERN = "**/";
public static final Set IGNORED_DIRECTORIES = new HashSet<>(Arrays.asList(Context.DOT_FIM_DIR, ".git", ".svn", ".cvs"));
private final Context context;
private String repositoryRootDirString;
private Set<String> ignoredFiles;
public FimIgnoreManager(Context context) {
this.context = context;
this.repositoryRootDirString = FileUtil.getNormalizedFileName(this.context.getRepositoryRootDir());
this.ignoredFiles = new HashSet<>();
}
public FimIgnore loadInitialFimIgnore() {
FimIgnore initialFimIgnore = loadGlobalFimIgnore();
addParentFimIgnore(initialFimIgnore);
return initialFimIgnore;
}
public FimIgnore loadLocalIgnore(Path directory, FimIgnore parentFimIgnore) {
FimIgnore fimIgnore = loadFimIgnore(directory);
fimIgnore.getFilesToIgnoreInAllDirectories().addAll(parentFimIgnore.getFilesToIgnoreInAllDirectories());
return fimIgnore;
}
/**
* If Fim is started from a sub-directory, it loads the parent .fimignore files and merge all the filesToIgnoreInAllDirectories.
*/
private void addParentFimIgnore(FimIgnore initialFimIgnore) {
Path directory = context.getAbsoluteCurrentDirectory();
while (false == directory.equals(context.getRepositoryRootDir())) {
directory = directory.getParent();
if (directory == null) {
break;
}
FimIgnore fimIgnore = loadFimIgnore(directory);
initialFimIgnore.getFilesToIgnoreInAllDirectories().addAll(fimIgnore.getFilesToIgnoreInAllDirectories());
}
}
private FimIgnore loadGlobalFimIgnore() {
Path userDir = Paths.get(System.getProperty("user.dir"));
return loadFimIgnore(userDir);
}
protected FimIgnore loadFimIgnore(Path directory) {
FimIgnore fimIgnore = new FimIgnore();
Path dotFimIgnore = directory.resolve(DOT_FIM_IGNORE);
if (Files.exists(dotFimIgnore)) {
try {
List<String> allLines = Files.readAllLines(dotFimIgnore);
for (String line : allLines) {
if (line.startsWith(ALL_DIRECTORIES_PATTERN)) {
String fileNamePattern = line.substring(ALL_DIRECTORIES_PATTERN.length());
FileToIgnore fileToIgnore = new FileToIgnore(fileNamePattern);
fimIgnore.getFilesToIgnoreInAllDirectories().add(fileToIgnore);
} else {
FileToIgnore fileToIgnore = new FileToIgnore(line);
fimIgnore.getFilesToIgnoreLocally().add(fileToIgnore);
}
}
} catch (IOException e) {
Logger.error(String.format("Unable to read file %s: %s", dotFimIgnore, e.getMessage()));
}
}
return fimIgnore;
}
// -----------------------------------------------------------------------------------------------------------------
public boolean isIgnored(String fileName, BasicFileAttributes attributes, FimIgnore fimIgnore) {
if (attributes.isDirectory() && IGNORED_DIRECTORIES.contains(fileName)) {
return true;
}
if (isIgnored(fileName, fimIgnore.getFilesToIgnoreInAllDirectories())) {
return true;
}
if (isIgnored(fileName, fimIgnore.getFilesToIgnoreLocally())) {
return true;
}
return false;
}
private boolean isIgnored(String fileName, Set<FileToIgnore> filesToIgnore) {
for (FileToIgnore fileToIgnore : filesToIgnore) {
if (fileToIgnore.getCompiledPattern() != null) {
Matcher matcher = fileToIgnore.getCompiledPattern().matcher(fileName);
if (matcher.find()) {
return true;
}
} else if (fileToIgnore.getFileNamePattern().equals(fileName)) {
return true;
}
}
return false;
}
public void ignoreThisFiles(Path file, BasicFileAttributes attributes) {
String normalizedFileName = FileUtil.getNormalizedFileName(file);
if (attributes.isDirectory()) {
normalizedFileName = normalizedFileName + "/";
}
String relativeFileName = FileUtil.getRelativeFileName(repositoryRootDirString, normalizedFileName);
ignoredFiles.add(relativeFileName);
}
public Set<String> getIgnoredFiles() {
return ignoredFiles;
}
}