use jgit instead of git cli

This commit is contained in:
Sebastian Sdorra
2010-11-14 17:28:12 +01:00
parent c6d531a7b2
commit eb07384aeb
7 changed files with 252 additions and 220 deletions

View File

@@ -17,6 +17,12 @@
<dependencies> <dependencies>
<dependency>
<groupId>sonia.scm</groupId>
<artifactId>scm-web-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>servlet-api</artifactId>
@@ -25,11 +31,28 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>sonia.scm</groupId> <groupId>org.eclipse.jgit</groupId>
<artifactId>scm-web-api</artifactId> <artifactId>org.eclipse.jgit</artifactId>
<version>1.0-SNAPSHOT</version> <version>${jgit.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.http.server</artifactId>
<version>${jgit.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
<properties>
<jgit.version>0.9.3</jgit.version>
</properties>
<repositories>
<repository>
<id>jgit-repository</id>
<url>http://download.eclipse.org/jgit/maven</url>
</repository>
</repositories>
</project> </project>

View File

@@ -29,6 +29,8 @@
* *
*/ */
package sonia.scm.repository; package sonia.scm.repository;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
@@ -40,60 +42,4 @@ import javax.xml.bind.annotation.XmlRootElement;
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
@XmlRootElement(name = "config") @XmlRootElement(name = "config")
public class GitConfig extends SimpleRepositoryConfig public class GitConfig extends SimpleRepositoryConfig {}
{
/**
* Method description
*
*
* @return
*/
public String getGitBinary()
{
return gitBinary;
}
/**
* Method description
*
*
* @return
*/
public String getGitHttpBackend()
{
return gitHttpBackend;
}
//~--- set methods ----------------------------------------------------------
/**
* Method description
*
*
* @param gitBinary
*/
public void setGitBinary(String gitBinary)
{
this.gitBinary = gitBinary;
}
/**
* Method description
*
*
* @param gitHttpBackend
*/
public void setGitHttpBackend(String gitHttpBackend)
{
this.gitHttpBackend = gitHttpBackend;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private String gitBinary = "git";
/** Field description */
private String gitHttpBackend = "git-http-backend";
}

View File

@@ -37,9 +37,9 @@ package sonia.scm.repository;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import sonia.scm.Type; import sonia.scm.Type;
import sonia.scm.io.CommandResult;
import sonia.scm.io.ExtendedCommand;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
@@ -80,23 +80,6 @@ public class GitRepositoryHandler
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param repository
* @param directory
*
* @return
*/
@Override
protected ExtendedCommand buildCreateCommand(Repository repository,
File directory)
{
return new ExtendedCommand(config.getGitBinary(), "init", "--bare",
directory.getPath());
}
/** /**
* Method description * Method description
* *
@@ -108,18 +91,11 @@ public class GitRepositoryHandler
* @throws RepositoryException * @throws RepositoryException
*/ */
@Override @Override
protected void postCreate(Repository repository, File directory) protected void create(Repository repository, File directory)
throws IOException, RepositoryException throws RepositoryException, IOException
{ {
ExtendedCommand command = new ExtendedCommand(config.getGitBinary(), new FileRepositoryBuilder().setGitDir(
"update-server-info"); directory).readEnvironment().findGitDir().build().create(true);
command.setWorkDirectory(directory);
execute(command);
command = new ExtendedCommand(config.getGitBinary(), "config", "--bool",
"--add", "http.receivepack", "true");
command.setWorkDirectory(directory);
execute(command);
} }
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
@@ -136,30 +112,8 @@ public class GitRepositoryHandler
return GitConfig.class; return GitConfig.class;
} }
//~--- methods -------------------------------------------------------------- //~--- fields ---------------------------------------------------------------
/** /** Field description */
* Method description private FileRepositoryBuilder builder = new FileRepositoryBuilder();
*
*
* @param command
*
* @throws IOException
* @throws RepositoryException
*/
private void execute(ExtendedCommand command)
throws IOException, RepositoryException
{
CommandResult result = command.execute();
if (!result.isSuccessfull())
{
StringBuilder msg = new StringBuilder("command exit with error ");
msg.append(result.getReturnCode()).append(" and message: '");
msg.append(result.getOutput()).append("'");
throw new RepositoryException(msg.toString());
}
}
} }

