From c8c1cad67fd5ba9e5fc333851a1a61373e61937a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 14 Aug 2018 17:22:30 +0200 Subject: [PATCH] Add raw stream result to cat command --- .../scm/repository/api/CatCommandBuilder.java | 39 +++--- .../sonia/scm/repository/spi/CatCommand.java | 20 +--- .../scm/repository/spi/GitCatCommand.java | 112 ++++++++++++------ .../scm/repository/spi/HgCatCommand.java | 24 ++-- .../scm/repository/spi/SvnCatCommand.java | 19 ++- 5 files changed, 134 insertions(+), 80 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/api/CatCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/CatCommandBuilder.java index f7b4d75fbd..8a08663f25 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/CatCommandBuilder.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/CatCommandBuilder.java @@ -37,22 +37,21 @@ package sonia.scm.repository.api; import com.google.common.base.Preconditions; import com.google.common.base.Strings; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryException; import sonia.scm.repository.spi.CatCommand; import sonia.scm.repository.spi.CatCommandRequest; import sonia.scm.util.IOUtil; -//~--- JDK imports ------------------------------------------------------------ - import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; +//~--- JDK imports ------------------------------------------------------------ + /** * Shows the content of a file in the {@link Repository}.
*
@@ -106,23 +105,31 @@ public final class CatCommandBuilder } /** - * Passes the content of the given file to the outputstream. + * Passes the content of the given file to the output stream. * - * @param outputStream outputstream for the content + * @param outputStream output stream for the content * @param path file path - * - * @return {@code this} - * - * @throws IOException - * @throws RepositoryException */ - public CatCommandBuilder retriveContent(OutputStream outputStream, - String path) - throws IOException, RepositoryException - { + public void retriveContent(OutputStream outputStream, String path) throws IOException, RepositoryException { getCatResult(outputStream, path); + } - return this; + /** + * Returns an output stream with the file content. + * + * @param path file path + */ + public InputStream getStream(String path) throws IOException, RepositoryException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(path), + "path is required"); + + CatCommandRequest requestClone = request.clone(); + + requestClone.setPath(path); + + logger.debug("create cat stream for {}", requestClone); + + return catCommand.getCatResultStream(requestClone); } //~--- get methods ---------------------------------------------------------- diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/CatCommand.java b/scm-core/src/main/java/sonia/scm/repository/spi/CatCommand.java index b9a6f52ab0..cbf1866298 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/CatCommand.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/CatCommand.java @@ -37,11 +37,12 @@ package sonia.scm.repository.spi; import sonia.scm.repository.RepositoryException; -//~--- JDK imports ------------------------------------------------------------ - import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra @@ -50,16 +51,7 @@ import java.io.OutputStream; public interface CatCommand { - /** - * Method description - * - * - * @param request - * @param output - * - * @throws IOException - * @throws RepositoryException - */ - public void getCatResult(CatCommandRequest request, OutputStream output) - throws IOException, RepositoryException; + void getCatResult(CatCommandRequest request, OutputStream output) throws IOException, RepositoryException; + + InputStream getCatResultStream(CatCommandRequest request) throws IOException, RepositoryException; } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitCatCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitCatCommand.java index 4420b9a22a..fdf8042c57 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitCatCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitCatCommand.java @@ -34,29 +34,29 @@ package sonia.scm.repository.spi; //~--- non-JDK imports -------------------------------------------------------- -import com.google.common.base.Strings; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectLoader; +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.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.PathNotFoundException; import sonia.scm.repository.RepositoryException; import sonia.scm.util.Util; -//~--- JDK imports ------------------------------------------------------------ - +import java.io.Closeable; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra @@ -110,22 +110,31 @@ public class GitCatCommand extends AbstractGitCommand implements CatCommand getContent(repo, revId, request.getPath(), output); } - /** - * Method description - * - * - * - * @param repo - * @param revId - * @param path - * @param output - * - * - * @throws IOException - * @throws RepositoryException - */ + @Override + public InputStream getCatResultStream(CatCommandRequest request) throws IOException, RepositoryException { + logger.debug("try to read content for {}", request); + + org.eclipse.jgit.lib.Repository repo = open(); + + ObjectId revId = getCommitOrDefault(repo, request.getRevision()); + ClosableObjectLoaderContainer closableObjectLoaderContainer = getLoader(repo, revId, request.getPath()); + return new InputStreamWrapper(closableObjectLoaderContainer); + } + void getContent(org.eclipse.jgit.lib.Repository repo, ObjectId revId, - String path, OutputStream output) + String path, OutputStream output) + throws IOException, RepositoryException + { + ClosableObjectLoaderContainer closableObjectLoaderContainer = getLoader(repo, revId, path); + try { + closableObjectLoaderContainer.objectLoader.copyTo(output); + } finally { + closableObjectLoaderContainer.close(); + } + } + + private ClosableObjectLoaderContainer getLoader(Repository repo, ObjectId revId, + String path) throws IOException, RepositoryException { TreeWalk treeWalk = null; @@ -157,23 +166,12 @@ public class GitCatCommand extends AbstractGitCommand implements CatCommand treeWalk.setFilter(PathFilter.create(path)); - if (treeWalk.next()) + if (treeWalk.next() && treeWalk.getFileMode(0).getObjectType() == Constants.OBJ_BLOB) { + ObjectId blobId = treeWalk.getObjectId(0); + ObjectLoader loader = repo.open(blobId); - // Path exists - if (treeWalk.getFileMode(0).getObjectType() == Constants.OBJ_BLOB) - { - ObjectId blobId = treeWalk.getObjectId(0); - ObjectLoader loader = repo.open(blobId); - - loader.copyTo(output); - } - else - { - - // Not a blob, its something else (tree, gitlink) - throw new PathNotFoundException(path); - } + return new ClosableObjectLoaderContainer(loader, treeWalk, revWalk); } else { @@ -182,8 +180,52 @@ public class GitCatCommand extends AbstractGitCommand implements CatCommand } finally { + } + } + + private static class ClosableObjectLoaderContainer implements Closeable { + private final ObjectLoader objectLoader; + private final TreeWalk treeWalk; + private final RevWalk revWalk; + + private ClosableObjectLoaderContainer(ObjectLoader objectLoader, TreeWalk treeWalk, RevWalk revWalk) { + this.objectLoader = objectLoader; + this.treeWalk = treeWalk; + this.revWalk = revWalk; + } + + @Override + public void close() throws IOException { GitUtil.release(revWalk); GitUtil.release(treeWalk); } } + + private static class InputStreamWrapper extends InputStream { + + private final InputStream delegate; + private final TreeWalk treeWalk; + private final RevWalk revWalk; + + private InputStreamWrapper(ClosableObjectLoaderContainer container) throws IOException { + this(container.objectLoader.openStream(), container.treeWalk, container.revWalk); + } + + private InputStreamWrapper(InputStream delegate, TreeWalk treeWalk, RevWalk revWalk) { + this.delegate = delegate; + this.treeWalk = treeWalk; + this.revWalk = revWalk; + } + + @Override + public int read () throws IOException { + return delegate.read(); + } + + @Override + public void close () throws IOException { + GitUtil.release(revWalk); + GitUtil.release(treeWalk); + } + } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgCatCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgCatCommand.java index 76438c1f1e..a8e585915e 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgCatCommand.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgCatCommand.java @@ -37,17 +37,16 @@ package sonia.scm.repository.spi; import com.google.common.io.ByteStreams; import com.google.common.io.Closeables; - import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryException; import sonia.scm.web.HgUtil; -//~--- JDK imports ------------------------------------------------------------ - import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra @@ -83,16 +82,9 @@ public class HgCatCommand extends AbstractCommand implements CatCommand public void getCatResult(CatCommandRequest request, OutputStream output) throws IOException, RepositoryException { - com.aragost.javahg.commands.CatCommand cmd = - com.aragost.javahg.commands.CatCommand.on(open()); - - cmd.rev(HgUtil.getRevision(request.getRevision())); - - InputStream input = null; - + InputStream input = getCatResultStream(request); try { - input = cmd.execute(request.getPath()); ByteStreams.copy(input, output); } finally @@ -100,4 +92,14 @@ public class HgCatCommand extends AbstractCommand implements CatCommand Closeables.close(input, true); } } + + @Override + public InputStream getCatResultStream(CatCommandRequest request) throws IOException, RepositoryException { + com.aragost.javahg.commands.CatCommand cmd = + com.aragost.javahg.commands.CatCommand.on(open()); + + cmd.rev(HgUtil.getRevision(request.getRevision())); + + return cmd.execute(request.getPath()); + } } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnCatCommand.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnCatCommand.java index af08ea929e..5bd3c54b1b 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnCatCommand.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnCatCommand.java @@ -37,22 +37,23 @@ package sonia.scm.repository.spi; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNProperties; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.wc.SVNClientManager; import org.tmatesoft.svn.core.wc.admin.SVNLookClient; - import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryException; import sonia.scm.repository.SvnUtil; -//~--- JDK imports ------------------------------------------------------------ - +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra @@ -120,6 +121,16 @@ public class SvnCatCommand extends AbstractSvnCommand implements CatCommand } } + @Override + public InputStream getCatResultStream(CatCommandRequest request) throws IOException, RepositoryException { + // There seems to be no method creating an input stream as a result, so + // we have no other possibility then to copy the content into a buffer and + // stream it from there. + ByteArrayOutputStream output = new ByteArrayOutputStream(); + getCatResult(request, output); + return new ByteArrayInputStream(output.toByteArray()); + } + /** * Method description *