Add raw stream result to cat command

This commit is contained in:
René Pfeuffer
2018-08-14 17:22:30 +02:00
parent 2266b971a9
commit c8c1cad67f
5 changed files with 134 additions and 80 deletions

View File

@@ -37,22 +37,21 @@ package sonia.scm.repository.api;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import sonia.scm.repository.Repository; import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryException; import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.spi.CatCommand; import sonia.scm.repository.spi.CatCommand;
import sonia.scm.repository.spi.CatCommandRequest; import sonia.scm.repository.spi.CatCommandRequest;
import sonia.scm.util.IOUtil; import sonia.scm.util.IOUtil;
//~--- JDK imports ------------------------------------------------------------
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
//~--- JDK imports ------------------------------------------------------------
/** /**
* Shows the content of a file in the {@link Repository}.<br /> * Shows the content of a file in the {@link Repository}.<br />
* <br /> * <br />
@@ -110,19 +109,27 @@ public final class CatCommandBuilder
* *
* @param outputStream output stream for the content * @param outputStream output stream for the content
* @param path file path * @param path file path
*
* @return {@code this}
*
* @throws IOException
* @throws RepositoryException
*/ */
public CatCommandBuilder retriveContent(OutputStream outputStream, public void retriveContent(OutputStream outputStream, String path) throws IOException, RepositoryException {
String path)
throws IOException, RepositoryException
{
getCatResult(outputStream, path); 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 ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------

View File

@@ -37,11 +37,12 @@ package sonia.scm.repository.spi;
import sonia.scm.repository.RepositoryException; import sonia.scm.repository.RepositoryException;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
//~--- JDK imports ------------------------------------------------------------
/** /**
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
@@ -50,16 +51,7 @@ import java.io.OutputStream;
public interface CatCommand public interface CatCommand
{ {
/** void getCatResult(CatCommandRequest request, OutputStream output) throws IOException, RepositoryException;
* Method description
* InputStream getCatResultStream(CatCommandRequest request) throws IOException, RepositoryException;
*
* @param request
* @param output
*
* @throws IOException
* @throws RepositoryException
*/
public void getCatResult(CatCommandRequest request, OutputStream output)
throws IOException, RepositoryException;
} }

View File

@@ -34,29 +34,29 @@ package sonia.scm.repository.spi;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Strings;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Repository;
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.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.PathNotFoundException; import sonia.scm.repository.PathNotFoundException;
import sonia.scm.repository.RepositoryException; import sonia.scm.repository.RepositoryException;
import sonia.scm.util.Util; import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------ import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
//~--- JDK imports ------------------------------------------------------------
/** /**
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
@@ -110,23 +110,32 @@ public class GitCatCommand extends AbstractGitCommand implements CatCommand
getContent(repo, revId, request.getPath(), output); getContent(repo, revId, request.getPath(), output);
} }
/** @Override
* Method description public InputStream getCatResultStream(CatCommandRequest request) throws IOException, RepositoryException {
* logger.debug("try to read content for {}", request);
*
* org.eclipse.jgit.lib.Repository repo = open();
* @param repo
* @param revId ObjectId revId = getCommitOrDefault(repo, request.getRevision());
* @param path ClosableObjectLoaderContainer closableObjectLoaderContainer = getLoader(repo, revId, request.getPath());
* @param output return new InputStreamWrapper(closableObjectLoaderContainer);
* }
*
* @throws IOException
* @throws RepositoryException
*/
void getContent(org.eclipse.jgit.lib.Repository repo, ObjectId revId, void getContent(org.eclipse.jgit.lib.Repository repo, ObjectId revId,
String path, OutputStream output) String path, OutputStream output)
throws IOException, RepositoryException 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; TreeWalk treeWalk = null;
RevWalk revWalk = null; RevWalk revWalk = null;
@@ -157,23 +166,12 @@ public class GitCatCommand extends AbstractGitCommand implements CatCommand
treeWalk.setFilter(PathFilter.create(path)); treeWalk.setFilter(PathFilter.create(path));
if (treeWalk.next()) if (treeWalk.next() && treeWalk.getFileMode(0).getObjectType() == Constants.OBJ_BLOB)
{
// Path exists
if (treeWalk.getFileMode(0).getObjectType() == Constants.OBJ_BLOB)
{ {
ObjectId blobId = treeWalk.getObjectId(0); ObjectId blobId = treeWalk.getObjectId(0);
ObjectLoader loader = repo.open(blobId); ObjectLoader loader = repo.open(blobId);
loader.copyTo(output); return new ClosableObjectLoaderContainer(loader, treeWalk, revWalk);
}
else
{
// Not a blob, its something else (tree, gitlink)
throw new PathNotFoundException(path);
}
} }
else else
{ {
@@ -182,6 +180,50 @@ public class GitCatCommand extends AbstractGitCommand implements CatCommand
} }
finally 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(revWalk);
GitUtil.release(treeWalk); GitUtil.release(treeWalk);
} }

View File

@@ -37,17 +37,16 @@ package sonia.scm.repository.spi;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.google.common.io.Closeables; import com.google.common.io.Closeables;
import sonia.scm.repository.Repository; import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryException; import sonia.scm.repository.RepositoryException;
import sonia.scm.web.HgUtil; import sonia.scm.web.HgUtil;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
//~--- JDK imports ------------------------------------------------------------
/** /**
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
@@ -83,16 +82,9 @@ public class HgCatCommand extends AbstractCommand implements CatCommand
public void getCatResult(CatCommandRequest request, OutputStream output) public void getCatResult(CatCommandRequest request, OutputStream output)
throws IOException, RepositoryException throws IOException, RepositoryException
{ {
com.aragost.javahg.commands.CatCommand cmd = InputStream input = getCatResultStream(request);
com.aragost.javahg.commands.CatCommand.on(open());
cmd.rev(HgUtil.getRevision(request.getRevision()));
InputStream input = null;
try try
{ {
input = cmd.execute(request.getPath());
ByteStreams.copy(input, output); ByteStreams.copy(input, output);
} }
finally finally
@@ -100,4 +92,14 @@ public class HgCatCommand extends AbstractCommand implements CatCommand
Closeables.close(input, true); 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());
}
} }

View File

@@ -37,22 +37,23 @@ package sonia.scm.repository.spi;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNProperties; import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc.SVNClientManager; import org.tmatesoft.svn.core.wc.SVNClientManager;
import org.tmatesoft.svn.core.wc.admin.SVNLookClient; import org.tmatesoft.svn.core.wc.admin.SVNLookClient;
import sonia.scm.repository.Repository; import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryException; import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.SvnUtil; import sonia.scm.repository.SvnUtil;
//~--- JDK imports ------------------------------------------------------------ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
//~--- JDK imports ------------------------------------------------------------
/** /**
* *
* @author Sebastian Sdorra * @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 * Method description
* *