View File

@@ -0,0 +1,192 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.web;
//~--- non-JDK imports --------------------------------------------------------
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.http.server.resolver.RepositoryResolver;
import org.eclipse.jgit.http.server.resolver.ServiceNotAuthorizedException;
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
import org.eclipse.jgit.util.FS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.GitConfig;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
/**
*
* @author Sebastian Sdorra
*/
public class GitRepositoryResolver implements RepositoryResolver
{
/** the logger for GitRepositoryResolver */
private static final Logger logger =
LoggerFactory.getLogger(GitRepositoryResolver.class);
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param config
*/
public GitRepositoryResolver(GitConfig config)
{
this.config = config;
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param name
*
* @return
*/
private static boolean isUnreasonableName(final String name)
{
if (name.length() == 0)
{
return true; // no empty paths
}
if (name.indexOf('\\') >= 0)
{
return true; // no windows/dos style paths
}
if (new File(name).isAbsolute())
{
return true; // no absolute paths
}
if (name.startsWith("../"))
{
return true; // no "l../etc/passwd"
}
if (name.contains("/../"))
{
return true; // no "foo/../etc/passwd"
}
if (name.contains("/./"))
{
return true; // "foo/./foo" is insane to ask
}
if (name.contains("//"))
{
return true; // double slashes is sloppy, don't use it
}
return false; // is a reasonable name
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param request
* @param repositoryName
*
* @return
*
* @throws RepositoryNotFoundException
* @throws ServiceNotAuthorizedException
* @throws ServiceNotEnabledException
*/
@Override
public Repository open(HttpServletRequest request, String repositoryName)
throws RepositoryNotFoundException, ServiceNotAuthorizedException,
ServiceNotEnabledException
{
Repository repository = null;
if (isUnreasonableName(repositoryName))
{
throw new RepositoryNotFoundException(repositoryName);
}
try
{
File gitdir = new File(config.getRepositoryDirectory(), repositoryName);
if (!gitdir.exists())
{
throw new RepositoryNotFoundException(repositoryName);
}
repository = RepositoryCache.open(FileKey.lenient(gitdir, FS.DETECTED),
true);
}
catch (RuntimeException e)
{
repository.close();
throw new RepositoryNotFoundException(repositoryName, e);
}
catch (IOException e)
{
repository.close();
throw new RepositoryNotFoundException(repositoryName, e);
}
return repository;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private GitConfig config;
}

View File

@@ -81,7 +81,7 @@ public class GitWebPlugin implements ScmWebPlugin
protected void configureServlets() protected void configureServlets()
{ {
filter("/git/*").through(BasicAuthenticationFilter.class); filter("/git/*").through(BasicAuthenticationFilter.class);
serve("/git/*").with(GitCGIServlet.class); serve("/git/*").with(ScmGitServlet.class);
} }
}); });
} }

View File

