implement first diff details

This commit is contained in:
Sebastian Sdorra
2019-07-29 12:54:58 +02:00
parent e0411ed17f
commit 01379caa08
4 changed files with 242 additions and 2 deletions

View File

@@ -6,7 +6,7 @@ public interface DiffFile extends Iterable<Hunk> {
String getNewRevision(); String getNewRevision();
String getOldName(); String getOldPath();
String getNewName(); String getNewPath();
} }

View File

@@ -0,0 +1,113 @@
package sonia.scm.repository.spi;
import com.google.common.base.Strings;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.EmptyTreeIterator;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import sonia.scm.repository.GitUtil;
import sonia.scm.util.Util;
import java.io.IOException;
import java.util.List;
import java.util.function.Consumer;
final class Differ implements AutoCloseable {
private final RevWalk walk;
private final TreeWalk treeWalk;
private final RevCommit commit;
private Differ(RevCommit commit, RevWalk walk, TreeWalk treeWalk) {
this.commit = commit;
this.walk = walk;
this.treeWalk = treeWalk;
}
public static Differ create(Repository repository, DiffCommandRequest request) throws IOException {
RevWalk walk = new RevWalk(repository);
ObjectId revision = repository.resolve(request.getRevision());
RevCommit commit = walk.parseCommit(revision);
walk.markStart(commit);
commit = walk.next();
TreeWalk treeWalk = new TreeWalk(repository);
treeWalk.reset();
treeWalk.setRecursive(true);
if (Util.isNotEmpty(request.getPath()))
{
treeWalk.setFilter(PathFilter.create(request.getPath()));
}
if (!Strings.isNullOrEmpty(request.getAncestorChangeset()))
{
ObjectId otherRevision = repository.resolve(request.getAncestorChangeset());
ObjectId ancestorId = computeCommonAncestor(repository, revision, otherRevision);
RevTree tree = walk.parseCommit(ancestorId).getTree();
treeWalk.addTree(tree);
}
else if (commit.getParentCount() > 0)
{
RevTree tree = commit.getParent(0).getTree();
if (tree != null)
{
treeWalk.addTree(tree);
}
else
{
treeWalk.addTree(new EmptyTreeIterator());
}
}
else
{
treeWalk.addTree(new EmptyTreeIterator());
}
treeWalk.addTree(commit.getTree());
return new Differ(commit, walk, treeWalk);
}
private static ObjectId computeCommonAncestor(org.eclipse.jgit.lib.Repository repository, ObjectId revision1, ObjectId revision2) throws IOException {
return GitUtil.computeCommonAncestor(repository, revision1, revision2);
}
public void process(Consumer<Diff> diffConsumer) throws IOException {
List<DiffEntry> entries = DiffEntry.scan(treeWalk);
diffConsumer.accept(new Diff(commit, entries));
}
@Override
public void close() {
GitUtil.release(walk);
GitUtil.release(treeWalk);
}
public static class Diff {
private final RevCommit commit;
private final List<DiffEntry> entries;
private Diff(RevCommit commit, List<DiffEntry> entries) {
this.commit = commit;
this.entries = entries;
}
public RevCommit getCommit() {
return commit;
}
public List<DiffEntry> getEntries() {
return entries;
}
}
}

View File

@@ -0,0 +1,85 @@
package sonia.scm.repository.spi;
import org.eclipse.jgit.diff.DiffEntry;
import sonia.scm.repository.GitUtil;
import sonia.scm.repository.Repository;
import sonia.scm.repository.api.DiffFile;
import sonia.scm.repository.api.DiffResult;
import sonia.scm.repository.api.Hunk;
import java.io.IOException;
import java.util.Iterator;
import java.util.stream.Collectors;
public class GitDiffResultCommand extends AbstractGitCommand implements DiffResultCommand {
GitDiffResultCommand(GitContext context, Repository repository) {
super(context, repository);
}
public DiffResult getDiffResult(DiffCommandRequest diffCommandRequest) throws IOException {
try (Differ differ = Differ.create(open(), diffCommandRequest)) {
GitDiffResult result = new GitDiffResult();
differ.process(result::process);
return result;
}
}
private class GitDiffResult implements DiffResult {
private Differ.Diff diff;
void process(Differ.Diff diff) {
this.diff = diff;
}
@Override
public String getOldRevision() {
return GitUtil.getId(diff.getCommit().getParent(0).getId());
}
@Override
public String getNewRevision() {
return GitUtil.getId(diff.getCommit().getId());
}
@Override
public Iterator<DiffFile> iterator() {
return diff.getEntries().stream().map(GitDiffFile::new).collect(Collectors.<DiffFile>toList()).iterator();
}
}
private static class GitDiffFile implements DiffFile {
private final DiffEntry diffEntry;
private GitDiffFile(DiffEntry diffEntry) {
this.diffEntry = diffEntry;
}
@Override
public String getOldRevision() {
return null;
}
@Override
public String getNewRevision() {
return null;
}
@Override
public String getOldPath() {
return diffEntry.getOldPath();
}
@Override
public String getNewPath() {
return diffEntry.getNewPath();
}
@Override
public Iterator<Hunk> iterator() {
return null;
}
}
}

View File

@@ -0,0 +1,42 @@
package sonia.scm.repository.spi;
import org.junit.Test;
import sonia.scm.repository.api.DiffFile;
import sonia.scm.repository.api.DiffResult;
import java.io.IOException;
import java.util.Iterator;
import static org.assertj.core.api.Assertions.assertThat;
public class GitDiffResultCommandTest extends AbstractGitCommandTestBase {
@Test
public void shouldReturnOldAndNewRevision() throws IOException {
GitDiffResultCommand gitDiffResultCommand = new GitDiffResultCommand(createContext(), repository);
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
diffCommandRequest.setRevision("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4");
DiffResult diffResult = gitDiffResultCommand.getDiffResult(diffCommandRequest);
assertThat(diffResult.getNewRevision()).isEqualTo("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4");
assertThat(diffResult.getOldRevision()).isEqualTo("592d797cd36432e591416e8b2b98154f4f163411");
}
@Test
public void shouldReturnFilePaths() throws IOException {
GitDiffResultCommand gitDiffResultCommand = new GitDiffResultCommand(createContext(), repository);
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
diffCommandRequest.setRevision("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4");
DiffResult diffResult = gitDiffResultCommand.getDiffResult(diffCommandRequest);
Iterator<DiffFile> iterator = diffResult.iterator();
DiffFile a = iterator.next();
assertThat(a.getNewPath()).isEqualTo("a.txt");
assertThat(a.getOldPath()).isEqualTo("a.txt");
DiffFile b = iterator.next();
assertThat(b.getOldPath()).isEqualTo("b.txt");
assertThat(b.getNewPath()).isEqualTo("/dev/null");
}
}