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 0b7592b446..3e62a8eebe 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 @@ -115,7 +115,7 @@ public final class DiffCommandRequest extends FileBaseCommandRequest this.ancestorChangeset = ancestorChangeset; } - public void setMergeChangeset(String mergeChangeset) { + public void setConflictBranch(String mergeChangeset) { this.mergeChangeset = mergeChangeset; } 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 86c2c9baab..0159beec9a 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 @@ -37,12 +37,15 @@ import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.diff.DiffEntry; import org.eclipse.jgit.diff.DiffFormatter; import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectReader; +import org.eclipse.jgit.treewalk.CanonicalTreeParser; import sonia.scm.repository.GitWorkdirFactory; import sonia.scm.repository.InternalRepositoryException; import sonia.scm.repository.Repository; import sonia.scm.repository.api.DiffCommandBuilder; import java.io.IOException; +import java.util.List; /** * @@ -61,7 +64,9 @@ public class GitDiffCommand extends AbstractGitCommand implements DiffCommand { public DiffCommandBuilder.OutputStreamConsumer getDiffResult(DiffCommandRequest request) throws IOException { WorkingCopyCloser closer = new WorkingCopyCloser(); if (Strings.isNullOrEmpty(request.getMergeChangeset())) { - return computeDiff(request, open(), closer); + Differ.Diff diff = Differ.diff(open(), request); + List entries = diff.getEntries(); + return computeDiff(entries, open(), closer); } else { return inCloneWithPostponedClose(git -> new GitCloneWorker(git) { @Override @@ -77,22 +82,34 @@ public class GitDiffCommand extends AbstractGitCommand implements DiffCommand { throw new InternalRepositoryException(context.getRepository(), "could not merge branch " + request.getRevision() + " into " + request.getMergeChangeset(), e); } - DiffCommandRequest clone = request.clone(); - clone.setRevision(sourceRevision.name()); - return computeDiff(request, getClone().getRepository(), closer); + CanonicalTreeParser treeParser = new CanonicalTreeParser(); + ObjectId treeId = git.getRepository().resolve(request.getMergeChangeset() + "^{tree}"); + return outputStream -> { + try (ObjectReader reader = git.getRepository().newObjectReader()) { + treeParser.reset(reader, treeId); + git + .diff() + .setOldTree(treeParser) + .setOutputStream(outputStream) + .call(); + DiffCommandRequest clone = request.clone(); + clone.setRevision(sourceRevision.name()); + } catch (GitAPIException e) { + throw new InternalRepositoryException(repository, "could not calculate diff", e); + } + }; } }, workdirFactory, request.getMergeChangeset(), closer); } } - private DiffCommandBuilder.OutputStreamConsumer computeDiff(DiffCommandRequest request, org.eclipse.jgit.lib.Repository repository, WorkingCopyCloser closer) throws IOException { - Differ.Diff diff = Differ.diff(repository, request); + private DiffCommandBuilder.OutputStreamConsumer computeDiff(List entries, org.eclipse.jgit.lib.Repository repository, WorkingCopyCloser closer) throws IOException { return output -> { try (DiffFormatter formatter = new DiffFormatter(output)) { formatter.setRepository(repository); - for (DiffEntry e : diff.getEntries()) { + for (DiffEntry e : entries) { if (!e.getOldId().equals(e.getNewId())) { formatter.format(e); } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommand_Merge_Test.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommand_Merge_Test.java index 300fbee4dc..81b07816ba 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommand_Merge_Test.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommand_Merge_Test.java @@ -12,7 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class GitDiffCommand_Merge_Test extends AbstractGitCommandTestBase { static final String DIFF_HEADER = "diff --git a/Main.java b/Main.java"; - static final String DIFF_FILE_A_MULTIPLE_REVISIONS = "--- a/Main.java\n" + + static final String DIFF_FILE_NO_CONFLICT = "--- a/Main.java\n" + "+++ b/Main.java\n" + "@@ -1,5 +1,5 @@\n" + " class Main {\n" + @@ -21,6 +21,22 @@ public class GitDiffCommand_Merge_Test extends AbstractGitCommandTestBase { " System.out.println(\"Expect nothing more to happen.\");\n" + " System.out.println(\"This is for demonstration, only.\");\n" + " }\n"; + static final String DIFF_FILE_CONFLICT = "--- a/Main.java\n" + + "+++ b/Main.java\n" + + "@@ -1,6 +1,13 @@\n" + + "+import java.util.Arrays;\n" + + "+\n" + + " class Main {\n" + + " public static void main(String[] args) {\n" + + " System.out.println(\"Expect nothing more to happen.\");\n" + + "+<<<<<<< HEAD\n" + + " System.out.println(\"This is for demonstration, only.\");\n" + + "+=======\n" + + "+ System.out.println(\"Parameters:\");\n" + + "+ Arrays.stream(args).map(arg -> \"- \" + arg).forEach(System.out::println);\n" + + "+>>>>>>> feature/print_args\n" + + " }\n" + + " }\n"; @Rule public BindTransportProtocolRule transportProtocolRule = new BindTransportProtocolRule(); @@ -30,12 +46,12 @@ public class GitDiffCommand_Merge_Test extends AbstractGitCommandTestBase { GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository, new SimpleGitWorkdirFactory(new WorkdirProvider())); DiffCommandRequest diffCommandRequest = new DiffCommandRequest(); diffCommandRequest.setRevision("feature/rename_variable"); - diffCommandRequest.setMergeChangeset("integration"); + diffCommandRequest.setConflictBranch("integration"); ByteArrayOutputStream output = new ByteArrayOutputStream(); gitDiffCommand.getDiffResult(diffCommandRequest).accept(output); assertThat(output.toString()) .contains(DIFF_HEADER) - .contains(DIFF_FILE_A_MULTIPLE_REVISIONS); + .contains(DIFF_FILE_NO_CONFLICT); } @Test @@ -43,12 +59,12 @@ public class GitDiffCommand_Merge_Test extends AbstractGitCommandTestBase { GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository, new SimpleGitWorkdirFactory(new WorkdirProvider())); DiffCommandRequest diffCommandRequest = new DiffCommandRequest(); diffCommandRequest.setRevision("feature/print_args"); - diffCommandRequest.setMergeChangeset("integration"); + diffCommandRequest.setConflictBranch("integration"); ByteArrayOutputStream output = new ByteArrayOutputStream(); gitDiffCommand.getDiffResult(diffCommandRequest).accept(output); assertThat(output.toString()) .contains(DIFF_HEADER) - .contains(DIFF_FILE_A_MULTIPLE_REVISIONS); + .contains(DIFF_FILE_CONFLICT); } @Override