Do not map not found exception manually

This commit is contained in:
René Pfeuffer
2019-03-04 14:27:07 +01:00
parent ffbf9e4fba
commit adcfb3ee5a
5 changed files with 184 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
package sonia.scm.protocolcommand.git;
import com.google.inject.servlet.ServletModule;
import sonia.scm.plugin.Extension;
import sonia.scm.protocolcommand.RepositoryContextResolver;
import sonia.scm.protocolcommand.ScmSshProtocol;
@Extension
public class GitProtocolModule extends ServletModule {
@Override
protected void configureServlets() {
bind(RepositoryContextResolver.class).to(GitRepositoryContextResolver.class);
bind(ScmSshProtocol.class).to(GitSshProtocol.class);
}
}

View File

@@ -0,0 +1,44 @@
package sonia.scm.protocolcommand.git;
import com.google.common.base.Splitter;
import sonia.scm.protocolcommand.RepositoryContext;
import sonia.scm.protocolcommand.RepositoryContextResolver;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryLocationResolver;
import sonia.scm.repository.RepositoryManager;
import javax.inject.Inject;
import java.nio.file.Path;
import java.util.Iterator;
public class GitRepositoryContextResolver implements RepositoryContextResolver {
private RepositoryManager repositoryManager;
private RepositoryLocationResolver locationResolver;
@Inject
public GitRepositoryContextResolver(RepositoryManager repositoryManager, RepositoryLocationResolver locationResolver) {
this.repositoryManager = repositoryManager;
this.locationResolver = locationResolver;
}
public RepositoryContext resolve(String[] args) {
NamespaceAndName namespaceAndName = extractNamespaceAndName(args);
Repository repository = repositoryManager.get(namespaceAndName);
Path path = locationResolver.getPath(repository.getId()).resolve("data");
return new RepositoryContext(repository, path);
}
private NamespaceAndName extractNamespaceAndName(String[] args) {
String path = args[args.length - 1];
Iterator<String> it = Splitter.on('/').omitEmptyStrings().split(path).iterator();
String type = it.next();
if ("repo".equals(type)) {
String ns = it.next();
String name = it.next();
return new NamespaceAndName(ns, name);
}
return null;
}
}

View File

@@ -0,0 +1,68 @@
package sonia.scm.protocolcommand.git;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.transport.ReceivePack;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.UploadPack;
import org.eclipse.jgit.util.FS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.protocolcommand.CommandContext;
import sonia.scm.protocolcommand.RepositoryContext;
import sonia.scm.protocolcommand.ScmSshProtocol;
import sonia.scm.repository.RepositoryPermissions;
import javax.inject.Inject;
import java.io.IOException;
public class GitSshProtocol implements ScmSshProtocol {
private static final Logger LOG = LoggerFactory.getLogger(GitSshProtocol.class);
private SshUploadPackFactory uploadPackFactory;
private SshReceivePackFactory receivePackFactory;
@Inject
public GitSshProtocol(SshUploadPackFactory uploadPackFactory, SshReceivePackFactory receivePackFactory) {
this.uploadPackFactory = uploadPackFactory;
this.receivePackFactory = receivePackFactory;
}
@Override
public void handle(CommandContext commandContext, RepositoryContext repositoryContext) throws IOException {
String subCommand = commandContext.getArgs()[0];
if (RemoteConfig.DEFAULT_UPLOAD_PACK.equals(subCommand)) {
LOG.trace("got upload pack");
upload(commandContext, repositoryContext);
} else if (RemoteConfig.DEFAULT_RECEIVE_PACK.equals(subCommand)) {
LOG.trace("got receive pack");
receive(commandContext, repositoryContext);
} else {
throw new IllegalArgumentException("Unknown git command: " + commandContext.getCommand());
}
}
private void receive(CommandContext commandContext, RepositoryContext repositoryContext) throws IOException {
RepositoryPermissions.push(repositoryContext.getRepository()).check();
try (Repository repository = open(repositoryContext)) {
ReceivePack receivePack = receivePackFactory.create(repositoryContext, repository);
receivePack.receive(commandContext.getInputStream(), commandContext.getOutputStream(), commandContext.getErrorStream());
}
}
private void upload(CommandContext commandContext, RepositoryContext repositoryContext) throws IOException {
RepositoryPermissions.pull(repositoryContext.getRepository()).check();
try (Repository repository = open(repositoryContext)) {
UploadPack uploadPack = uploadPackFactory.create(repositoryContext, repository);
uploadPack.upload(commandContext.getInputStream(), commandContext.getOutputStream(), commandContext.getErrorStream());
}
}
private Repository open(RepositoryContext repositoryContext) throws IOException {
RepositoryCache.FileKey key = RepositoryCache.FileKey.lenient(repositoryContext.getDirectory().toFile(), FS.DETECTED);
return key.open(true);
}
}

View File

@@ -0,0 +1,44 @@
package sonia.scm.protocolcommand.git;
import com.google.inject.Inject;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.ReceivePack;
import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
import sonia.scm.protocolcommand.RepositoryContext;
import sonia.scm.repository.GitRepositoryHandler;
import sonia.scm.repository.spi.HookEventFacade;
import sonia.scm.web.CollectingPackParserListener;
import sonia.scm.web.GitReceiveHook;
/**
* TODO we should have a single/abstract ReceivePackFactory for http and ssh.
*/
public class SshReceivePackFactory implements ReceivePackFactory<RepositoryContext> {
private final GitRepositoryHandler handler;
private final GitReceiveHook hook;
@Inject
public SshReceivePackFactory(GitRepositoryHandler handler, HookEventFacade hookEventFacade) {
this.handler = handler;
this.hook = new GitReceiveHook(hookEventFacade, handler);
}
@Override
public ReceivePack create(RepositoryContext repositoryContext, Repository repository) {
ReceivePack receivePack = new ReceivePack(repository);
receivePack.setAllowNonFastForwards(isNonFastForwardAllowed());
receivePack.setPreReceiveHook(hook);
receivePack.setPostReceiveHook(hook);
// apply collecting listener, to be able to check which commits are new
CollectingPackParserListener.set(receivePack);
return receivePack;
}
private boolean isNonFastForwardAllowed() {
return ! handler.getConfig().isNonFastForwardDisallowed();
}
}

View File

@@ -0,0 +1,13 @@
package sonia.scm.protocolcommand.git;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.UploadPack;
import org.eclipse.jgit.transport.resolver.UploadPackFactory;
import sonia.scm.protocolcommand.RepositoryContext;
public class SshUploadPackFactory implements UploadPackFactory<RepositoryContext> {
@Override
public UploadPack create(RepositoryContext repositoryContext, Repository repository) {
return new UploadPack(repository);
}
}