@@ -29,6 +29,8 @@
* *
*/ */
package sonia.scm.web; package sonia.scm.web;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
@@ -36,15 +38,13 @@ package sonia.scm.web;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import sonia.scm.repository.GitConfig; import org.eclipse.jgit.http.server.GitServlet;
import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.GitRepositoryHandler;
import sonia.scm.util.IOUtil; import sonia.scm.util.IOUtil;
import sonia.scm.web.cgi.AbstractCGIServlet;
import sonia.scm.web.cgi.EnvList;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@@ -58,15 +58,9 @@ import javax.servlet.http.HttpServletResponse;
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
@Singleton @Singleton
public class GitCGIServlet extends AbstractCGIServlet public class ScmGitServlet extends GitServlet
{ {
/** Field description */
public static final String ENV_HTTP_EXPORT_ALL = "GIT_HTTP_EXPORT_ALL";
/** Field description */
public static final String ENV_PROJECT_ROOT = "GIT_PROJECT_ROOT";
/** Field description */ /** Field description */
public static final String MIMETYPE_HTML = "text/html"; public static final String MIMETYPE_HTML = "text/html";
@@ -78,56 +72,24 @@ public class GitCGIServlet extends AbstractCGIServlet
public static final String RESOURCE_GITINDEX = "/sonia/scm/git.index.html"; public static final String RESOURCE_GITINDEX = "/sonia/scm/git.index.html";
/** Field description */ /** Field description */
private static final long serialVersionUID = 9147517765161830847L; private static final long serialVersionUID = -7712897339207470674L;
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param handler
*/
@Inject
public ScmGitServlet(GitRepositoryHandler handler)
{
setRepositoryResolver(new GitRepositoryResolver(handler.getConfig()));
}
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @return
*
* @throws ServletException
*/
@Override
protected EnvList createBaseEnvironment() throws ServletException
{
EnvList list = super.createBaseEnvironment();
list.set(ENV_HTTP_EXPORT_ALL, "");
return list;
}
/**
* Method description
*
*
* @param baseEnvironment
*
* @return
*
* @throws ServletException
*/
@Override
protected EnvList createRequestEnvironment(EnvList baseEnvironment)
throws ServletException
{
GitConfig config = repositoryHandler.getConfig();
if (config == null)
{
throw new ServletException("git is not configured");
}
EnvList env = new EnvList(baseEnvironment);
env.set(ENV_PROJECT_ROOT, config.getRepositoryDirectory().getPath());
return env;
}
/** /**
* Method description * Method description
* *
@@ -155,35 +117,6 @@ public class GitCGIServlet extends AbstractCGIServlet
} }
} }
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param request
*
* @return
*
* @throws IOException
* @throws ServletException
*/
@Override
protected File getCommand(HttpServletRequest request)
throws ServletException, IOException
{
GitConfig config = repositoryHandler.getConfig();
if (config == null)
{
throw new ServletException("git is not configured");
}
return new File(config.getGitHttpBackend());
}
//~--- methods --------------------------------------------------------------
/** /**
* Method description * Method description
* *
@@ -203,7 +136,7 @@ public class GitCGIServlet extends AbstractCGIServlet
try try
{ {
input = GitCGIServlet.class.getResourceAsStream(RESOURCE_GITINDEX); input = ScmGitServlet.class.getResourceAsStream(RESOURCE_GITINDEX);
output = response.getOutputStream(); output = response.getOutputStream();
IOUtil.copy(input, output); IOUtil.copy(input, output);
} }
@@ -228,10 +161,4 @@ public class GitCGIServlet extends AbstractCGIServlet
{ {
return request.getRequestURI().substring(request.getContextPath().length()); return request.getRequestURI().substring(request.getContextPath().length());
} }
//~--- fields ---------------------------------------------------------------
/** Field description */
@Inject
private GitRepositoryHandler repositoryHandler;
} }

View File

@@ -33,11 +33,6 @@ registerConfigPanel({
xtype : 'configForm', xtype : 'configForm',
title : 'Git Settings', title : 'Git Settings',
items : [{ items : [{
xtype : 'textfield',
fieldLabel : 'Git Binary',
name : 'gitBinary',
allowBlank : false
},{
xtype: 'textfield', xtype: 'textfield',
name: 'repositoryDirectory', name: 'repositoryDirectory',
fieldLabel: 'Repository directory', fieldLabel: 'Repository directory',
@@ -47,11 +42,6 @@ registerConfigPanel({
name: 'baseUrl', name: 'baseUrl',
fieldLabel: 'Base URL', fieldLabel: 'Base URL',
allowBlank : false allowBlank : false
},{
xtype : 'textfield',
fieldLabel : 'Git-Http-Backend',
name : 'gitHttpBackend',
allowBlank : false
}], }],
onSubmit: function(values){ onSubmit: function(values){