Clean up git cat command

This commit is contained in:
René Pfeuffer
2018-08-15 09:24:21 +02:00
parent 3038d6460c
commit 267ef50e51
2 changed files with 80 additions and 171 deletions

View File

@@ -32,8 +32,6 @@
package sonia.scm.repository.spi; package sonia.scm.repository.spi;
//~--- non-JDK imports --------------------------------------------------------
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;
@@ -51,135 +49,72 @@ import sonia.scm.repository.RepositoryException;
import sonia.scm.util.Util; import sonia.scm.util.Util;
import java.io.Closeable; import java.io.Closeable;
import java.io.FilterInputStream;
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 ------------------------------------------------------------
/** public class GitCatCommand extends AbstractGitCommand implements CatCommand {
*
* @author Sebastian Sdorra
*/
public class GitCatCommand extends AbstractGitCommand implements CatCommand
{
/** private static final Logger logger = LoggerFactory.getLogger(GitCatCommand.class);
* the logger for GitCatCommand
*/
private static final Logger logger =
LoggerFactory.getLogger(GitCatCommand.class);
//~--- constructors --------------------------------------------------------- public GitCatCommand(GitContext context, sonia.scm.repository.Repository repository) {
/**
* Constructs ...
*
*
*
* @param context
* @param repository
*/
public GitCatCommand(GitContext context,
sonia.scm.repository.Repository repository)
{
super(context, repository); super(context, repository);
} }
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param request
* @param output
*
* @throws IOException
* @throws RepositoryException
*/
@Override @Override
public void getCatResult(CatCommandRequest request, OutputStream output) public void getCatResult(CatCommandRequest request, OutputStream output) throws IOException, RepositoryException {
throws IOException, RepositoryException
{
logger.debug("try to read content for {}", request); logger.debug("try to read content for {}", request);
try (ClosableObjectLoaderContainer closableObjectLoaderContainer = getLoader(request)) {
org.eclipse.jgit.lib.Repository repo = open(); closableObjectLoaderContainer.objectLoader.copyTo(output);
}
ObjectId revId = getCommitOrDefault(repo, request.getRevision());
getContent(repo, revId, request.getPath(), output);
} }
@Override @Override
public InputStream getCatResultStream(CatCommandRequest request) throws IOException, RepositoryException { public InputStream getCatResultStream(CatCommandRequest request) throws IOException, RepositoryException {
logger.debug("try to read content for {}", request); logger.debug("try to read content for {}", request);
return new InputStreamWrapper(getLoader(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, void getContent(org.eclipse.jgit.lib.Repository repo, ObjectId revId, String path, OutputStream output) throws IOException, RepositoryException {
String path, OutputStream output) try (ClosableObjectLoaderContainer closableObjectLoaderContainer = getLoader(repo, revId, path)) {
throws IOException, RepositoryException
{
ClosableObjectLoaderContainer closableObjectLoaderContainer = getLoader(repo, revId, path);
try {
closableObjectLoaderContainer.objectLoader.copyTo(output); closableObjectLoaderContainer.objectLoader.copyTo(output);
} finally {
closableObjectLoaderContainer.close();
} }
} }
private ClosableObjectLoaderContainer getLoader(Repository repo, ObjectId revId, private ClosableObjectLoaderContainer getLoader(CatCommandRequest request) throws IOException, RepositoryException {
String path) org.eclipse.jgit.lib.Repository repo = open();
throws IOException, RepositoryException ObjectId revId = getCommitOrDefault(repo, request.getRevision());
{ return getLoader(repo, revId, request.getPath());
TreeWalk treeWalk = null; }
RevWalk revWalk = null;
try private ClosableObjectLoaderContainer getLoader(Repository repo, ObjectId revId, String path) throws IOException, RepositoryException {
{ TreeWalk treeWalk = new TreeWalk(repo);
treeWalk = new TreeWalk(repo); treeWalk.setRecursive(Util.nonNull(path).contains("/"));
treeWalk.setRecursive(Util.nonNull(path).contains("/"));
if (logger.isDebugEnabled()) logger.debug("load content for {} at {}", path, revId.name());
{
logger.debug("load content for {} at {}", path, revId.name());
}
revWalk = new RevWalk(repo); RevWalk revWalk = new RevWalk(repo);
RevCommit entry = revWalk.parseCommit(revId); RevCommit entry = revWalk.parseCommit(revId);
RevTree revTree = entry.getTree(); RevTree revTree = entry.getTree();
if (revTree != null) if (revTree != null) {
{ treeWalk.addTree(revTree);
treeWalk.addTree(revTree); } else {
} logger.error("could not find tree for {}", revId.name());
else
{
logger.error("could not find tree for {}", revId.name());
}
treeWalk.setFilter(PathFilter.create(path));
if (treeWalk.next() && treeWalk.getFileMode(0).getObjectType() == Constants.OBJ_BLOB)
{
ObjectId blobId = treeWalk.getObjectId(0);
ObjectLoader loader = repo.open(blobId);
return new ClosableObjectLoaderContainer(loader, treeWalk, revWalk);
}
else
{
throw new PathNotFoundException(path);
}
} }
finally
{ treeWalk.setFilter(PathFilter.create(path));
if (treeWalk.next() && treeWalk.getFileMode(0).getObjectType() == Constants.OBJ_BLOB) {
ObjectId blobId = treeWalk.getObjectId(0);
ObjectLoader loader = repo.open(blobId);
return new ClosableObjectLoaderContainer(loader, treeWalk, revWalk);
} else {
throw new PathNotFoundException(path);
} }
} }
@@ -195,37 +130,28 @@ public class GitCatCommand extends AbstractGitCommand implements CatCommand
} }
@Override @Override
public void close() throws IOException { public void close() {
GitUtil.release(revWalk); GitUtil.release(revWalk);
GitUtil.release(treeWalk); GitUtil.release(treeWalk);
} }
} }
private static class InputStreamWrapper extends InputStream { private static class InputStreamWrapper extends FilterInputStream {
private final InputStream delegate; private final ClosableObjectLoaderContainer container;
private final TreeWalk treeWalk;
private final RevWalk revWalk;
private InputStreamWrapper(ClosableObjectLoaderContainer container) throws IOException { private InputStreamWrapper(ClosableObjectLoaderContainer container) throws IOException {
this(container.objectLoader.openStream(), container.treeWalk, container.revWalk); super(container.objectLoader.openStream());
this.container = container;
} }
private InputStreamWrapper(InputStream delegate, TreeWalk treeWalk, RevWalk revWalk) { @Override
this.delegate = delegate; public void close() throws IOException {
this.treeWalk = treeWalk; try {
this.revWalk = revWalk; super.close();
} } finally {
container.close();
@Override
public int read () throws IOException {
return delegate.read();
}
@Override
public void close () throws IOException {
GitUtil.release(revWalk);
GitUtil.release(treeWalk);
} }
} }
}
} }

