Merged in feature/errorhandling (pull request #99)

Feature Error Handling
This commit is contained in:
Sebastian Sdorra
2018-11-08 09:36:18 +00:00
139 changed files with 1122 additions and 2010 deletions

View File

@@ -56,6 +56,7 @@ import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.util.FS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.ContextEntry;
import sonia.scm.util.HttpUtil;
import sonia.scm.util.Util;
import sonia.scm.web.GitUserAgentProvider;
@@ -204,7 +205,7 @@ public final class GitUtil
}
catch (GitAPIException ex)
{
throw new InternalRepositoryException("could not fetch", ex);
throw new InternalRepositoryException(ContextEntry.ContextBuilder.entity("remote", directory.toString()).in(remoteRepository), "could not fetch", ex);
}
}

View File

@@ -160,7 +160,7 @@ public abstract class AbstractGitIncomingOutgoingCommand
}
catch (Exception ex)
{
throw new InternalRepositoryException("could not execute incoming command", ex);
throw new InternalRepositoryException(repository, "could not execute incoming command", ex);
}
finally
{
@@ -200,13 +200,7 @@ public abstract class AbstractGitIncomingOutgoingCommand
{
if (e.getKey().startsWith(prefix))
{
if (ref != null)
{
throw new InternalRepositoryException("could not find remote branch");
}
ref = e.getValue();
break;
}
}

View File

@@ -114,7 +114,7 @@ public abstract class AbstractGitPushOrPullCommand extends AbstractGitCommand
}
catch (Exception ex)
{
throw new InternalRepositoryException("could not execute push/pull command", ex);
throw new InternalRepositoryException(repository, "could not execute push/pull command", ex);
}
return counter;

View File

