diff --git a/scm-core/src/main/java/sonia/scm/repository/api/DiffCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/DiffCommandBuilder.java index 18d4e11a7f..03f4361083 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/DiffCommandBuilder.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/DiffCommandBuilder.java @@ -40,7 +40,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.repository.Feature; import sonia.scm.repository.spi.DiffCommand; -import sonia.scm.util.IOUtil; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -103,16 +102,12 @@ public final class DiffCommandBuilder extends AbstractDiffCommandBuilder { + try (DiffFormatter formatter = new DiffFormatter(output)) { + formatter.setRepository(repository); + + for (DiffEntry e : diff.getEntries()) { + if (!e.getOldId().equals(e.getNewId())) { + formatter.format(e); + } } - } - formatter.flush(); - } + formatter.flush(); + } + }; } } 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 fd9c45be5c..52932e83ae 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 @@ -44,7 +44,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { DiffCommandRequest diffCommandRequest = new DiffCommandRequest(); diffCommandRequest.setRevision("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4"); ByteArrayOutputStream output = new ByteArrayOutputStream(); - gitDiffCommand.getDiffResult(diffCommandRequest, output); + gitDiffCommand.getDiffResult(diffCommandRequest).accept(output); assertEquals(DIFF_FILE_A + DIFF_FILE_B, output.toString()); } @@ -54,7 +54,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { DiffCommandRequest diffCommandRequest = new DiffCommandRequest(); diffCommandRequest.setRevision("test-branch"); ByteArrayOutputStream output = new ByteArrayOutputStream(); - gitDiffCommand.getDiffResult(diffCommandRequest, output); + gitDiffCommand.getDiffResult(diffCommandRequest).accept(output); assertEquals(DIFF_FILE_A + DIFF_FILE_B, output.toString()); } @@ -65,7 +65,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { diffCommandRequest.setRevision("test-branch"); diffCommandRequest.setPath("a.txt"); ByteArrayOutputStream output = new ByteArrayOutputStream(); - gitDiffCommand.getDiffResult(diffCommandRequest, output); + gitDiffCommand.getDiffResult(diffCommandRequest).accept(output); assertEquals(DIFF_FILE_A, output.toString()); } @@ -76,7 +76,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { diffCommandRequest.setRevision("master"); diffCommandRequest.setAncestorChangeset("test-branch"); ByteArrayOutputStream output = new ByteArrayOutputStream(); - gitDiffCommand.getDiffResult(diffCommandRequest, output); + gitDiffCommand.getDiffResult(diffCommandRequest).accept(output); assertEquals(DIFF_FILE_A_MULTIPLE_REVISIONS + DIFF_FILE_F_MULTIPLE_REVISIONS, output.toString()); } @@ -88,7 +88,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { diffCommandRequest.setAncestorChangeset("test-branch"); diffCommandRequest.setPath("a.txt"); ByteArrayOutputStream output = new ByteArrayOutputStream(); - gitDiffCommand.getDiffResult(diffCommandRequest, output); + gitDiffCommand.getDiffResult(diffCommandRequest).accept(output); assertEquals(DIFF_FILE_A_MULTIPLE_REVISIONS, output.toString()); } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgDiffCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgDiffCommand.java index d705f0ac14..9e43e26014 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgDiffCommand.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgDiffCommand.java @@ -39,13 +39,12 @@ import com.google.common.base.Strings; import com.google.common.io.ByteStreams; import com.google.common.io.Closeables; import sonia.scm.repository.Repository; +import sonia.scm.repository.api.DiffCommandBuilder; import sonia.scm.repository.api.DiffFormat; import sonia.scm.repository.spi.javahg.HgDiffInternalCommand; import sonia.scm.web.HgUtil; -import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; //~--- JDK imports ------------------------------------------------------------ @@ -71,41 +70,36 @@ public class HgDiffCommand extends AbstractCommand implements DiffCommand //~--- get methods ---------------------------------------------------------- @Override - public void getDiffResult(DiffCommandRequest request, OutputStream output) - throws IOException + public DiffCommandBuilder.OutputStreamConsumer getDiffResult(DiffCommandRequest request) { - com.aragost.javahg.Repository hgRepo = open(); + return output -> { + com.aragost.javahg.Repository hgRepo = open(); - HgDiffInternalCommand cmd = HgDiffInternalCommand.on(hgRepo); - DiffFormat format = request.getFormat(); + HgDiffInternalCommand cmd = HgDiffInternalCommand.on(hgRepo); + DiffFormat format = request.getFormat(); - if (format == DiffFormat.GIT) - { - cmd.git(); - } - - cmd.change(HgUtil.getRevision(request.getRevision())); - - InputStream inputStream = null; - - try - { - - if (!Strings.isNullOrEmpty(request.getPath())) + if (format == DiffFormat.GIT) { - inputStream = cmd.stream(hgRepo.file(request.getPath())); - } - else - { - inputStream = cmd.stream(); + cmd.git(); } - ByteStreams.copy(inputStream, output); + cmd.change(HgUtil.getRevision(request.getRevision())); - } - finally - { - Closeables.close(inputStream, true); - } + InputStream inputStream = null; + + try { + + if (!Strings.isNullOrEmpty(request.getPath())) { + inputStream = cmd.stream(hgRepo.file(request.getPath())); + } else { + inputStream = cmd.stream(); + } + + ByteStreams.copy(inputStream, output); + + } finally { + Closeables.close(inputStream, true); + } + }; } } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnDiffCommand.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnDiffCommand.java index 4aaa12e28f..3bbde02844 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnDiffCommand.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnDiffCommand.java @@ -46,11 +46,10 @@ import org.tmatesoft.svn.core.wc.SVNRevision; import sonia.scm.repository.InternalRepositoryException; import sonia.scm.repository.Repository; import sonia.scm.repository.SvnUtil; +import sonia.scm.repository.api.DiffCommandBuilder; import sonia.scm.repository.api.DiffFormat; import sonia.scm.util.Util; -import java.io.OutputStream; - //~--- JDK imports ------------------------------------------------------------ /** @@ -70,33 +69,34 @@ public class SvnDiffCommand extends AbstractSvnCommand implements DiffCommand { } @Override - public void getDiffResult(DiffCommandRequest request, OutputStream output) { + public DiffCommandBuilder.OutputStreamConsumer getDiffResult(DiffCommandRequest request) { logger.debug("create diff for {}", request); Preconditions.checkNotNull(request, "request is required"); - Preconditions.checkNotNull(output, "outputstream is required"); String path = request.getPath(); - SVNClientManager clientManager = null; - try { - SVNURL svnurl = context.createUrl(); - if (Util.isNotEmpty(path)) { - svnurl = svnurl.appendPath(path, true); + return output -> { + SVNClientManager clientManager = null; + try { + SVNURL svnurl = context.createUrl(); + if (Util.isNotEmpty(path)) { + svnurl = svnurl.appendPath(path, true); + } + clientManager = SVNClientManager.newInstance(); + SVNDiffClient diffClient = clientManager.getDiffClient(); + diffClient.setDiffGenerator(new SvnNewDiffGenerator(new SCMSvnDiffGenerator())); + + long currentRev = SvnUtil.getRevisionNumber(request.getRevision(), repository); + + diffClient.setGitDiffFormat(request.getFormat() == DiffFormat.GIT); + + diffClient.doDiff(svnurl, SVNRevision.HEAD, + SVNRevision.create(currentRev - 1), SVNRevision.create(currentRev), + SVNDepth.INFINITY, false, output); + } catch (SVNException ex) { + throw new InternalRepositoryException(repository, "could not create diff", ex); + } finally { + SvnUtil.dispose(clientManager); } - clientManager = SVNClientManager.newInstance(); - SVNDiffClient diffClient = clientManager.getDiffClient(); - diffClient.setDiffGenerator(new SvnNewDiffGenerator(new SCMSvnDiffGenerator())); - - long currentRev = SvnUtil.getRevisionNumber(request.getRevision(), repository); - - diffClient.setGitDiffFormat(request.getFormat() == DiffFormat.GIT); - - diffClient.doDiff(svnurl, SVNRevision.HEAD, - SVNRevision.create(currentRev - 1), SVNRevision.create(currentRev), - SVNDepth.INFINITY, false, output); - } catch (SVNException ex) { - throw new InternalRepositoryException(repository, "could not create diff", ex); - } finally { - SvnUtil.dispose(clientManager); - } + }; } } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/DiffRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/DiffRootResource.java index 4d15b773cd..016c316500 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/DiffRootResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/DiffRootResource.java @@ -4,6 +4,7 @@ import com.webcohesion.enunciate.metadata.rs.ResponseCode; import com.webcohesion.enunciate.metadata.rs.StatusCodes; import sonia.scm.NotFoundException; import sonia.scm.repository.NamespaceAndName; +import sonia.scm.repository.api.DiffCommandBuilder; import sonia.scm.repository.api.DiffFormat; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; @@ -20,6 +21,7 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; import javax.ws.rs.core.StreamingOutput; +import java.io.IOException; public class DiffRootResource { @@ -55,20 +57,17 @@ public class DiffRootResource { @ResponseCode(code = 404, condition = "not found, no revision with the specified param for the repository available or repository not found"), @ResponseCode(code = 500, condition = "internal server error") }) - public Response get(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("revision") String revision , @Pattern(regexp = DIFF_FORMAT_VALUES_REGEX) @DefaultValue("NATIVE") @QueryParam("format") String format ){ + public Response get(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("revision") String revision , @Pattern(regexp = DIFF_FORMAT_VALUES_REGEX) @DefaultValue("NATIVE") @QueryParam("format") String format ) throws IOException { HttpUtil.checkForCRLFInjection(revision); DiffFormat diffFormat = DiffFormat.valueOf(format); try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) { - StreamingOutput responseEntry = output -> { - repositoryService.getDiffCommand() - .setRevision(revision) - .setFormat(diffFormat) - .retrieveContent(output); - }; - return Response.ok(responseEntry) + DiffCommandBuilder.OutputStreamConsumer outputStreamConsumer = repositoryService.getDiffCommand() + .setRevision(revision) + .setFormat(diffFormat) + .retrieveContent(); + return Response.ok((StreamingOutput) outputStreamConsumer::accept) .header(HEADER_CONTENT_DISPOSITION, HttpUtil.createContentDispositionAttachmentHeader(String.format("%s-%s.diff", name, revision))) .build(); } } - } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/IncomingRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/IncomingRootResource.java index 4c43485abd..cb27d9b5dc 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/IncomingRootResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/IncomingRootResource.java @@ -10,6 +10,7 @@ import sonia.scm.repository.ChangesetPagingResult; import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryPermissions; +import sonia.scm.repository.api.DiffCommandBuilder; import sonia.scm.repository.api.DiffFormat; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; @@ -138,14 +139,13 @@ public class IncomingRootResource { HttpUtil.checkForCRLFInjection(target); DiffFormat diffFormat = DiffFormat.valueOf(format); try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) { - StreamingOutput responseEntry = output -> - repositoryService.getDiffCommand() - .setRevision(source) - .setAncestorChangeset(target) - .setFormat(diffFormat) - .retrieveContent(output); + DiffCommandBuilder.OutputStreamConsumer outputStreamConsumer = repositoryService.getDiffCommand() + .setRevision(source) + .setAncestorChangeset(target) + .setFormat(diffFormat) + .retrieveContent(); - return Response.ok(responseEntry) + return Response.ok((StreamingOutput) outputStreamConsumer::accept) .header(HEADER_CONTENT_DISPOSITION, HttpUtil.createContentDispositionAttachmentHeader(String.format("%s-%s.diff", name, source))) .build(); } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/DiffResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/DiffResourceTest.java index 01d5e22b53..33d4d7e9e1 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/DiffResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/DiffResourceTest.java @@ -91,7 +91,7 @@ public class DiffResourceTest extends RepositoryTestBase { public void shouldGetDiffs() throws Exception { when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder); - when(diffCommandBuilder.retrieveContent(any())).thenReturn(diffCommandBuilder); + when(diffCommandBuilder.retrieveContent()).thenReturn(output -> {}); MockHttpRequest request = MockHttpRequest .get(DIFF_URL + "revision") .accept(VndMediaType.DIFF); @@ -123,7 +123,7 @@ public class DiffResourceTest extends RepositoryTestBase { public void shouldGet404OnMissingRevision() throws Exception { when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder); - when(diffCommandBuilder.retrieveContent(any())).thenThrow(new NotFoundException("Text", "x")); + when(diffCommandBuilder.retrieveContent()).thenThrow(new NotFoundException("Text", "x")); MockHttpRequest request = MockHttpRequest .get(DIFF_URL + "revision") @@ -139,7 +139,7 @@ public class DiffResourceTest extends RepositoryTestBase { public void shouldGet400OnCrlfInjection() throws Exception { when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder); - when(diffCommandBuilder.retrieveContent(any())).thenThrow(new NotFoundException("Text", "x")); + when(diffCommandBuilder.retrieveContent()).thenThrow(new NotFoundException("Text", "x")); MockHttpRequest request = MockHttpRequest .get(DIFF_URL + "ny%0D%0ASet-cookie:%20Tamper=3079675143472450634") @@ -153,7 +153,7 @@ public class DiffResourceTest extends RepositoryTestBase { public void shouldGet400OnUnknownFormat() throws Exception { when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder); - when(diffCommandBuilder.retrieveContent(any())).thenThrow(new NotFoundException("Test", "test")); + when(diffCommandBuilder.retrieveContent()).thenThrow(new NotFoundException("Test", "test")); MockHttpRequest request = MockHttpRequest .get(DIFF_URL + "revision?format=Unknown") @@ -167,7 +167,7 @@ public class DiffResourceTest extends RepositoryTestBase { public void shouldAcceptDiffFormats() throws Exception { when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder); - when(diffCommandBuilder.retrieveContent(any())).thenReturn(diffCommandBuilder); + when(diffCommandBuilder.retrieveContent()).thenReturn(output -> {}); Arrays.stream(DiffFormat.values()).map(DiffFormat::name).forEach( this::assertRequestOk diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/IncomingRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/IncomingRootResourceTest.java index b965c2f2c3..0c1f4235b9 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/IncomingRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/IncomingRootResourceTest.java @@ -171,7 +171,7 @@ public class IncomingRootResourceTest extends RepositoryTestBase { when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setAncestorChangeset(anyString())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder); - when(diffCommandBuilder.retrieveContent(any())).thenReturn(diffCommandBuilder); + when(diffCommandBuilder.retrieveContent()).thenReturn(output -> {}); MockHttpRequest request = MockHttpRequest .get(INCOMING_DIFF_URL + "src_changeset_id/target_changeset_id/diff") .accept(VndMediaType.DIFF); @@ -206,7 +206,7 @@ public class IncomingRootResourceTest extends RepositoryTestBase { when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setAncestorChangeset(anyString())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder); - when(diffCommandBuilder.retrieveContent(any())).thenThrow(new NotFoundException("Text", "x")); + when(diffCommandBuilder.retrieveContent()).thenThrow(new NotFoundException("Text", "x")); MockHttpRequest request = MockHttpRequest .get(INCOMING_DIFF_URL + "src_changeset_id/target_changeset_id/diff") @@ -223,7 +223,7 @@ public class IncomingRootResourceTest extends RepositoryTestBase { when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setAncestorChangeset(anyString())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder); - when(diffCommandBuilder.retrieveContent(any())).thenThrow(new NotFoundException("Text", "x")); + when(diffCommandBuilder.retrieveContent()).thenThrow(new NotFoundException("Text", "x")); MockHttpRequest request = MockHttpRequest .get(INCOMING_DIFF_URL + "ny%0D%0ASet-cookie:%20Tamper=3079675143472450634/ny%0D%0ASet-cookie:%20Tamper=3079675143472450634/diff") .accept(VndMediaType.DIFF); @@ -240,7 +240,7 @@ public class IncomingRootResourceTest extends RepositoryTestBase { when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setAncestorChangeset(anyString())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder); - when(diffCommandBuilder.retrieveContent(any())).thenThrow(new NotFoundException("Test", "test")); + when(diffCommandBuilder.retrieveContent()).thenThrow(new NotFoundException("Test", "test")); MockHttpRequest request = MockHttpRequest .get(INCOMING_DIFF_URL + "src_changeset_id/target_changeset_id/diff?format=Unknown") .accept(VndMediaType.DIFF);