mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-13 00:45:44 +01:00
use jgit instead of git cli
This commit is contained in:
@@ -17,6 +17,12 @@
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>sonia.scm</groupId>
|
||||
<artifactId>scm-web-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
@@ -25,11 +31,28 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>sonia.scm</groupId>
|
||||
<artifactId>scm-web-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
<artifactId>org.eclipse.jgit</artifactId>
|
||||
<version>${jgit.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
<artifactId>org.eclipse.jgit.http.server</artifactId>
|
||||
<version>${jgit.version}</version>
|
||||
</dependency>
|
||||
|
||||
</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>
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
@@ -40,60 +42,4 @@ import javax.xml.bind.annotation.XmlRootElement;
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@XmlRootElement(name = "config")
|
||||
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";
|
||||
}
|
||||
public class GitConfig extends SimpleRepositoryConfig {}
|
||||
|
||||
@@ -37,9 +37,9 @@ package sonia.scm.repository;
|
||||
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
|
||||
|
||||
import sonia.scm.Type;
|
||||
import sonia.scm.io.CommandResult;
|
||||
import sonia.scm.io.ExtendedCommand;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
@@ -80,23 +80,6 @@ public class GitRepositoryHandler
|
||||
|
||||
//~--- 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
|
||||
*
|
||||
@@ -108,18 +91,11 @@ public class GitRepositoryHandler
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Override
|
||||
protected void postCreate(Repository repository, File directory)
|
||||
throws IOException, RepositoryException
|
||||
protected void create(Repository repository, File directory)
|
||||
throws RepositoryException, IOException
|
||||
{
|
||||
ExtendedCommand command = new ExtendedCommand(config.getGitBinary(),
|
||||
"update-server-info");
|
||||
|
||||
command.setWorkDirectory(directory);
|
||||
execute(command);
|
||||
command = new ExtendedCommand(config.getGitBinary(), "config", "--bool",
|
||||
"--add", "http.receivepack", "true");
|
||||
command.setWorkDirectory(directory);
|
||||
execute(command);
|
||||
new FileRepositoryBuilder().setGitDir(
|
||||
directory).readEnvironment().findGitDir().build().create(true);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
@@ -136,30 +112,8 @@ public class GitRepositoryHandler
|
||||
return GitConfig.class;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @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());
|
||||
}
|
||||
}
|
||||
/** Field description */
|
||||
private FileRepositoryBuilder builder = new FileRepositoryBuilder();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -81,7 +81,7 @@ public class GitWebPlugin implements ScmWebPlugin
|
||||
protected void configureServlets()
|
||||
{
|
||||
filter("/git/*").through(BasicAuthenticationFilter.class);
|
||||
serve("/git/*").with(GitCGIServlet.class);
|
||||
serve("/git/*").with(ScmGitServlet.class);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.web;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
@@ -36,15 +38,13 @@ package sonia.scm.web;
|
||||
import com.google.inject.Inject;
|
||||
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.util.IOUtil;
|
||||
import sonia.scm.web.cgi.AbstractCGIServlet;
|
||||
import sonia.scm.web.cgi.EnvList;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@@ -58,15 +58,9 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@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 */
|
||||
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";
|
||||
|
||||
/** 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 --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
@@ -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
|
||||
*
|
||||
@@ -203,7 +136,7 @@ public class GitCGIServlet extends AbstractCGIServlet
|
||||
|
||||
try
|
||||
{
|
||||
input = GitCGIServlet.class.getResourceAsStream(RESOURCE_GITINDEX);
|
||||
input = ScmGitServlet.class.getResourceAsStream(RESOURCE_GITINDEX);
|
||||
output = response.getOutputStream();
|
||||
IOUtil.copy(input, output);
|
||||
}
|
||||
@@ -228,10 +161,4 @@ public class GitCGIServlet extends AbstractCGIServlet
|
||||
{
|
||||
return request.getRequestURI().substring(request.getContextPath().length());
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
@Inject
|
||||
private GitRepositoryHandler repositoryHandler;
|
||||
}
|
||||
@@ -33,11 +33,6 @@ registerConfigPanel({
|
||||
xtype : 'configForm',
|
||||
title : 'Git Settings',
|
||||
items : [{
|
||||
xtype : 'textfield',
|
||||
fieldLabel : 'Git Binary',
|
||||
name : 'gitBinary',
|
||||
allowBlank : false
|
||||
},{
|
||||
xtype: 'textfield',
|
||||
name: 'repositoryDirectory',
|
||||
fieldLabel: 'Repository directory',
|
||||
@@ -47,11 +42,6 @@ registerConfigPanel({
|
||||
name: 'baseUrl',
|
||||
fieldLabel: 'Base URL',
|
||||
allowBlank : false
|
||||
},{
|
||||
xtype : 'textfield',
|
||||
fieldLabel : 'Git-Http-Backend',
|
||||
name : 'gitHttpBackend',
|
||||
allowBlank : false
|
||||
}],
|
||||
|
||||
onSubmit: function(values){
|
||||
|
||||
Reference in New Issue
Block a user