@@ -55,6 +55,8 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static sonia.scm.ContextEntry.ContextBuilder.entity;
//~--- JDK imports ------------------------------------------------------------
/**
@@ -108,9 +110,8 @@ public class GitBlameCommand extends AbstractGitCommand implements BlameCommand
if (gitBlameResult == null)
{
throw new InternalRepositoryException(
"could not create blame result for path ".concat(
request.getPath()));
throw new InternalRepositoryException(entity("path", request.getPath()).in(repository),
"could not create blame result for path");
}
List<BlameLine> blameLines = new ArrayList<BlameLine>();
@@ -150,7 +151,7 @@ public class GitBlameCommand extends AbstractGitCommand implements BlameCommand
}
catch (GitAPIException ex)
{
throw new InternalRepositoryException("could not create blame view", ex);
throw new InternalRepositoryException(repository, "could not create blame view", ex);
}
return result;

View File

@@ -102,7 +102,7 @@ public class GitBranchesCommand extends AbstractGitCommand
}
catch (GitAPIException ex)
{
throw new InternalRepositoryException("could not read branches", ex);
throw new InternalRepositoryException(repository, "could not read branches", ex);
}
return branches;

View File

@@ -55,9 +55,7 @@ import sonia.scm.repository.BrowserResult;
import sonia.scm.repository.FileObject;
import sonia.scm.repository.GitSubModuleParser;
import sonia.scm.repository.GitUtil;
import sonia.scm.repository.PathNotFoundException;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RevisionNotFoundException;
import sonia.scm.repository.SubRepository;
import sonia.scm.util.Util;
@@ -104,7 +102,7 @@ public class GitBrowseCommand extends AbstractGitCommand
@Override
@SuppressWarnings("unchecked")
public BrowserResult getBrowserResult(BrowseCommandRequest request)
throws IOException, NotFoundException {
throws IOException {
logger.debug("try to create browse result for {}", request);
BrowserResult result;
@@ -166,7 +164,7 @@ public class GitBrowseCommand extends AbstractGitCommand
*/
private FileObject createFileObject(org.eclipse.jgit.lib.Repository repo,
BrowseCommandRequest request, ObjectId revId, TreeWalk treeWalk)
throws IOException, RevisionNotFoundException {
throws IOException {
FileObject file = new FileObject();
@@ -258,7 +256,7 @@ public class GitBrowseCommand extends AbstractGitCommand
return result;
}
private FileObject getEntry(org.eclipse.jgit.lib.Repository repo, BrowseCommandRequest request, ObjectId revId) throws IOException, NotFoundException {
private FileObject getEntry(org.eclipse.jgit.lib.Repository repo, BrowseCommandRequest request, ObjectId revId) throws IOException {
RevWalk revWalk = null;
TreeWalk treeWalk = null;
@@ -309,7 +307,7 @@ public class GitBrowseCommand extends AbstractGitCommand
return Strings.isNullOrEmpty(request.getPath()) || "/".equals(request.getPath());
}
private FileObject findChildren(FileObject parent, org.eclipse.jgit.lib.Repository repo, BrowseCommandRequest request, ObjectId revId, TreeWalk treeWalk) throws IOException, NotFoundException {
private FileObject findChildren(FileObject parent, org.eclipse.jgit.lib.Repository repo, BrowseCommandRequest request, ObjectId revId, TreeWalk treeWalk) throws IOException {
List<FileObject> files = Lists.newArrayList();
while (treeWalk.next())
{
@@ -337,7 +335,7 @@ public class GitBrowseCommand extends AbstractGitCommand
}
private FileObject findFirstMatch(org.eclipse.jgit.lib.Repository repo,
BrowseCommandRequest request, ObjectId revId, TreeWalk treeWalk) throws IOException, NotFoundException {
BrowseCommandRequest request, ObjectId revId, TreeWalk treeWalk) throws IOException {
String[] pathElements = request.getPath().split("/");
int currentDepth = 0;
int limit = pathElements.length;
@@ -363,7 +361,7 @@ public class GitBrowseCommand extends AbstractGitCommand
private Map<String,
SubRepository> getSubRepositories(org.eclipse.jgit.lib.Repository repo,
ObjectId revision)
throws IOException, RevisionNotFoundException {
throws IOException {
if (logger.isDebugEnabled())
{
logger.debug("read submodules of {} at {}", repository.getName(),
@@ -377,7 +375,7 @@ public class GitBrowseCommand extends AbstractGitCommand
PATH_MODULES, baos);
subRepositories = GitSubModuleParser.parse(baos.toString());
}
catch (PathNotFoundException ex)
catch (NotFoundException ex)
{
logger.trace("could not find .gitmodules", ex);
subRepositories = Collections.EMPTY_MAP;
@@ -388,7 +386,7 @@ public class GitBrowseCommand extends AbstractGitCommand
private SubRepository getSubRepository(org.eclipse.jgit.lib.Repository repo,
ObjectId revId, String path)
throws IOException, RevisionNotFoundException {
throws IOException {
Map<String, SubRepository> subRepositories = subrepositoryCache.get(revId);
if (subRepositories == null)

View File

@@ -45,8 +45,6 @@ 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.RevisionNotFoundException;
import sonia.scm.util.Util;
import java.io.Closeable;
@@ -55,6 +53,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import static sonia.scm.ContextEntry.ContextBuilder.entity;
import static sonia.scm.NotFoundException.notFound;
public class GitCatCommand extends AbstractGitCommand implements CatCommand {
@@ -65,7 +66,7 @@ public class GitCatCommand extends AbstractGitCommand implements CatCommand {
}
@Override
public void getCatResult(CatCommandRequest request, OutputStream output) throws IOException, PathNotFoundException, RevisionNotFoundException {
public void getCatResult(CatCommandRequest request, OutputStream output) throws IOException {
logger.debug("try to read content for {}", request);
try (ClosableObjectLoaderContainer closableObjectLoaderContainer = getLoader(request)) {
closableObjectLoaderContainer.objectLoader.copyTo(output);
@@ -73,24 +74,24 @@ public class GitCatCommand extends AbstractGitCommand implements CatCommand {
}
@Override
public InputStream getCatResultStream(CatCommandRequest request) throws IOException, PathNotFoundException, RevisionNotFoundException {
public InputStream getCatResultStream(CatCommandRequest request) throws IOException {
logger.debug("try to read content for {}", request);
return new InputStreamWrapper(getLoader(request));
}
void getContent(org.eclipse.jgit.lib.Repository repo, ObjectId revId, String path, OutputStream output) throws IOException, PathNotFoundException, RevisionNotFoundException {
void getContent(org.eclipse.jgit.lib.Repository repo, ObjectId revId, String path, OutputStream output) throws IOException {
try (ClosableObjectLoaderContainer closableObjectLoaderContainer = getLoader(repo, revId, path)) {
closableObjectLoaderContainer.objectLoader.copyTo(output);
}
}
private ClosableObjectLoaderContainer getLoader(CatCommandRequest request) throws IOException, PathNotFoundException, RevisionNotFoundException {
private ClosableObjectLoaderContainer getLoader(CatCommandRequest request) throws IOException {
org.eclipse.jgit.lib.Repository repo = open();
ObjectId revId = getCommitOrDefault(repo, request.getRevision());
return getLoader(repo, revId, request.getPath());
}
private ClosableObjectLoaderContainer getLoader(Repository repo, ObjectId revId, String path) throws IOException, PathNotFoundException, RevisionNotFoundException {
private ClosableObjectLoaderContainer getLoader(Repository repo, ObjectId revId, String path) throws IOException {
TreeWalk treeWalk = new TreeWalk(repo);
treeWalk.setRecursive(Util.nonNull(path).contains("/"));
@@ -102,7 +103,7 @@ public class GitCatCommand extends AbstractGitCommand implements CatCommand {
try {
entry = revWalk.parseCommit(revId);
} catch (MissingObjectException e) {
throw new RevisionNotFoundException(revId.getName());
throw notFound(entity("Revision", revId.getName()).in(repository));
}
RevTree revTree = entry.getTree();
@@ -120,7 +121,7 @@ public class GitCatCommand extends AbstractGitCommand implements CatCommand {
return new ClosableObjectLoaderContainer(loader, treeWalk, revWalk);
} else {
throw new PathNotFoundException(path);
throw notFound(entity("Path", path).in("Revision", revId.getName()).in(repository));
}
}

View File

@@ -54,7 +54,6 @@ import sonia.scm.repository.ChangesetPagingResult;
import sonia.scm.repository.GitChangesetConverter;
import sonia.scm.repository.GitUtil;
import sonia.scm.repository.InternalRepositoryException;
import sonia.scm.repository.RevisionNotFoundException;
import sonia.scm.util.IOUtil;
import java.io.IOException;
@@ -62,6 +61,9 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import static sonia.scm.ContextEntry.ContextBuilder.entity;
import static sonia.scm.NotFoundException.notFound;
//~--- JDK imports ------------------------------------------------------------
/**
@@ -86,7 +88,6 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand
*
* @param context
* @param repository
* @param repositoryDirectory
*/
GitLogCommand(GitContext context, sonia.scm.repository.Repository repository)
{
@@ -163,7 +164,7 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand
*/
@Override
@SuppressWarnings("unchecked")
public ChangesetPagingResult getChangesets(LogCommandRequest request) throws RevisionNotFoundException {
public ChangesetPagingResult getChangesets(LogCommandRequest request) {
if (logger.isDebugEnabled()) {
logger.debug("fetch changesets for request: {}", request);
}
@@ -261,11 +262,11 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand
}
catch (MissingObjectException e)
{
throw new RevisionNotFoundException(e.getObjectId().name());
throw notFound(entity("Revision", e.getObjectId().getName()).in(repository));
}
catch (Exception ex)
{
throw new InternalRepositoryException("could not create change log", ex);
throw new InternalRepositoryException(repository, "could not create change log", ex);
}
finally
{

View File

@@ -17,6 +17,8 @@ import java.io.IOException;
import java.text.MessageFormat;
import java.util.List;
import static sonia.scm.ContextEntry.ContextBuilder.entity;
@Slf4j
public class GitModificationsCommand extends AbstractGitCommand implements ModificationsCommand {
@@ -26,7 +28,7 @@ public class GitModificationsCommand extends AbstractGitCommand implements Modif
}
private Modifications createModifications(TreeWalk treeWalk, RevCommit commit, RevWalk revWalk, String revision)
throws IOException, UnsupportedModificationTypeException {
throws IOException {
treeWalk.reset();
treeWalk.setRecursive(true);
if (commit.getParentCount() > 0) {
@@ -73,12 +75,7 @@ public class GitModificationsCommand extends AbstractGitCommand implements Modif
}
} catch (IOException ex) {
log.error("could not open repository", ex);
throw new InternalRepositoryException(ex);
} catch (UnsupportedModificationTypeException ex) {
log.error("Unsupported modification type", ex);
throw new InternalRepositoryException(ex);
throw new InternalRepositoryException(entity(repository), "could not open repository", ex);
} finally {
GitUtil.release(revWalk);
GitUtil.close(gitRepository);
@@ -100,7 +97,7 @@ public class GitModificationsCommand extends AbstractGitCommand implements Modif
} else if (type == DiffEntry.ChangeType.DELETE) {
modifications.getRemoved().add(entry.getOldPath());
} else {
throw new UnsupportedModificationTypeException(MessageFormat.format("The modification type: {0} is not supported.", type));
throw new UnsupportedModificationTypeException(entity(repository), MessageFormat.format("The modification type: {0} is not supported.", type));
}
}
}

View File

@@ -249,7 +249,7 @@ public class GitPullCommand extends AbstractGitPushOrPullCommand
}
catch (GitAPIException ex)
{
throw new InternalRepositoryException("error durring pull", ex);
throw new InternalRepositoryException(repository, "error during pull", ex);
}
return response;

View File

@@ -95,7 +95,7 @@ public class GitTagsCommand extends AbstractGitCommand implements TagsCommand
}
catch (GitAPIException ex)
{
throw new InternalRepositoryException("could not read tags from repository", ex);
throw new InternalRepositoryException(repository, "could not read tags from repository", ex);
}
finally
{

View File

@@ -1,9 +1,10 @@
package sonia.scm.repository.spi;
import sonia.scm.ContextEntry;
import sonia.scm.repository.InternalRepositoryException;
public class UnsupportedModificationTypeException extends InternalRepositoryException {
public UnsupportedModificationTypeException(String message) {
super(message);
public UnsupportedModificationTypeException(ContextEntry.ContextBuilder entity, String message) {
super(entity, message);
}
}

View File

@@ -32,7 +32,6 @@
package sonia.scm.repository.spi;
import org.junit.Test;
import sonia.scm.NotFoundException;
import sonia.scm.repository.BrowserResult;
import sonia.scm.repository.FileObject;
import sonia.scm.repository.GitConstants;
@@ -54,7 +53,7 @@ import static org.junit.Assert.assertTrue;
public class GitBrowseCommandTest extends AbstractGitCommandTestBase {
@Test
public void testGetFile() throws IOException, NotFoundException {
public void testDefaultBranch() throws IOException {
BrowseCommandRequest request = new BrowseCommandRequest();
request.setPath("a.txt");
BrowserResult result = createCommand().getBrowserResult(request);
@@ -63,7 +62,7 @@ public class GitBrowseCommandTest extends AbstractGitCommandTestBase {
}
@Test
public void testDefaultDefaultBranch() throws IOException, NotFoundException {
public void testDefaultDefaultBranch() throws IOException {
// without default branch, the repository head should be used
FileObject root = createCommand().getBrowserResult(new BrowseCommandRequest()).getFile();
assertNotNull(root);
@@ -78,7 +77,7 @@ public class GitBrowseCommandTest extends AbstractGitCommandTestBase {
}
@Test
public void testExplicitDefaultBranch() throws IOException, NotFoundException {
public void testExplicitDefaultBranch() throws IOException {
repository.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "test-branch");
FileObject root = createCommand().getBrowserResult(new BrowseCommandRequest()).getFile();
@@ -91,7 +90,7 @@ public class GitBrowseCommandTest extends AbstractGitCommandTestBase {
}
@Test
public void testBrowse() throws IOException, NotFoundException {
public void testBrowse() throws IOException {
FileObject root = createCommand().getBrowserResult(new BrowseCommandRequest()).getFile();
assertNotNull(root);
@@ -113,7 +112,7 @@ public class GitBrowseCommandTest extends AbstractGitCommandTestBase {
}
@Test
public void testBrowseSubDirectory() throws IOException, NotFoundException {
public void testBrowseSubDirectory() throws IOException {
BrowseCommandRequest request = new BrowseCommandRequest();
request.setPath("c");
@@ -143,7 +142,7 @@ public class GitBrowseCommandTest extends AbstractGitCommandTestBase {
}
@Test
public void testRecursive() throws IOException, NotFoundException {
public void testRecusive() throws IOException {
BrowseCommandRequest request = new BrowseCommandRequest();
request.setRecursive(true);

View File

@@ -32,10 +32,13 @@
package sonia.scm.repository.spi;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import sonia.scm.NotFoundException;
import sonia.scm.repository.GitConstants;
import sonia.scm.repository.PathNotFoundException;
import sonia.scm.repository.RevisionNotFoundException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -51,9 +54,12 @@ import static org.junit.Assert.assertEquals;
* @author Sebastian Sdorra
*/
public class GitCatCommandTest extends AbstractGitCommandTestBase {
@Rule
public final ExpectedException expectedException = ExpectedException.none();
@Test
public void testDefaultBranch() throws IOException, PathNotFoundException, RevisionNotFoundException {
public void testDefaultBranch() throws IOException {
// without default branch, the repository head should be used
CatCommandRequest request = new CatCommandRequest();
request.setPath("a.txt");
@@ -66,7 +72,7 @@ public class GitCatCommandTest extends AbstractGitCommandTestBase {
}
@Test
public void testCat() throws IOException, PathNotFoundException, RevisionNotFoundException {
public void testCat() throws IOException {
CatCommandRequest request = new CatCommandRequest();
request.setPath("a.txt");
@@ -75,32 +81,58 @@ public class GitCatCommandTest extends AbstractGitCommandTestBase {
}
@Test
public void testSimpleCat() throws IOException, PathNotFoundException, RevisionNotFoundException {
public void testSimpleCat() throws IOException {
CatCommandRequest request = new CatCommandRequest();
request.setPath("b.txt");
assertEquals("b", execute(request));
}
@Test(expected = PathNotFoundException.class)
public void testUnknownFile() throws IOException, PathNotFoundException, RevisionNotFoundException {
@Test
public void testUnknownFile() throws IOException {
CatCommandRequest request = new CatCommandRequest();
request.setPath("unknown");
execute(request);
}
@Test(expected = RevisionNotFoundException.class)
public void testUnknownRevision() throws IOException, PathNotFoundException, RevisionNotFoundException {
CatCommandRequest request = new CatCommandRequest();
expectedException.expect(new BaseMatcher<Object>() {
@Override
public void describeTo(Description description) {
description.appendText("expected NotFoundException for path");
}
@Override
public boolean matches(Object item) {
return "Path".equals(((NotFoundException)item).getContext().get(0).getType());
}
});
request.setRevision("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
request.setPath("a.txt");
execute(request);
}
@Test
public void testSimpleStream() throws IOException, PathNotFoundException, RevisionNotFoundException {
public void testUnknownRevision() throws IOException {
CatCommandRequest request = new CatCommandRequest();
request.setRevision("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
request.setPath("a.txt");
expectedException.expect(new BaseMatcher<Object>() {
@Override
public void describeTo(Description description) {
description.appendText("expected NotFoundException for revision");
}
@Override
public boolean matches(Object item) {
return "Revision".equals(((NotFoundException)item).getContext().get(0).getType());
}
});
execute(request);
}
@Test
public void testSimpleStream() throws IOException {
CatCommandRequest request = new CatCommandRequest();
request.setPath("b.txt");
@@ -113,7 +145,7 @@ public class GitCatCommandTest extends AbstractGitCommandTestBase {
catResultStream.close();
}
private String execute(CatCommandRequest request) throws IOException, PathNotFoundException, RevisionNotFoundException {
private String execute(CatCommandRequest request) throws IOException {
String content = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();