diff --git a/LauncherCore/src/main/java/pro/gravit/launcher/hasher/HashedDir.java b/LauncherCore/src/main/java/pro/gravit/launcher/hasher/HashedDir.java index 71b28e17..83d3d6a2 100644 --- a/LauncherCore/src/main/java/pro/gravit/launcher/hasher/HashedDir.java +++ b/LauncherCore/src/main/java/pro/gravit/launcher/hasher/HashedDir.java @@ -10,10 +10,12 @@ import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Path; +import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.*; import java.util.Map.Entry; +import java.util.function.Predicate; public final class HashedDir extends HashedEntry { @LauncherNetworkAPI @@ -63,6 +65,60 @@ public Diff compare(HashedDir other, FileNameMatcher matcher) { return new Diff(mismatch, extra); } + public HashedDir filter(Predicate filter) { + return filterAndAdd(new HashedDir(), filter); + } + + public HashedDir filterAndAdd(HashedDir result, Predicate filter) { + Queue queue = new ArrayDeque<>(); + Path path = Paths.get(""); + queue.add(new HashedEntryAndPath(path, this, result)); + while(!queue.isEmpty()) { + HashedEntryAndPath entry = queue.poll(); + if(!filter.test(entry.path)) { + continue; + } + if(entry.entry.getType() == Type.DIR) { + HashedDir dir = (HashedDir) entry.entry; + for(Map.Entry e : dir.map.entrySet()) { + String key = e.getKey(); + HashedEntry value = e.getValue(); + if(entry.sideEntry.getType() == Type.FILE) { + throw new IllegalArgumentException(String.format("Filter path: %s failed: expected DIR, found FILE ", entry.path)); + } + HashedDir sideDir = (HashedDir) entry.sideEntry; + HashedEntry sideEntry = sideDir.getEntry(key); + if(sideEntry == null) { + if(value.getType() == Type.DIR) { + sideEntry = new HashedDir(); + queue.add(new HashedEntryAndPath(entry.path.resolve(key), value, sideEntry)); + } else if(value.getType() == Type.FILE) { + sideEntry = value; + } + sideDir.map.put(key, sideEntry); + } else if(sideEntry.getType() == Type.DIR) { + queue.add(new HashedEntryAndPath(entry.path.resolve(key), value, sideEntry)); + } + } + } + } + return result; + } + + + + private static class HashedEntryAndPath { + public final HashedEntry entry; + public final HashedEntry sideEntry; + public final Path path; + + public HashedEntryAndPath(Path path, HashedEntry entry, HashedEntry sideEntry) { + this.entry = entry; + this.path = path; + this.sideEntry = sideEntry; + } + } + public void remove(String name) { map.remove(name); } diff --git a/LauncherCore/src/main/java/pro/gravit/launcher/hasher/HashedEntry.java b/LauncherCore/src/main/java/pro/gravit/launcher/hasher/HashedEntry.java index d8e491c9..dec01ff3 100644 --- a/LauncherCore/src/main/java/pro/gravit/launcher/hasher/HashedEntry.java +++ b/LauncherCore/src/main/java/pro/gravit/launcher/hasher/HashedEntry.java @@ -16,7 +16,6 @@ public abstract class HashedEntry extends StreamObject { public abstract long size(); - public enum Type implements EnumSerializer.Itf { DIR(1), FILE(2); private static final EnumSerializer SERIALIZER = new EnumSerializer<>(Type.class);