89 lines
3.0 KiB
Java
89 lines
3.0 KiB
Java
package io.gitlab.jfronny.inceptum.launcher.util.gitignore;
|
|
|
|
import java.io.IOException;
|
|
import java.io.UncheckedIOException;
|
|
import java.nio.file.*;
|
|
import java.util.*;
|
|
import java.util.stream.Stream;
|
|
import java.util.stream.StreamSupport;
|
|
|
|
public class IgnoringWalk implements Iterator<Path> {
|
|
public static Stream<Path> walk(Path repositoryRoot) throws IOException {
|
|
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(new IgnoringWalk(repositoryRoot), 0), false);
|
|
}
|
|
|
|
private static final String GITIGNORE = ".gitignore";
|
|
private static final String ICEIGNORE = ".iceignore";
|
|
private static final String GIT = ".git";
|
|
|
|
private final Path ref;
|
|
private final Queue<Path> toScan = new ArrayDeque<>(); // A queue of absolute Paths which must still be scanned/returned
|
|
private final Map<Path, Ignore> ignores = new HashMap<>();
|
|
private Path next;
|
|
|
|
private IgnoringWalk(Path repositoryRoot) throws IOException {
|
|
this.ref = repositoryRoot;
|
|
enqueueDirectory(repositoryRoot);
|
|
}
|
|
|
|
@Override
|
|
public Path next() {
|
|
if (!hasNext()) throw new NoSuchElementException();
|
|
Path ret = next;
|
|
next = null;
|
|
return ret;
|
|
}
|
|
|
|
@Override
|
|
public boolean hasNext() {
|
|
if (next != null) return true;
|
|
next = toScan.poll();
|
|
if (next == null) return false;
|
|
if (Files.isDirectory(next)) {
|
|
try {
|
|
enqueueDirectory(next);
|
|
} catch (IOException e) {
|
|
throw new UncheckedIOException(e);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private void enqueueDirectory(Path directory) throws IOException {
|
|
Path gitignorePath = directory.resolve(GITIGNORE);
|
|
Path iceignorePath = directory.resolve(ICEIGNORE);
|
|
Ignore ignore = null;
|
|
if (Files.exists(gitignorePath)) {
|
|
if (ignore == null) ignore = new Ignore();
|
|
ignore.add(Files.readAllLines(gitignorePath));
|
|
}
|
|
if (Files.exists(iceignorePath)) {
|
|
if (ignore == null) ignore = new Ignore();
|
|
ignore.add(Files.readAllLines(iceignorePath));
|
|
}
|
|
if (ignore != null) ignores.put(directory, ignore);
|
|
try (DirectoryStream<Path> files = Files.newDirectoryStream(directory)) {
|
|
for (Path path : files) {
|
|
String fileName = path.getFileName().toString();
|
|
if (!fileName.equals(GITIGNORE)
|
|
&& !fileName.equals(ICEIGNORE)
|
|
&& !fileName.equals(GIT)
|
|
&& !isIgnored(ref.relativize(path))) {
|
|
toScan.add(path);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private boolean isIgnored(Path relativePath) {
|
|
Path constructed = ref;
|
|
for (Path segment : relativePath) {
|
|
Ignore ignore = ignores.get(constructed);
|
|
if (ignore != null && ignore.isIgnored(relativePath.toString()))
|
|
return true;
|
|
constructed = constructed.resolve(segment);
|
|
}
|
|
return false;
|
|
}
|
|
}
|