From a725e4232b3648dbd6405de801ebcdc9171d3d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 6 Nov 2018 11:26:36 +0100 Subject: [PATCH 1/5] Add unit test for git diff command --- .../repository/spi/GitDiffCommandTest.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java new file mode 100644 index 0000000000..3b12fb0c3f --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java @@ -0,0 +1,45 @@ +package sonia.scm.repository.spi; + +import org.junit.Test; + +import java.io.ByteArrayOutputStream; + +import static org.junit.Assert.assertEquals; + +public class GitDiffCommandTest extends AbstractGitCommandTestBase { + + private static final String DIFF_LATEST_COMMIT_TEST_BRANCH = "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" + + "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"; + + @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_LATEST_COMMIT_TEST_BRANCH, 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_LATEST_COMMIT_TEST_BRANCH, output.toString()); + } +} From 8be8c19a266622e9b3486a18ca6b6c952b970f41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 6 Nov 2018 12:04:33 +0100 Subject: [PATCH 2/5] Implement diff between two changesets for git --- .../repository/spi/DiffCommandRequest.java | 12 +++++++-- .../java/sonia/scm/repository/GitUtil.java | 13 +++++++++ .../scm/repository/spi/GitDiffCommand.java | 27 +++++++++++++------ .../repository/spi/GitDiffCommandTest.java | 24 +++++++++++++++++ 4 files changed, 66 insertions(+), 10 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/DiffCommandRequest.java b/scm-core/src/main/java/sonia/scm/repository/spi/DiffCommandRequest.java index 5cfd57f71b..e26b2eb5aa 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/DiffCommandRequest.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/DiffCommandRequest.java @@ -109,7 +109,10 @@ public final class DiffCommandRequest extends FileBaseCommandRequest this.format = format; } - //~--- get methods ---------------------------------------------------------- + public void setAncestorChangeset(String ancestorChangeset) { + this.ancestorChangeset = ancestorChangeset; + } +//~--- get methods ---------------------------------------------------------- /** * Return the output format of the diff command. @@ -124,8 +127,13 @@ public final class DiffCommandRequest extends FileBaseCommandRequest return format; } - //~--- fields --------------------------------------------------------------- + public String getAncestorChangeset() { + return ancestorChangeset; + } +//~--- fields --------------------------------------------------------------- /** diff format */ private DiffFormat format = DiffFormat.NATIVE; + + private String ancestorChangeset; } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java index 13340a20e7..6d7be2e93c 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java @@ -48,6 +48,7 @@ import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.revwalk.filter.RevFilter; import org.eclipse.jgit.storage.file.FileRepositoryBuilder; import org.eclipse.jgit.transport.FetchResult; import org.eclipse.jgit.transport.RefSpec; @@ -716,6 +717,18 @@ public final class GitUtil 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 -------------------------------------------------------------- /** diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitDiffCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitDiffCommand.java index 83977ef290..2d56c8e786 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitDiffCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitDiffCommand.java @@ -34,27 +34,25 @@ package sonia.scm.repository.spi; //~--- non-JDK imports -------------------------------------------------------- +import com.google.common.base.Strings; import org.eclipse.jgit.diff.DiffEntry; import org.eclipse.jgit.diff.DiffFormatter; +import org.eclipse.jgit.lib.ObjectId; 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 org.slf4j.Logger; import org.slf4j.LoggerFactory; - import sonia.scm.repository.GitUtil; import sonia.scm.repository.Repository; import sonia.scm.util.Util; -//~--- JDK imports ------------------------------------------------------------ - import java.io.BufferedOutputStream; +import java.io.IOException; import java.io.OutputStream; - import java.util.List; /** @@ -107,7 +105,8 @@ public class GitDiffCommand extends AbstractGitCommand implements DiffCommand 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); commit = walk.next(); @@ -120,7 +119,15 @@ public class GitDiffCommand extends AbstractGitCommand implements DiffCommand 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(); @@ -156,7 +163,6 @@ public class GitDiffCommand extends AbstractGitCommand implements DiffCommand } catch (Exception ex) { - // TODO throw exception logger.error("could not create diff", ex); } @@ -167,4 +173,9 @@ public class GitDiffCommand extends AbstractGitCommand implements DiffCommand GitUtil.release(formatter); } } + + private ObjectId computeCommonAncestor(org.eclipse.jgit.lib.Repository repository, ObjectId revision1, ObjectId revision2) throws IOException { + return GitUtil.computeCommonAncestor(repository, revision1, revision2); + } + } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java index 3b12fb0c3f..d07801ceab 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java @@ -42,4 +42,28 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { gitDiffCommand.getDiffResult(diffCommandRequest, output); assertEquals(DIFF_LATEST_COMMIT_TEST_BRANCH, 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 --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" + + "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", output.toString()); + } } From adce24fcd77c7b409553e3b2716559ea9afcac64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 6 Nov 2018 12:36:36 +0100 Subject: [PATCH 3/5] Enhance unit test --- .../repository/spi/GitDiffCommandTest.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java index d07801ceab..84088ba4ef 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java @@ -43,6 +43,23 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { assertEquals(DIFF_LATEST_COMMIT_TEST_BRANCH, 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 --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", output.toString()); + } + @Test public void diffBetweenTwoBranchesShouldCreateDiff() { GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository); @@ -66,4 +83,22 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { "@@ -0,0 +1 @@\n" + "+f\n", 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 --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", output.toString()); + } } From cccadef5cc7258f59f962bad49d6b33c2ebdba05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 6 Nov 2018 12:40:44 +0100 Subject: [PATCH 4/5] Refactor unit test --- .../repository/spi/GitDiffCommandTest.java | 55 ++++++++----------- 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java index 84088ba4ef..f6e462f968 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java @@ -8,20 +8,34 @@ import static org.junit.Assert.assertEquals; public class GitDiffCommandTest extends AbstractGitCommandTestBase { - private static final String DIFF_LATEST_COMMIT_TEST_BRANCH = "diff --git a/a.txt b/a.txt\n" + + 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" + - "diff --git a/b.txt b/b.txt\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() { @@ -30,7 +44,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { diffCommandRequest.setRevision("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4"); ByteArrayOutputStream output = new ByteArrayOutputStream(); gitDiffCommand.getDiffResult(diffCommandRequest, output); - assertEquals(DIFF_LATEST_COMMIT_TEST_BRANCH, output.toString()); + assertEquals(DIFF_FILE_A + DIFF_FILE_B, output.toString()); } @Test @@ -40,7 +54,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { diffCommandRequest.setRevision("test-branch"); ByteArrayOutputStream output = new ByteArrayOutputStream(); gitDiffCommand.getDiffResult(diffCommandRequest, output); - assertEquals(DIFF_LATEST_COMMIT_TEST_BRANCH, output.toString()); + assertEquals(DIFF_FILE_A + DIFF_FILE_B, output.toString()); } @Test @@ -51,13 +65,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { diffCommandRequest.setPath("a.txt"); ByteArrayOutputStream output = new ByteArrayOutputStream(); gitDiffCommand.getDiffResult(diffCommandRequest, output); - assertEquals("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", output.toString()); + assertEquals(DIFF_FILE_A, output.toString()); } @Test @@ -68,20 +76,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { diffCommandRequest.setAncestorChangeset("test-branch"); ByteArrayOutputStream output = new ByteArrayOutputStream(); gitDiffCommand.getDiffResult(diffCommandRequest, output); - assertEquals("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" + - "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", output.toString()); + assertEquals(DIFF_FILE_A_MULTIPLE_REVISIONS + DIFF_FILE_F_MULTIPLE_REVISIONS, output.toString()); } @Test @@ -93,12 +88,6 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { diffCommandRequest.setPath("a.txt"); ByteArrayOutputStream output = new ByteArrayOutputStream(); gitDiffCommand.getDiffResult(diffCommandRequest, output); - assertEquals("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", output.toString()); + assertEquals(DIFF_FILE_A_MULTIPLE_REVISIONS, output.toString()); } } From 7127cc4cda2443d56ba89d627f8897331c6480af Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Wed, 7 Nov 2018 13:54:23 +0000 Subject: [PATCH 5/5] Close branch feature/diff_two_revisions