com.beijunyi.parallelgit.filesystem.io.GfsTreeIterator Maven / Gradle / Ivy
package com.beijunyi.parallelgit.filesystem.io;
import java.io.IOException;
import java.util.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.beijunyi.parallelgit.filesystem.GfsFileStore;
import com.beijunyi.parallelgit.filesystem.GitFileSystem;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.WorkingTreeIterator;
import org.eclipse.jgit.treewalk.WorkingTreeOptions;
import static java.lang.System.arraycopy;
import static java.util.Collections.*;
import static org.eclipse.jgit.lib.Constants.*;
public class GfsTreeIterator extends WorkingTreeIterator {
private final List files;
private int index = -1;
private ObjectId id;
private GfsTreeIterator(List files, GfsTreeIterator parent) {
super(parent);
this.files = files;
next(1);
}
private GfsTreeIterator(List files) {
super((WorkingTreeOptions) null);
this.files = files;
next(1);
}
private GfsTreeIterator(DirectoryNode node) throws IOException {
this(GfsTreeEntry.listChildren(node));
}
private GfsTreeIterator(GfsFileStore store) throws IOException {
this(store.getRoot());
}
private GfsTreeIterator(GitFileSystem gfs) throws IOException {
this(gfs.getFileStore());
}
@Nonnull
public static GfsTreeIterator iterateRoot(GitFileSystem gfs) throws IOException {
return new GfsTreeIterator(gfs);
}
@Override
public boolean isModified(@Nullable DirCacheEntry entry, boolean forceContentCheck, ObjectReader reader) throws IOException {
GfsTreeEntry current = currentEntry();
return entry == null || !current.getId().equals(entry.getObjectId()) || !current.getMode().equals(entry.getFileMode());
}
@Override
public boolean hasId() {
return index >= 0 && index < files.size();
}
@Override
public byte[] idBuffer() {
byte[] ret = new byte[OBJECT_ID_LENGTH];
id.copyRawTo(ret, 0);
return ret;
}
@Override
public int idOffset() {
return 0;
}
@Nonnull
@Override
public AbstractTreeIterator createSubtreeIterator(ObjectReader reader) throws IOException {
GfsTreeEntry entry = currentEntry();
return new GfsTreeIterator(entry.listChildren(), this);
}
@Override
public boolean first() {
return index == 0;
}
@Override
public boolean eof() {
return index == files.size();
}
@Override
public void next(int delta) {
index = Math.min(files.size(), index + delta);
if(!eof()) readEntry();
}
@Override
public void back(int delta) {
index = Math.max(0, index - delta);
readEntry();
}
@Nonnull
private GfsTreeEntry currentEntry() {
return files.get(index);
}
private void readEntry() {
GfsTreeEntry entry = currentEntry();
mode = entry.getMode().getBits();
id = entry.getId();
byte[] name = encode(entry.getName());
ensurePathCapacity(pathOffset + name.length, pathOffset);
arraycopy(name, 0, path, pathOffset, name.length);
pathLen = pathOffset + name.length;
}
private static class GfsTreeEntry {
private final String name;
private final Node node;
private GfsTreeEntry(String name, Node node) {
this.name = name;
this.node = node;
}
@Nonnull
public static GfsTreeEntry forNode(String name, Node node) {
return new GfsTreeEntry(name, node);
}
@Nonnull
public String getName() {
return name;
}
@Nonnull
public ObjectId getId() {
try {
return node.getObjectId(false);
} catch(IOException e) {
throw new IllegalStateException(e);
}
}
@Nonnull
public FileMode getMode() {
return node.getMode();
}
@Nonnull
public List listChildren() throws IOException {
if(!node.isDirectory())
throw new IllegalStateException();
return listChildren((DirectoryNode) node);
}
@Nonnull
public static List listChildren(DirectoryNode dir) throws IOException {
List ret = new ArrayList<>();
for(Map.Entry child : dir.getData().entrySet()) {
Node node = child.getValue();
if(!node.isTrivial()) ret.add(forNode(child.getKey(), node));
}
sort(ret, TreeEntryComparator.ASCENDING);
return unmodifiableList(ret);
}
}
private static class TreeEntryComparator implements Comparator {
private static TreeEntryComparator ASCENDING = new TreeEntryComparator();
@Override
public int compare(GfsTreeEntry o1, GfsTreeEntry o2) {
return o1.getName().compareTo(o2.getName());
}
}
}