move core plugins back to main repository, because of a broken release management

This commit is contained in:
Sebastian Sdorra
2011-07-01 18:43:26 +02:00
parent 9aaf71f5ca
commit fa1d433a36
58 changed files with 9240 additions and 0 deletions

View File

@@ -0,0 +1,124 @@
/**
* 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.api.rest.resources;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Inject;
import com.google.inject.Singleton;
import sonia.scm.repository.GitConfig;
import sonia.scm.repository.GitRepositoryHandler;
//~--- JDK imports ------------------------------------------------------------
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
/**
*
* @author Sebastian Sdorra
*/
@Singleton
@Path("config/repositories/git")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public class GitConfigResource
{
/**
* Constructs ...
*
*
*
* @param repositoryHandler
*/
@Inject
public GitConfigResource(GitRepositoryHandler repositoryHandler)
{
this.repositoryHandler = repositoryHandler;
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@GET
public GitConfig getConfig()
{
GitConfig config = repositoryHandler.getConfig();
if (config == null)
{
config = new GitConfig();
repositoryHandler.setConfig(config);
}
return config;
}
//~--- set methods ----------------------------------------------------------
/**
* Method description
*
*
* @param uriInfo
* @param config
*
* @return
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Response setConfig(@Context UriInfo uriInfo, GitConfig config)
{
repositoryHandler.setConfig(config);
repositoryHandler.storeConfig();
return Response.created(uriInfo.getRequestUri()).build();
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private GitRepositoryHandler repositoryHandler;
}

View File

@@ -0,0 +1,305 @@
/**
* 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.repository;
//~--- non-JDK imports --------------------------------------------------------
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.treewalk.EmptyTreeIterator;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author Sebastian Sdorra
*/
public class GitChangesetViewer implements ChangesetViewer
{
/** Field description */
public static final int ID_LENGTH = 20;
/** the logger for GitChangesetViewer */
private static final Logger logger =
LoggerFactory.getLogger(GitChangesetViewer.class);
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param handler
* @param repository
*/
public GitChangesetViewer(GitRepositoryHandler handler, Repository repository)
{
this.handler = handler;
this.repository = repository;
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param start
* @param max
*
* @return
*/
@Override
public ChangesetPagingResult getChangesets(int start, int max)
{
ChangesetPagingResult changesets = null;
File directory = handler.getDirectory(repository);
org.eclipse.jgit.lib.Repository gr = null;
TreeWalk treeWalk = null;
try
{
gr = GitUtil.open(directory);
if (!gr.getAllRefs().isEmpty())
{
Git git = new Git(gr);
List<Changeset> changesetList = new ArrayList<Changeset>();
int counter = 0;
treeWalk = new TreeWalk(gr);
Map<ObjectId, String> tags = createTagMap(gr);
for (RevCommit commit : git.log().call())
{
if ((counter >= start) && (counter < start + max))
{
changesetList.add(createChangeset(treeWalk, tags, commit));
}
counter++;
}
changesets = new ChangesetPagingResult(counter, changesetList);
}
}
catch (NoHeadException ex)
{
logger.error("could not read changesets", ex);
}
catch (IOException ex)
{
logger.error("could not open repository", ex);
}
finally
{
GitUtil.release(treeWalk);
GitUtil.close(gr);
}
return changesets;
}
//~--- methods --------------------------------------------------------------
/**
* TODO: copy and rename
*
*
* @param modifications
* @param entry
*/
private void appendModification(Modifications modifications, DiffEntry entry)
{
switch (entry.getChangeType())
{
case ADD :
modifications.getAdded().add(entry.getNewPath());
break;
case MODIFY :
modifications.getModified().add(entry.getNewPath());
break;
case DELETE :
modifications.getRemoved().add(entry.getOldPath());
break;
}
}
/**
* Method description
*
*
*
* @param treeWalk
* @param tags
* @param commit
*
* @return
*
* @throws IOException
*/
private Changeset createChangeset(TreeWalk treeWalk,
Map<ObjectId, String> tags,
RevCommit commit)
throws IOException
{
String id = commit.getId().abbreviate(ID_LENGTH).name();
long date = GitUtil.getCommitTime(commit);
PersonIdent authorIndent = commit.getCommitterIdent();
Person author = new Person(authorIndent.getName(),
authorIndent.getEmailAddress());
String message = commit.getShortMessage();
Changeset changeset = new Changeset(id, date, author, message);
Modifications modifications = createModifications(treeWalk, commit);
if (modifications != null)
{
changeset.setModifications(modifications);
}
String tag = tags.get(commit.getId());
if (tag != null)
{
changeset.getTags().add(tag);
}
return changeset;
}
/**
* Method description
*
*
* @param treeWalk
* @param commit
*
* @return
*
* @throws IOException
*/
private Modifications createModifications(TreeWalk treeWalk, RevCommit commit)
throws IOException
{
Modifications modifications = null;
treeWalk.reset();
treeWalk.setRecursive(true);
if (commit.getParentCount() > 0)
{
treeWalk.addTree(commit.getParent(0).getTree());
}
else
{
treeWalk.addTree(new EmptyTreeIterator());
}
treeWalk.addTree(commit.getTree());
List<DiffEntry> entries = DiffEntry.scan(treeWalk);
for (DiffEntry e : entries)
{
if (!e.getOldId().equals(e.getNewId()))
{
if (modifications == null)
{
modifications = new Modifications();
}
appendModification(modifications, e);
}
}
return modifications;
}
/**
* Method description
*
*
* @param repository
*
* @return
*/
private Map<ObjectId,
String> createTagMap(org.eclipse.jgit.lib.Repository repository)
{
Map<ObjectId, String> tagMap = new HashMap<ObjectId, String>();
Map<String, Ref> tags = repository.getTags();
if (tags != null)
{
for (Map.Entry<String, Ref> e : tags.entrySet())
{
tagMap.put(e.getValue().getObjectId(), e.getKey());
}
}
return tagMap;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private GitRepositoryHandler handler;
/** Field description */
private Repository repository;
}

View File

@@ -0,0 +1,45 @@
/**
* 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.repository;
//~--- JDK imports ------------------------------------------------------------
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @author Sebastian Sdorra
*/
@XmlRootElement(name = "config")
public class GitConfig extends SimpleRepositoryConfig {}

View File

@@ -0,0 +1,338 @@
/**
* 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.repository;
//~--- non-JDK imports --------------------------------------------------------
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Sebastian Sdorra
*/
public class GitRepositoryBrowser implements RepositoryBrowser
{
/** the logger for GitRepositoryBrowser */
private static final Logger logger =
LoggerFactory.getLogger(GitRepositoryBrowser.class);
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param handler
* @param repository
*/
public GitRepositoryBrowser(GitRepositoryHandler handler,
Repository repository)
{
this.handler = handler;
this.repository = repository;
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param revision
* @param path
* @param output
*
*
* @throws IOException
* @throws RepositoryException
*/
@Override
public void getContent(String revision, String path, OutputStream output)
throws IOException, RepositoryException
{
File directory = handler.getDirectory(repository);
org.eclipse.jgit.lib.Repository repo = GitUtil.open(directory);
TreeWalk treeWalk = null;
RevWalk revWalk = null;
try
{
treeWalk = new TreeWalk(repo);
treeWalk.setRecursive(Util.nonNull(path).contains("/"));
ObjectId revId = GitUtil.getRevisionId(repo, revision);
revWalk = new RevWalk(repo);
RevCommit entry = revWalk.parseCommit(revId);
RevTree revTree = entry.getTree();
treeWalk.addTree(revTree);
treeWalk.setFilter(PathFilter.create(path));
if (treeWalk.next())
{
// Path exists
if (treeWalk.getFileMode(0).getObjectType() == Constants.OBJ_BLOB)
{
ObjectId blobId = treeWalk.getObjectId(0);
ObjectLoader loader = repo.open(blobId);
loader.copyTo(output);
}
else
{
// Not a blob, its something else (tree, gitlink)
throw new PathNotFoundException(path);
}
}
else
{
throw new PathNotFoundException(path);
}
}
finally
{
GitUtil.release(revWalk);
GitUtil.release(treeWalk);
GitUtil.close(repo);
}
}
/**
* Method description
*
*
* @param revision
* @param path
*
* @return
*
* @throws IOException
* @throws RepositoryException
*/
@Override
public BrowserResult getResult(String revision, String path)
throws IOException, RepositoryException
{
BrowserResult result = null;
File directory = handler.getDirectory(repository);
org.eclipse.jgit.lib.Repository repo = GitUtil.open(directory);
RevWalk revWalk = null;
TreeWalk treeWalk = null;
try
{
ObjectId revId = GitUtil.getRevisionId(repo, revision);
treeWalk = new TreeWalk(repo);
revWalk = new RevWalk(repo);
treeWalk.addTree(revWalk.parseTree(revId));
result = new BrowserResult();
List<FileObject> files = new ArrayList<FileObject>();
if (Util.isEmpty(path))
{
while (treeWalk.next())
{
files.add(createFileObject(repo, revId, treeWalk));
}
}
else
{
String[] parts = path.split("/");
int current = 0;
int limit = parts.length;
while (treeWalk.next())
{
String name = treeWalk.getNameString();
if (current >= limit)
{
String p = treeWalk.getPathString();
if (p.split("/").length > limit)
{
files.add(createFileObject(repo, revId, treeWalk));
}
}
else if (name.equalsIgnoreCase(parts[current]))
{
current++;
treeWalk.enterSubtree();
}
}
}
result.setFiles(files);
result.setRevision(revId.getName());
}
finally
{
GitUtil.close(repo);
GitUtil.release(revWalk);
GitUtil.release(treeWalk);
}
return result;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
*
*
* @param repo
* @param revId
* @param treeWalk
*
* @return
*
* @throws IOException
*/
private FileObject createFileObject(org.eclipse.jgit.lib.Repository repo,
ObjectId revId, TreeWalk treeWalk)
throws IOException
{
FileObject file = new FileObject();
String path = treeWalk.getPathString();
file.setName(treeWalk.getNameString());
file.setPath(path);
ObjectLoader loader = repo.open(treeWalk.getObjectId(0));
file.setDirectory(loader.getType() == Constants.OBJ_TREE);
file.setLength(loader.getSize());
// don't show message and date for directories to improve performance
if (!file.isDirectory())
{
RevCommit commit = getLatestCommit(repo, revId, path);
if (commit != null)
{
file.setLastModified(GitUtil.getCommitTime(commit));
file.setDescription(commit.getShortMessage());
}
else if (logger.isWarnEnabled())
{
logger.warn("could not find latest commit for {} on {}", path, revId);
}
}
return file;
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
*
* @param repo
* @param revId
* @param path
*
* @return
*/
private RevCommit getLatestCommit(org.eclipse.jgit.lib.Repository repo,
ObjectId revId, String path)
{
RevCommit result = null;
RevWalk walk = null;
try
{
walk = new RevWalk(repo);
walk.setTreeFilter(AndTreeFilter.create(PathFilter.create(path),
TreeFilter.ANY_DIFF));
RevCommit commit = walk.parseCommit(revId);
walk.markStart(commit);
result = Util.getFirst(walk);
}
catch (Exception ex)
{
logger.error("could not parse commit for file", ex);
}
finally
{
GitUtil.release(walk);
}
return result;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private GitRepositoryHandler handler;
/** Field description */
private Repository repository;
}

View File

@@ -0,0 +1,208 @@
/**
* 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.repository;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.jgit.storage.file.FileRepository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import sonia.scm.Type;
import sonia.scm.io.FileSystem;
import sonia.scm.plugin.ext.Extension;
import sonia.scm.store.StoreFactory;
import sonia.scm.util.AssertUtil;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
/**
*
* @author Sebastian Sdorra
*/
@Singleton
@Extension
public class GitRepositoryHandler
extends AbstractSimpleRepositoryHandler<GitConfig>
{
/** Field description */
public static final String TYPE_DISPLAYNAME = "Git";
/** Field description */
public static final String TYPE_NAME = "git";
/** Field description */
public static final Type TYPE = new Type(TYPE_NAME, TYPE_DISPLAYNAME);
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param storeFactory
* @param fileSystem
*/
@Inject
public GitRepositoryHandler(StoreFactory storeFactory, FileSystem fileSystem)
{
super(storeFactory, fileSystem);
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param repository
*
* @return
*/
@Override
public ChangesetViewer getChangesetViewer(Repository repository)
{
GitChangesetViewer changesetViewer = null;
AssertUtil.assertIsNotNull(repository);
String type = repository.getType();
AssertUtil.assertIsNotEmpty(type);
if (TYPE_NAME.equals(type))
{
changesetViewer = new GitChangesetViewer(this, repository);
}
else
{
throw new IllegalArgumentException("mercurial repository is required");
}
return changesetViewer;
}
/**
* Method description
*
*
* @param repository
*
* @return
*/
@Override
public RepositoryBrowser getRepositoryBrowser(Repository repository)
{
AssertUtil.assertIsNotNull(repository);
return new GitRepositoryBrowser(this, repository);
}
/**
* Method description
*
*
* @return
*/
@Override
public Type getType()
{
return TYPE;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param repository
* @param directory
*
* @throws IOException
* @throws RepositoryException
*/
@Override
protected void create(Repository repository, File directory)
throws RepositoryException, IOException
{
FileRepository fr = null;
try
{
fr = new FileRepositoryBuilder().setGitDir(
directory).readEnvironment().findGitDir().build();
fr.create(true);
}
finally
{
if (fr != null)
{
fr.close();
}
}
}
/**
* Method description
*
*
* @return
*/
@Override
protected GitConfig createInitialConfig()
{
return new GitConfig();
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@Override
protected Class<GitConfig> getConfigClass()
{
return GitConfig.class;
}
}

View File

@@ -0,0 +1,167 @@
/**
* 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.repository;
//~--- non-JDK imports --------------------------------------------------------
import java.io.File;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.util.FS;
/**
*
* @author Sebastian Sdorra
*/
public class GitUtil
{
/**
* Method description
*
*
* @param repo
*/
public static void close(org.eclipse.jgit.lib.Repository repo)
{
if (repo != null)
{
repo.close();
}
}
/**
* Method description
*
*
* @param walk
*/
public static void release(TreeWalk walk)
{
if (walk != null)
{
walk.release();
}
}
/**
* Method description
*
*
* @param walk
*/
public static void release(RevWalk walk)
{
if (walk != null)
{
walk.release();
}
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param commit
*
* @return
*/
public static long getCommitTime(RevCommit commit)
{
long date = commit.getCommitTime();
date = date * 1000;
return date;
}
/**
* Method description
*
*
* @param directory
*
* @return
*
* @throws IOException
*/
public static org.eclipse.jgit.lib.Repository open(File directory)
throws IOException
{
return RepositoryCache.open(RepositoryCache.FileKey.lenient(directory,
FS.DETECTED), true);
}
/**
* Method description
*
*
* @param repo
* @param revision
*
* @return
*
* @throws IOException
*/
public static ObjectId getRevisionId(org.eclipse.jgit.lib.Repository repo,
String revision)
throws IOException
{
ObjectId revId = null;
if (Util.isNotEmpty(revision))
{
revId = repo.resolve(revision);
}
else
{
revId = repo.resolve(Constants.HEAD);
}
return revId;
}
}

View File

@@ -0,0 +1,121 @@
/**
* 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 com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import sonia.scm.repository.GitRepositoryHandler;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.web.filter.RegexPermissionFilter;
import sonia.scm.web.security.WebSecurityContext;
//~--- JDK imports ------------------------------------------------------------
import javax.servlet.http.HttpServletRequest;
/**
*
* @author Sebastian Sdorra
*/
@Singleton
public class GitPermissionFilter extends RegexPermissionFilter
{
/** Field description */
public static final String PARAMETER_SERVICE = "service";
/** Field description */
public static final String PARAMETER_VALUE_RECEIVE = "git-receive-pack";
/** Field description */
public static final String URI_RECEIVE_PACK = "git-receive-pack";
/** Field description */
public static final String URI_REF_INFO = "/info/refs";
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
*
* @param securityContextProvider
* @param repositoryManager
*/
@Inject
public GitPermissionFilter(
Provider<WebSecurityContext> securityContextProvider,
RepositoryManager repositoryManager)
{
super(securityContextProvider, repositoryManager);
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@Override
protected String getType()
{
return GitRepositoryHandler.TYPE_NAME;
}
/**
* Method description
*
*
* @param request
*
* @return
*/
@Override
protected boolean isWriteRequest(HttpServletRequest request)
{
String uri = request.getRequestURI();
return uri.endsWith(URI_RECEIVE_PACK)
|| (uri.endsWith(URI_REF_INFO)
&& PARAMETER_VALUE_RECEIVE.equals(
request.getParameter(PARAMETER_SERVICE)));
}
}

View File

@@ -0,0 +1,210 @@
/**
* 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.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
import org.eclipse.jgit.transport.resolver.RepositoryResolver;
import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
import org.eclipse.jgit.util.FS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.GitConfig;
import sonia.scm.repository.GitRepositoryHandler;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
/**
*
* @author Sebastian Sdorra
*/
public class GitRepositoryResolver
implements RepositoryResolver<HttpServletRequest>
{
/** the logger for GitRepositoryResolver */
private static final Logger logger =
LoggerFactory.getLogger(GitRepositoryResolver.class);
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
*
* @param handler
*/
public GitRepositoryResolver(GitRepositoryHandler handler)
{
this.handler = handler;
}
//~--- 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
{
GitConfig config = handler.getConfig();
if (config.isValid())
{
File gitdir = new File(config.getRepositoryDirectory(), repositoryName);
if (logger.isDebugEnabled())
{
logger.debug("try to open git repository at {}", gitdir);
}
if (!gitdir.exists())
{
throw new RepositoryNotFoundException(repositoryName);
}
repository = RepositoryCache.open(FileKey.lenient(gitdir, FS.DETECTED),
true);
}
else
{
if (logger.isWarnEnabled())
{
logger.warn("gitconfig is not valid, the service is not available");
}
throw new ServiceNotEnabledException();
}
}
catch (RuntimeException e)
{
throw new RepositoryNotFoundException(repositoryName, e);
}
catch (IOException e)
{
throw new RepositoryNotFoundException(repositoryName, e);
}
return repository;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private GitRepositoryHandler handler;
}

View File

@@ -0,0 +1,205 @@
/**
* 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.apache.commons.lang.StringEscapeUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import sonia.scm.io.RegexResourceProcessor;
import sonia.scm.io.ResourceProcessor;
import sonia.scm.util.IOUtil;
import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
/**
*
* @author Sebastian Sdorra
*/
public class GitRepositoryViewer
{
/** Field description */
public static final String MIMETYPE_HTML = "text/html";
/** Field description */
public static final String RESOURCE_GITINDEX = "/sonia/scm/git.index.html";
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param response
* @param repository
* @param repositoryName
*
* @throws IOException
* @throws NoHeadException
* @throws ServletException
*/
public void handleRequest(HttpServletResponse response,
Repository repository, String repositoryName)
throws IOException, ServletException, NoHeadException
{
response.setContentType(MIMETYPE_HTML);
ResourceProcessor processor = new RegexResourceProcessor();
processor.addVariable("name", repositoryName);
StringBuilder sb = new StringBuilder();
if (!repository.getAllRefs().isEmpty())
{
Git git = new Git(repository);
int c = 0;
for (RevCommit commit : git.log().call())
{
appendCommit(sb, commit);
c++;
if (c > logSize)
{
break;
}
}
}
processor.addVariable("commits", sb.toString());
BufferedReader reader = null;
PrintWriter writer = null;
try
{
reader = new BufferedReader(
new InputStreamReader(
GitRepositoryViewer.class.getResourceAsStream(
RESOURCE_GITINDEX)));
writer = response.getWriter();
processor.process(reader, writer);
}
finally
{
IOUtil.close(reader);
IOUtil.close(writer);
}
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
public int getLogSize()
{
return logSize;
}
//~--- set methods ----------------------------------------------------------
/**
* Method description
*
*
* @param logSize
*/
public void setLogSize(int logSize)
{
this.logSize = logSize;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param sb
* @param commit
*/
private void appendCommit(StringBuilder sb, RevCommit commit)
{
sb.append("<tr><td class=\"small\">");
long time = commit.getCommitTime();
sb.append(Util.formatDate(new Date(time * 1000)));
sb.append("</td><td class=\"small\">");
PersonIdent person = commit.getCommitterIdent();
if (person != null)
{
String name = person.getName();
if (Util.isNotEmpty(name))
{
sb.append(StringEscapeUtils.escapeHtml(name));
}
}
sb.append("</td><td>");
sb.append(StringEscapeUtils.escapeHtml(commit.getFullMessage()));
sb.append("</td></tr>");
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private int logSize = 25;
}

View File

@@ -0,0 +1,67 @@
/**
* 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 com.google.inject.servlet.ServletModule;
import sonia.scm.plugin.ext.Extension;
import sonia.scm.web.filter.BasicAuthenticationFilter;
/**
*
* @author Sebastian Sdorra
*/
@Extension
public class GitServletModule extends ServletModule
{
/** Field description */
public static final String PATTERN_GIT = "/git/*";
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*/
@Override
protected void configureServlets()
{
filter(PATTERN_GIT).through(BasicAuthenticationFilter.class);
filter(PATTERN_GIT).through(GitPermissionFilter.class);
serve(PATTERN_GIT).with(ScmGitServlet.class);
}
}

View File

@@ -0,0 +1,176 @@
/**
* 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 com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.jgit.http.server.GitServlet;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.resolver.RepositoryResolver;
import sonia.scm.repository.GitRepositoryHandler;
import sonia.scm.util.HttpUtil;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @author Sebastian Sdorra
*/
@Singleton
public class ScmGitServlet extends GitServlet
{
/** Field description */
public static final String REGEX_GITHTTPBACKEND =
"(?x)^/git/(.*/(HEAD|info/refs|objects/(info/[^/]+|[0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\\.(pack|idx))|git-(upload|receive)-pack))$";
/** Field description */
private static final long serialVersionUID = -7712897339207470674L;
/** Field description */
private static final Pattern REGEX_REPOSITORYNAME =
Pattern.compile("/git/([^/]+)/?.*");
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param handler
*/
@Inject
public ScmGitServlet(GitRepositoryHandler handler)
{
resolver = new GitRepositoryResolver(handler);
setRepositoryResolver(resolver);
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param request
* @param response
*
* @throws IOException
* @throws ServletException
*/
@Override
protected void service(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
String uri = HttpUtil.getStrippedURI(request);
if (uri.matches(REGEX_GITHTTPBACKEND))
{
super.service(request, response);
}
else
{
printGitInformation(request, response);
}
}
/**
* Method description
*
*
*
* @param request
* @param response
*
* @throws IOException
* @throws ServletException
*/
private void printGitInformation(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
String uri = HttpUtil.getStrippedURI(request);
Matcher m = REGEX_REPOSITORYNAME.matcher(uri);
String name = null;
Repository repository = null;
try
{
if (m.matches())
{
name = m.group(1);
repository = resolver.open(request, name);
}
if (repository != null)
{
new GitRepositoryViewer().handleRequest(response, repository, name);
}
else
{
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
catch (Exception ex)
{
throw new ServletException(ex);
}
finally
{
if (repository != null)
{
repository.close();
}
}
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private RepositoryResolver<HttpServletRequest> resolver;
}