mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-14 01:15:44 +01:00
Merged in feature/diff_two_revisions (pull request #101)
Feature diff between two revisions
This commit is contained in:
@@ -109,6 +109,9 @@ public final class DiffCommandRequest extends FileBaseCommandRequest
|
|||||||
this.format = format;
|
this.format = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAncestorChangeset(String ancestorChangeset) {
|
||||||
|
this.ancestorChangeset = ancestorChangeset;
|
||||||
|
}
|
||||||
//~--- get methods ----------------------------------------------------------
|
//~--- get methods ----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,8 +127,13 @@ public final class DiffCommandRequest extends FileBaseCommandRequest
|
|||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getAncestorChangeset() {
|
||||||
|
return ancestorChangeset;
|
||||||
|
}
|
||||||
//~--- fields ---------------------------------------------------------------
|
//~--- fields ---------------------------------------------------------------
|
||||||
|
|
||||||
/** diff format */
|
/** diff format */
|
||||||
private DiffFormat format = DiffFormat.NATIVE;
|
private DiffFormat format = DiffFormat.NATIVE;
|
||||||
|
|
||||||
|
private String ancestorChangeset;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import org.eclipse.jgit.lib.ObjectId;
|
|||||||
import org.eclipse.jgit.lib.Ref;
|
import org.eclipse.jgit.lib.Ref;
|
||||||
import org.eclipse.jgit.revwalk.RevCommit;
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
import org.eclipse.jgit.revwalk.RevWalk;
|
import org.eclipse.jgit.revwalk.RevWalk;
|
||||||
|
import org.eclipse.jgit.revwalk.filter.RevFilter;
|
||||||
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
|
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
|
||||||
import org.eclipse.jgit.transport.FetchResult;
|
import org.eclipse.jgit.transport.FetchResult;
|
||||||
import org.eclipse.jgit.transport.RefSpec;
|
import org.eclipse.jgit.transport.RefSpec;
|
||||||
@@ -716,6 +717,18 @@ public final class GitUtil
|
|||||||
return (id != null) &&!id.equals(ObjectId.zeroId());
|
return (id != null) &&!id.equals(ObjectId.zeroId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the first common ancestor of two revisions, aka merge base.
|
||||||
|
*/
|
||||||
|
public static ObjectId computeCommonAncestor(org.eclipse.jgit.lib.Repository repository, ObjectId revision1, ObjectId revision2) throws IOException {
|
||||||
|
try (RevWalk mergeBaseWalk = new RevWalk(repository)) {
|
||||||
|
mergeBaseWalk.setRevFilter(RevFilter.MERGE_BASE);
|
||||||
|
mergeBaseWalk.markStart(mergeBaseWalk.lookupCommit(revision1));
|
||||||
|
mergeBaseWalk.markStart(mergeBaseWalk.parseCommit(revision2));
|
||||||
|
return mergeBaseWalk.next().getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
//~--- methods --------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -34,27 +34,25 @@ package sonia.scm.repository.spi;
|
|||||||
|
|
||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import org.eclipse.jgit.diff.DiffEntry;
|
import org.eclipse.jgit.diff.DiffEntry;
|
||||||
import org.eclipse.jgit.diff.DiffFormatter;
|
import org.eclipse.jgit.diff.DiffFormatter;
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
import org.eclipse.jgit.revwalk.RevCommit;
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
import org.eclipse.jgit.revwalk.RevTree;
|
import org.eclipse.jgit.revwalk.RevTree;
|
||||||
import org.eclipse.jgit.revwalk.RevWalk;
|
import org.eclipse.jgit.revwalk.RevWalk;
|
||||||
import org.eclipse.jgit.treewalk.EmptyTreeIterator;
|
import org.eclipse.jgit.treewalk.EmptyTreeIterator;
|
||||||
import org.eclipse.jgit.treewalk.TreeWalk;
|
import org.eclipse.jgit.treewalk.TreeWalk;
|
||||||
import org.eclipse.jgit.treewalk.filter.PathFilter;
|
import org.eclipse.jgit.treewalk.filter.PathFilter;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import sonia.scm.repository.GitUtil;
|
import sonia.scm.repository.GitUtil;
|
||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
import sonia.scm.util.Util;
|
import sonia.scm.util.Util;
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
|
||||||
|
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,7 +105,8 @@ public class GitDiffCommand extends AbstractGitCommand implements DiffCommand
|
|||||||
|
|
||||||
walk = new RevWalk(gr);
|
walk = new RevWalk(gr);
|
||||||
|
|
||||||
RevCommit commit = walk.parseCommit(gr.resolve(request.getRevision()));
|
ObjectId revision = gr.resolve(request.getRevision());
|
||||||
|
RevCommit commit = walk.parseCommit(revision);
|
||||||
|
|
||||||
walk.markStart(commit);
|
walk.markStart(commit);
|
||||||
commit = walk.next();
|
commit = walk.next();
|
||||||
@@ -120,7 +119,15 @@ public class GitDiffCommand extends AbstractGitCommand implements DiffCommand
|
|||||||
treeWalk.setFilter(PathFilter.create(request.getPath()));
|
treeWalk.setFilter(PathFilter.create(request.getPath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commit.getParentCount() > 0)
|
|
||||||
|
if (!Strings.isNullOrEmpty(request.getAncestorChangeset()))
|
||||||
|
{
|
||||||
|
ObjectId otherRevision = gr.resolve(request.getAncestorChangeset());
|
||||||
|
ObjectId ancestorId = computeCommonAncestor(gr, revision, otherRevision);
|
||||||
|
RevTree tree = walk.parseCommit(ancestorId).getTree();
|
||||||
|
treeWalk.addTree(tree);
|
||||||
|
}
|
||||||
|
else if (commit.getParentCount() > 0)
|
||||||
{
|
{
|
||||||
RevTree tree = commit.getParent(0).getTree();
|
RevTree tree = commit.getParent(0).getTree();
|
||||||
|
|
||||||
@@ -156,7 +163,6 @@ public class GitDiffCommand extends AbstractGitCommand implements DiffCommand
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
||||||
// TODO throw exception
|
// TODO throw exception
|
||||||
logger.error("could not create diff", ex);
|
logger.error("could not create diff", ex);
|
||||||
}
|
}
|
||||||
@@ -167,4 +173,9 @@ public class GitDiffCommand extends AbstractGitCommand implements DiffCommand
|
|||||||
GitUtil.release(formatter);
|
GitUtil.release(formatter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ObjectId computeCommonAncestor(org.eclipse.jgit.lib.Repository repository, ObjectId revision1, ObjectId revision2) throws IOException {
|
||||||
|
return GitUtil.computeCommonAncestor(repository, revision1, revision2);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package sonia.scm.repository.spi;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class GitDiffCommandTest extends AbstractGitCommandTestBase {
|
||||||
|
|
||||||
|
public static final String DIFF_FILE_A = "diff --git a/a.txt b/a.txt\n" +
|
||||||
|
"index 7898192..1dc60c7 100644\n" +
|
||||||
|
"--- a/a.txt\n" +
|
||||||
|
"+++ b/a.txt\n" +
|
||||||
|
"@@ -1 +1 @@\n" +
|
||||||
|
"-a\n" +
|
||||||
|
"+a and b\n";
|
||||||
|
public static final String DIFF_FILE_B = "diff --git a/b.txt b/b.txt\n" +
|
||||||
|
"deleted file mode 100644\n" +
|
||||||
|
"index 6178079..0000000\n" +
|
||||||
|
"--- a/b.txt\n" +
|
||||||
|
"+++ /dev/null\n" +
|
||||||
|
"@@ -1 +0,0 @@\n" +
|
||||||
|
"-b\n";
|
||||||
|
public static final String DIFF_FILE_A_MULTIPLE_REVISIONS = "diff --git a/a.txt b/a.txt\n" +
|
||||||
|
"index 7898192..2f8bc28 100644\n" +
|
||||||
|
"--- a/a.txt\n" +
|
||||||
|
"+++ b/a.txt\n" +
|
||||||
|
"@@ -1 +1,2 @@\n" +
|
||||||
|
" a\n" +
|
||||||
|
"+line for blame\n";
|
||||||
|
public static final String DIFF_FILE_F_MULTIPLE_REVISIONS = "diff --git a/f.txt b/f.txt\n" +
|
||||||
|
"new file mode 100644\n" +
|
||||||
|
"index 0000000..6a69f92\n" +
|
||||||
|
"--- /dev/null\n" +
|
||||||
|
"+++ b/f.txt\n" +
|
||||||
|
"@@ -0,0 +1 @@\n" +
|
||||||
|
"+f\n";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void diffForOneRevisionShouldCreateDiff() {
|
||||||
|
GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository);
|
||||||
|
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
||||||
|
diffCommandRequest.setRevision("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4");
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
gitDiffCommand.getDiffResult(diffCommandRequest, output);
|
||||||
|
assertEquals(DIFF_FILE_A + DIFF_FILE_B, output.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void diffForOneBranchShouldCreateDiff() {
|
||||||
|
GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository);
|
||||||
|
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
||||||
|
diffCommandRequest.setRevision("test-branch");
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
gitDiffCommand.getDiffResult(diffCommandRequest, output);
|
||||||
|
assertEquals(DIFF_FILE_A + DIFF_FILE_B, output.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void diffForPathShouldCreateLimitedDiff() {
|
||||||
|
GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository);
|
||||||
|
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
||||||
|
diffCommandRequest.setRevision("test-branch");
|
||||||
|
diffCommandRequest.setPath("a.txt");
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
gitDiffCommand.getDiffResult(diffCommandRequest, output);
|
||||||
|
assertEquals(DIFF_FILE_A, output.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void diffBetweenTwoBranchesShouldCreateDiff() {
|
||||||
|
GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository);
|
||||||
|
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
||||||
|
diffCommandRequest.setRevision("master");
|
||||||
|
diffCommandRequest.setAncestorChangeset("test-branch");
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
gitDiffCommand.getDiffResult(diffCommandRequest, output);
|
||||||
|
assertEquals(DIFF_FILE_A_MULTIPLE_REVISIONS + DIFF_FILE_F_MULTIPLE_REVISIONS, output.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void diffBetweenTwoBranchesForPathShouldCreateLimitedDiff() {
|
||||||
|
GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository);
|
||||||
|
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
||||||
|
diffCommandRequest.setRevision("master");
|
||||||
|
diffCommandRequest.setAncestorChangeset("test-branch");
|
||||||
|
diffCommandRequest.setPath("a.txt");
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
gitDiffCommand.getDiffResult(diffCommandRequest, output);
|
||||||
|
assertEquals(DIFF_FILE_A_MULTIPLE_REVISIONS, output.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user