View File

@@ -32,19 +32,16 @@
package sonia.scm.repository.spi; package sonia.scm.repository.spi;
//~--- non-JDK imports --------------------------------------------------------
import org.junit.Test; import org.junit.Test;
import sonia.scm.repository.GitConstants;
import sonia.scm.repository.PathNotFoundException;
import sonia.scm.repository.RepositoryException; import sonia.scm.repository.RepositoryException;
import static org.junit.Assert.*;
//~--- JDK imports ------------------------------------------------------------
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import sonia.scm.repository.GitConstants; import java.io.InputStream;
import static org.junit.Assert.assertEquals;
/** /**
* Unit tests for {@link GitCatCommand}. * Unit tests for {@link GitCatCommand}.
@@ -53,15 +50,8 @@ import sonia.scm.repository.GitConstants;
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
public class GitCatCommandTest extends AbstractGitCommandTestBase public class GitCatCommandTest extends AbstractGitCommandTestBase {
{
/**
* Tests cat command with default branch.
*
* @throws IOException
* @throws RepositoryException
*/
@Test @Test
public void testDefaultBranch() throws IOException, RepositoryException { public void testDefaultBranch() throws IOException, RepositoryException {
// without default branch, the repository head should be used // without default branch, the repository head should be used
@@ -75,16 +65,8 @@ public class GitCatCommandTest extends AbstractGitCommandTestBase
assertEquals("a and b", execute(request)); assertEquals("a and b", execute(request));
} }
/**
* Method description
*
*
* @throws IOException
* @throws RepositoryException
*/
@Test @Test
public void testCat() throws IOException, RepositoryException public void testCat() throws IOException, RepositoryException {
{
CatCommandRequest request = new CatCommandRequest(); CatCommandRequest request = new CatCommandRequest();
request.setPath("a.txt"); request.setPath("a.txt");
@@ -92,36 +74,37 @@ public class GitCatCommandTest extends AbstractGitCommandTestBase
assertEquals("a and b", execute(request)); assertEquals("a and b", execute(request));
} }
/**
* Method description
*
*
* @throws IOException
* @throws RepositoryException
*/
@Test @Test
public void testSimpleCat() throws IOException, RepositoryException public void testSimpleCat() throws IOException, RepositoryException {
{
CatCommandRequest request = new CatCommandRequest(); CatCommandRequest request = new CatCommandRequest();
request.setPath("b.txt"); request.setPath("b.txt");
assertEquals("b", execute(request)); assertEquals("b", execute(request));
} }
/** @Test(expected = PathNotFoundException.class)
* Method description public void testUnknownFile() throws IOException, RepositoryException {
* CatCommandRequest request = new CatCommandRequest();
*
* @param request request.setPath("unknown");
* assertEquals("b", execute(request));
* @return }
*
* @throws IOException @Test
* @throws RepositoryException public void testSimpleStream() throws IOException, RepositoryException {
*/ CatCommandRequest request = new CatCommandRequest();
private String execute(CatCommandRequest request) request.setPath("b.txt");
throws IOException, RepositoryException
{ InputStream catResultStream = new GitCatCommand(createContext(), repository).getCatResultStream(request);
assertEquals('b', catResultStream.read());
assertEquals('\n', catResultStream.read());
assertEquals(-1, catResultStream.read());
catResultStream.close();
}
private String execute(CatCommandRequest request) throws IOException, RepositoryException {
String content = null; String content = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();