mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-01 11:05:56 +01:00
move core plugins back to main repository, because of a broken release management
This commit is contained in:
@@ -18,6 +18,10 @@
|
||||
<modules>
|
||||
<module>scm-activedirectory-auth-plugin</module>
|
||||
<module>scm-auth-ldap-plugin</module>
|
||||
<!-- core plugins -->
|
||||
<module>scm-hg-plugin</module>
|
||||
<module>scm-git-plugin</module>
|
||||
<module>scm-svn-plugin</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
|
||||
86
scm-plugins/scm-git-plugin/pom.xml
Normal file
86
scm-plugins/scm-git-plugin/pom.xml
Normal file
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<artifactId>scm-plugins</artifactId>
|
||||
<groupId>sonia.scm.plugins</groupId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>sonia.scm.plugins</groupId>
|
||||
<artifactId>scm-git-plugin</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
<name>scm-git-plugin</name>
|
||||
<url>https://bitbucket.org/sdorra/scm-manager</url>
|
||||
<description>Plugin for the version control system Git</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>${servlet.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
<artifactId>org.eclipse.jgit</artifactId>
|
||||
<version>${jgit.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jsch</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
<artifactId>org.eclipse.jgit.http.server</artifactId>
|
||||
<version>${jgit.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
|
||||
<!-- test scope -->
|
||||
|
||||
<dependency>
|
||||
<groupId>sonia.scm</groupId>
|
||||
<artifactId>scm-test</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<jgit.version>1.0.0.201106090707-r</jgit.version>
|
||||
</properties>
|
||||
|
||||
<!-- for jgit -->
|
||||
|
||||
<repositories>
|
||||
|
||||
<repository>
|
||||
<id>jgit-repository</id>
|
||||
<url>http://download.eclipse.org/jgit/maven</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>maven.scm-manager.org</id>
|
||||
<name>scm-manager release repository</name>
|
||||
<url>http://maven.scm-manager.org/nexus/content/groups/public</url>
|
||||
</repository>
|
||||
|
||||
</repositories>
|
||||
|
||||
</project>
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 {}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
|
||||
-->
|
||||
|
||||
<!--
|
||||
Document : plugin.xml
|
||||
Created on : October 12, 2010, 8:29 AM
|
||||
Author : sdorra
|
||||
Description:
|
||||
Purpose of the document follows.
|
||||
-->
|
||||
|
||||
<plugin>
|
||||
|
||||
<information>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>${project.artifactId}</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<name>${project.name}</name>
|
||||
<description>${project.description}</description>
|
||||
<author>Sebastian Sdorra</author>
|
||||
<url>${project.url}</url>
|
||||
</information>
|
||||
|
||||
<conditions>
|
||||
<min-version>1.1</min-version>
|
||||
</conditions>
|
||||
|
||||
<resources>
|
||||
<script>/sonia/scm/git.config.js</script>
|
||||
</resources>
|
||||
|
||||
</plugin>
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
Ext.ns("Sonia.git");
|
||||
|
||||
Sonia.git.ConfigPanel = Ext.extend(Sonia.config.SimpleConfigForm, {
|
||||
|
||||
// labels
|
||||
titleText: 'Git Settings',
|
||||
repositoryDirectoryText: 'Repository directory',
|
||||
|
||||
// helpTexts
|
||||
repositoryDirectoryHelpText: 'Location of the Git repositories.',
|
||||
|
||||
initComponent: function(){
|
||||
|
||||
var config = {
|
||||
title : this.titleText,
|
||||
configUrl: restUrl + 'config/repositories/git.json',
|
||||
items : [{
|
||||
xtype: 'textfield',
|
||||
name: 'repositoryDirectory',
|
||||
fieldLabel: this.repositoryDirectoryText,
|
||||
helpText: this.repositoryDirectoryHelpText,
|
||||
allowBlank : false
|
||||
}]
|
||||
}
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
Sonia.git.ConfigPanel.superclass.initComponent.apply(this, arguments);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Ext.reg("gitConfigPanel", Sonia.git.ConfigPanel);
|
||||
|
||||
// i18n
|
||||
|
||||
if ( i18n != null && i18n.country == 'de' ){
|
||||
|
||||
Ext.override(Sonia.git.ConfigPanel, {
|
||||
|
||||
// labels
|
||||
titleText: 'Git Einstellungen',
|
||||
repositoryDirectoryText: 'Repository-Verzeichnis',
|
||||
|
||||
// helpTexts
|
||||
repositoryDirectoryHelpText: 'Verzeichnis der Git-Repositories.'
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// register information panel
|
||||
|
||||
initCallbacks.push(function(main){
|
||||
main.registerInfoPanel('git', {
|
||||
checkoutTemplate: 'git clone <a href="{0}" target="_blank">{0}</a>',
|
||||
xtype: 'repositoryExtendedInfoPanel'
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
// register panel
|
||||
|
||||
registerConfigPanel({
|
||||
xtype : 'gitConfigPanel'
|
||||
});
|
||||
@@ -0,0 +1,114 @@
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>SCM :: Manager - Git Repository - ${name}</title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
background-color: #ffffff;
|
||||
margin: 10px;
|
||||
color: #202020;
|
||||
font-family: Verdana,Helvetica,Arial,sans-serif;
|
||||
font-size: 75%;
|
||||
}
|
||||
h1, h2, h3, h4, h5 {
|
||||
font-family: Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
|
||||
font-weight: bold;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
color: #D20005;
|
||||
}
|
||||
h1 {
|
||||
font-size: 18px;
|
||||
border-bottom: 1px solid #AFAFAF;
|
||||
}
|
||||
h2 {
|
||||
font-size: 14px;
|
||||
border-bottom: 1px solid #AFAFAF;
|
||||
}
|
||||
a:link, a:visited {
|
||||
color: #045491;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:link:hover, a:visited:hover {
|
||||
color: #045491;
|
||||
font-weight: bold;
|
||||
text-decoration: underline;
|
||||
}
|
||||
table {
|
||||
border: 0 none;
|
||||
border-collapse: collapse;
|
||||
font-size: 100%;
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
td, th {
|
||||
padding: 3px;
|
||||
vertical-align: top;
|
||||
border: 1px solid #CCCCCC;
|
||||
text-align: left;
|
||||
}
|
||||
.small {
|
||||
width: 20%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>SCM :: Manager - Git Repository - ${name}</h1>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="small">Time</th>
|
||||
<th class="small">Author</th>
|
||||
<th>Message</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${commits}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>Git Informations</h2>
|
||||
<ul>
|
||||
<li><a href="http://git-scm.com/" target="_blank">Git Homepage</a></li>
|
||||
<li><a href="http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html" target="_blank">Git Tutorial</a></li>
|
||||
<li><a href="http://www.kernel.org/pub/software/scm/git/docs/user-manual.html" target="_blank">Git User's Manual</a></li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* 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 sonia.scm.io.DefaultFileSystem;
|
||||
import sonia.scm.store.StoreFactory;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class GitRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param directory
|
||||
*/
|
||||
@Override
|
||||
protected void checkDirectory(File directory)
|
||||
{
|
||||
File head = new File(directory, "HEAD");
|
||||
|
||||
assertTrue(head.exists());
|
||||
assertTrue(head.isFile());
|
||||
|
||||
File config = new File(directory, "config");
|
||||
|
||||
assertTrue(config.exists());
|
||||
assertTrue(config.isFile());
|
||||
|
||||
File refs = new File(directory, "refs");
|
||||
|
||||
assertTrue(refs.exists());
|
||||
assertTrue(refs.isDirectory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param factory
|
||||
* @param directory
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected RepositoryHandler createRepositoryHandler(StoreFactory factory,
|
||||
File directory)
|
||||
{
|
||||
GitRepositoryHandler repositoryHandler = new GitRepositoryHandler(factory,
|
||||
new DefaultFileSystem());
|
||||
|
||||
repositoryHandler.init(contextProvider);
|
||||
|
||||
GitConfig config = new GitConfig();
|
||||
|
||||
config.setRepositoryDirectory(directory);
|
||||
repositoryHandler.setConfig(config);
|
||||
|
||||
return repositoryHandler;
|
||||
}
|
||||
}
|
||||
56
scm-plugins/scm-hg-plugin/pom.xml
Normal file
56
scm-plugins/scm-hg-plugin/pom.xml
Normal file
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>sonia.scm.plugins</groupId>
|
||||
<artifactId>scm-plugins</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>sonia.scm.plugins</groupId>
|
||||
<artifactId>scm-hg-plugin</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
<name>scm-hg-plugin</name>
|
||||
<url>https://bitbucket.org/sdorra/scm-manager</url>
|
||||
<description>Plugin for the version control system Mercurial</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>${servlet.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-json</artifactId>
|
||||
<version>${jersey.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- test scope -->
|
||||
|
||||
<dependency>
|
||||
<groupId>sonia.scm</groupId>
|
||||
<artifactId>scm-test</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
|
||||
<repository>
|
||||
<id>maven.scm-manager.org</id>
|
||||
<name>scm-manager release repository</name>
|
||||
<url>http://maven.scm-manager.org/nexus/content/groups/public</url>
|
||||
</repository>
|
||||
|
||||
</repositories>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,351 @@
|
||||
/**
|
||||
* 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.SCMContext;
|
||||
import sonia.scm.cache.CacheManager;
|
||||
import sonia.scm.installer.HgInstallerFactory;
|
||||
import sonia.scm.installer.HgPackage;
|
||||
import sonia.scm.installer.HgPackageReader;
|
||||
import sonia.scm.installer.HgPackages;
|
||||
import sonia.scm.net.HttpClient;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.web.HgWebConfigWriter;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
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;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Singleton
|
||||
@Path("config/repositories/hg")
|
||||
public class HgConfigResource
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param client
|
||||
* @param handler
|
||||
* @param cacheManager
|
||||
*/
|
||||
@Inject
|
||||
public HgConfigResource(HttpClient client, HgRepositoryHandler handler,
|
||||
CacheManager cacheManager)
|
||||
{
|
||||
this.client = client;
|
||||
this.handler = handler;
|
||||
this.pkgReader = new HgPackageReader(cacheManager);
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param uriInfo
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@POST
|
||||
@Path("auto-configuration")
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public HgConfig autoConfiguration(@Context UriInfo uriInfo)
|
||||
{
|
||||
return autoConfiguration(uriInfo, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param uriInfo
|
||||
* @param config
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@POST
|
||||
@Path("auto-configuration")
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public HgConfig autoConfiguration(@Context UriInfo uriInfo, HgConfig config)
|
||||
{
|
||||
if (config == null)
|
||||
{
|
||||
config = new HgConfig();
|
||||
}
|
||||
|
||||
handler.doAutoConfiguration(config);
|
||||
|
||||
return handler.getConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@POST
|
||||
@Path("packages/{pkgId}")
|
||||
public Response installPackage(@PathParam("pkgId") String id)
|
||||
{
|
||||
Response response = null;
|
||||
HgPackage pkg = pkgReader.getPackage(id);
|
||||
|
||||
if (pkg != null)
|
||||
{
|
||||
if (HgInstallerFactory.createInstaller().installPackage(client, handler,
|
||||
SCMContext.getContext().getBaseDirectory(), pkg))
|
||||
{
|
||||
response = Response.noContent().build();
|
||||
}
|
||||
else
|
||||
{
|
||||
response =
|
||||
Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response = Response.status(Response.Status.NOT_FOUND).build();
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public HgConfig getConfig()
|
||||
{
|
||||
HgConfig config = handler.getConfig();
|
||||
|
||||
if (config == null)
|
||||
{
|
||||
config = new HgConfig();
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Path("installations/hg")
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public InstallationsResponse getHgInstallations()
|
||||
{
|
||||
List<String> installations =
|
||||
HgInstallerFactory.createInstaller().getHgInstallations();
|
||||
|
||||
return new InstallationsResponse(installations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Path("packages")
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public HgPackages getPackages()
|
||||
{
|
||||
return pkgReader.getPackages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Path("installations/python")
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public InstallationsResponse getPythonInstallations()
|
||||
{
|
||||
List<String> installations =
|
||||
HgInstallerFactory.createInstaller().getPythonInstallations();
|
||||
|
||||
return new InstallationsResponse(installations);
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param uriInfo
|
||||
* @param config
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public Response setConfig(@Context UriInfo uriInfo, HgConfig config)
|
||||
throws IOException
|
||||
{
|
||||
handler.setConfig(config);
|
||||
handler.storeConfig();
|
||||
new HgWebConfigWriter(config).write();
|
||||
|
||||
return Response.created(uriInfo.getRequestUri()).build();
|
||||
}
|
||||
|
||||
//~--- inner classes --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class description
|
||||
*
|
||||
*
|
||||
* @version Enter version here..., 11/04/25
|
||||
* @author Enter your name here...
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlRootElement(name = "installations")
|
||||
public static class InstallationsResponse
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*/
|
||||
public InstallationsResponse() {}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param paths
|
||||
*/
|
||||
public InstallationsResponse(List<String> paths)
|
||||
{
|
||||
this.paths = paths;
|
||||
}
|
||||
|
||||
//~--- get methods --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<String> getPaths()
|
||||
{
|
||||
return paths;
|
||||
}
|
||||
|
||||
//~--- set methods --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param paths
|
||||
*/
|
||||
public void setPaths(List<String> paths)
|
||||
{
|
||||
this.paths = paths;
|
||||
}
|
||||
|
||||
//~--- fields -------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "path")
|
||||
private List<String> paths;
|
||||
}
|
||||
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private HttpClient client;
|
||||
|
||||
/** Field description */
|
||||
private HgRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private HgPackageReader pkgReader;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* 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.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.net.HttpClient;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public abstract class AbstractHgInstaller implements HgInstaller
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String DIRECTORY_REPOSITORY = "repositories";
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public void install(File baseDirectory, HgConfig config) throws IOException
|
||||
{
|
||||
File repoDirectory = new File(
|
||||
baseDirectory,
|
||||
DIRECTORY_REPOSITORY.concat(File.separator).concat(
|
||||
HgRepositoryHandler.TYPE_NAME));
|
||||
|
||||
IOUtil.mkdirs(repoDirectory);
|
||||
config.setRepositoryDirectory(repoDirectory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param client
|
||||
* @param handler
|
||||
* @param baseDirectory
|
||||
* @param pkg
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean installPackage(HttpClient client, HgRepositoryHandler handler,
|
||||
File baseDirectory, HgPackage pkg)
|
||||
{
|
||||
return new HgPackageInstaller(client, handler, baseDirectory,
|
||||
pkg).install();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* 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.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.net.HttpClient;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public interface HgInstaller
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void install(File baseDirectory, HgConfig config) throws IOException;
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param client
|
||||
* @param handler
|
||||
* @param baseDirectory
|
||||
* @param pkg
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean installPackage(HttpClient client, HgRepositoryHandler handler,
|
||||
File baseDirectory, HgPackage pkg);
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void update(File baseDirectory, HgConfig config) throws IOException;
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<String> getHgInstallations();
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<String> getPythonInstallations();
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 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.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.util.SystemUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgInstallerFactory
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static HgInstaller createInstaller()
|
||||
{
|
||||
HgInstaller installer = null;
|
||||
|
||||
if (SystemUtil.isWindows())
|
||||
{
|
||||
installer = new WindowsHgInstaller();
|
||||
}
|
||||
else
|
||||
{
|
||||
installer = new UnixHgInstaller();
|
||||
}
|
||||
|
||||
return installer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
/**
|
||||
* 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.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.repository.HgConfig;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@XmlRootElement(name = "package")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class HgPackage
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getArch()
|
||||
{
|
||||
return arch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public HgConfig getHgConfigTemplate()
|
||||
{
|
||||
return hgConfigTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getHgVersion()
|
||||
{
|
||||
return hgVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPlatform()
|
||||
{
|
||||
return platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPythonVersion()
|
||||
{
|
||||
return pythonVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public long getSize()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getUrl()
|
||||
{
|
||||
return url;
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param arch
|
||||
*/
|
||||
public void setArch(String arch)
|
||||
{
|
||||
this.arch = arch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param hgConfigTemplate
|
||||
*/
|
||||
public void setHgConfigTemplate(HgConfig hgConfigTemplate)
|
||||
{
|
||||
this.hgConfigTemplate = hgConfigTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param hgVersion
|
||||
*/
|
||||
public void setHgVersion(String hgVersion)
|
||||
{
|
||||
this.hgVersion = hgVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
public void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param platform
|
||||
*/
|
||||
public void setPlatform(String platform)
|
||||
{
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param pythonVersion
|
||||
*/
|
||||
public void setPythonVersion(String pythonVersion)
|
||||
{
|
||||
this.pythonVersion = pythonVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param size
|
||||
*/
|
||||
public void setSize(long size)
|
||||
{
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
public void setUrl(String url)
|
||||
{
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private String arch;
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "hg-config-template")
|
||||
private HgConfig hgConfigTemplate;
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "hg-version")
|
||||
private String hgVersion;
|
||||
|
||||
/** Field description */
|
||||
private String id;
|
||||
|
||||
/** Field description */
|
||||
private String platform;
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "python-version")
|
||||
private String pythonVersion;
|
||||
|
||||
/** Field description */
|
||||
private long size;
|
||||
|
||||
/** Field description */
|
||||
private String url;
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
/**
|
||||
* 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.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.io.ZipUnArchiver;
|
||||
import sonia.scm.net.HttpClient;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgPackageInstaller implements Runnable
|
||||
{
|
||||
|
||||
/** the logger for HgPackageInstaller */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(HgPackageInstaller.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param client
|
||||
* @param handler
|
||||
* @param baseDirectory
|
||||
* @param pkg
|
||||
*/
|
||||
public HgPackageInstaller(HttpClient client, HgRepositoryHandler handler,
|
||||
File baseDirectory, HgPackage pkg)
|
||||
{
|
||||
this.client = client;
|
||||
this.handler = handler;
|
||||
this.baseDirectory = baseDirectory;
|
||||
this.pkg = pkg;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean install()
|
||||
{
|
||||
boolean success = false;
|
||||
File downloadedFile = downloadFile();
|
||||
|
||||
if ((downloadedFile != null) && downloadedFile.exists())
|
||||
{
|
||||
File directory = extractPackage(downloadedFile);
|
||||
|
||||
if ((directory != null) && directory.exists())
|
||||
{
|
||||
updateConfig(directory);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (!install())
|
||||
{
|
||||
logger.error("installation of pkg {} failed", pkg.getId());
|
||||
}
|
||||
else if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info("successfully installed pkg {}", pkg.getId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private File downloadFile()
|
||||
{
|
||||
File file = null;
|
||||
InputStream input = null;
|
||||
OutputStream output = null;
|
||||
|
||||
try
|
||||
{
|
||||
file = File.createTempFile("scm-hg-", ".pkg");
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("download package to {}", file.getAbsolutePath());
|
||||
}
|
||||
|
||||
// TODO error handling
|
||||
input = client.get(pkg.getUrl()).getContent();
|
||||
output = new FileOutputStream(file);
|
||||
IOUtil.copy(input, output);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.error("could not downlaod file ".concat(pkg.getUrl()), ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(input);
|
||||
IOUtil.close(output);
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param file
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private File extractPackage(File file)
|
||||
{
|
||||
File directory = new File(baseDirectory,
|
||||
"pkg".concat(File.separator).concat(pkg.getId()));
|
||||
|
||||
IOUtil.mkdirs(directory);
|
||||
|
||||
try
|
||||
{
|
||||
IOUtil.extract(file, directory, ZipUnArchiver.EXTENSION);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
directory = null;
|
||||
logger.error("could not extract pacakge ".concat(pkg.getId()), ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
// delete temp file
|
||||
try
|
||||
{
|
||||
IOUtil.delete(file, true);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.error(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param directory
|
||||
*/
|
||||
private void updateConfig(File directory)
|
||||
{
|
||||
String path = directory.getAbsolutePath();
|
||||
HgConfig template = pkg.getHgConfigTemplate();
|
||||
HgConfig config = handler.getConfig();
|
||||
|
||||
config.setHgBinary(getTemplateValue(template.getHgBinary(), path));
|
||||
config.setPythonBinary(getTemplateValue(template.getPythonBinary(), path));
|
||||
config.setPythonPath(getTemplateValue(template.getPythonPath(), path));
|
||||
config.setUseOptimizedBytecode(template.isUseOptimizedBytecode());
|
||||
handler.storeConfig();
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param template
|
||||
* @param path
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getTemplateValue(String template, String path)
|
||||
{
|
||||
String result = null;
|
||||
|
||||
if (template != null)
|
||||
{
|
||||
result = MessageFormat.format(template, path);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private File baseDirectory;
|
||||
|
||||
/** Field description */
|
||||
private HttpClient client;
|
||||
|
||||
/** Field description */
|
||||
private HgRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private HgPackage pkg;
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
/**
|
||||
* 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.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.PlatformType;
|
||||
import sonia.scm.cache.Cache;
|
||||
import sonia.scm.cache.CacheManager;
|
||||
import sonia.scm.util.IOUtil;
|
||||
import sonia.scm.util.SystemUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import javax.xml.bind.JAXB;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgPackageReader
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String CACHENAME = "sonia.scm.hg.packages";
|
||||
|
||||
/** Field description */
|
||||
public static final String PACKAGEURL =
|
||||
"http://download.scm-manager.org/pkg/mercurial/packages.xml.gz";
|
||||
|
||||
/** the logger for HgPackageReader */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(HgPackageReader.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param cacheManager
|
||||
*/
|
||||
public HgPackageReader(CacheManager cacheManager)
|
||||
{
|
||||
cache = cacheManager.getCache(String.class, HgPackages.class, CACHENAME);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public HgPackage getPackage(String id)
|
||||
{
|
||||
HgPackage pkg = null;
|
||||
|
||||
for (HgPackage p : getPackages())
|
||||
{
|
||||
if (id.equals(p.getId()))
|
||||
{
|
||||
pkg = p;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pkg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public HgPackages getPackages()
|
||||
{
|
||||
HgPackages packages = cache.get(HgPackages.class.getName());
|
||||
|
||||
if (packages == null)
|
||||
{
|
||||
packages = getRemptePackages();
|
||||
filterPackage(packages);
|
||||
cache.put(HgPackages.class.getName(), packages);
|
||||
}
|
||||
|
||||
return packages;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param packages
|
||||
*/
|
||||
private void filterPackage(HgPackages packages)
|
||||
{
|
||||
List<HgPackage> pkgList = new ArrayList<HgPackage>();
|
||||
|
||||
for (HgPackage pkg : packages)
|
||||
{
|
||||
boolean add = true;
|
||||
|
||||
if (Util.isNotEmpty(pkg.getPlatform()))
|
||||
{
|
||||
PlatformType pt = PlatformType.createPlatformType(pkg.getPlatform());
|
||||
|
||||
if (SystemUtil.getPlatform().getType() != pt)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("reject package {}, because of wrong platform {}",
|
||||
pkg.getId(), pkg.getPlatform());
|
||||
}
|
||||
|
||||
add = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (add && Util.isNotEmpty(pkg.getArch()))
|
||||
{
|
||||
if (!SystemUtil.getArch().equals(pkg.getArch()))
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("reject package {}, because of wrong arch {}",
|
||||
pkg.getId(), pkg.getArch());
|
||||
}
|
||||
|
||||
add = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (add)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("added HgPackage {}", pkg.getId());
|
||||
}
|
||||
|
||||
pkgList.add(pkg);
|
||||
}
|
||||
}
|
||||
|
||||
packages.setPackages(pkgList);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private HgPackages getRemptePackages()
|
||||
{
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info("fetch HgPackages from {}", PACKAGEURL);
|
||||
}
|
||||
|
||||
HgPackages packages = null;
|
||||
InputStream input = null;
|
||||
|
||||
try
|
||||
{
|
||||
URL url = new URL(PACKAGEURL);
|
||||
|
||||
if (PACKAGEURL.endsWith(".gz"))
|
||||
{
|
||||
input = new GZIPInputStream(url.openStream());
|
||||
}
|
||||
else
|
||||
{
|
||||
input = url.openStream();
|
||||
}
|
||||
|
||||
packages = JAXB.unmarshal(input, HgPackages.class);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.error("could not read HgPackages from {}", PACKAGEURL);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(input);
|
||||
}
|
||||
|
||||
if (packages == null)
|
||||
{
|
||||
packages = new HgPackages();
|
||||
packages.setPackages(new ArrayList<HgPackage>());
|
||||
}
|
||||
|
||||
return packages;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Cache<String, HgPackages> cache;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* 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.installer;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@XmlRootElement(name = "packages")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class HgPackages implements Iterable<HgPackage>
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Iterator<HgPackage> iterator()
|
||||
{
|
||||
return packages.iterator();
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<HgPackage> getPackages()
|
||||
{
|
||||
return packages;
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param packages
|
||||
*/
|
||||
public void setPackages(List<HgPackage> packages)
|
||||
{
|
||||
this.packages = packages;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "package")
|
||||
private List<HgPackage> packages;
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* 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.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.util.IOUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class UnixHgInstaller extends AbstractHgInstaller
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String COMMAND_HG = "hg";
|
||||
|
||||
/** Field description */
|
||||
public static final String COMMAND_PYTHON = "python";
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public void install(File baseDirectory, HgConfig config) throws IOException
|
||||
{
|
||||
super.install(baseDirectory, config);
|
||||
|
||||
// search mercurial (hg)
|
||||
|
||||
if (Util.isEmpty(config.getHgBinary()))
|
||||
{
|
||||
String hg = IOUtil.search(COMMAND_HG);
|
||||
|
||||
if (Util.isNotEmpty(hg))
|
||||
{
|
||||
config.setHgBinary(hg);
|
||||
|
||||
// search python in the same folder
|
||||
File hgFile = new File(hg);
|
||||
|
||||
if (hgFile.exists())
|
||||
{
|
||||
File pythonFile = new File(hgFile.getParentFile(), COMMAND_PYTHON);
|
||||
|
||||
if (pythonFile.exists())
|
||||
{
|
||||
config.setPythonBinary(pythonFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// search python
|
||||
|
||||
if (Util.isEmpty(config.getPythonBinary()))
|
||||
{
|
||||
config.setPythonBinary(IOUtil.search(COMMAND_PYTHON));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
*/
|
||||
@Override
|
||||
public void update(File baseDirectory, HgConfig config)
|
||||
{
|
||||
|
||||
// do nothing
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<String> getHgInstallations()
|
||||
{
|
||||
return IOUtil.searchAll(COMMAND_HG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<String> getPythonInstallations()
|
||||
{
|
||||
return IOUtil.searchAll(COMMAND_PYTHON);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,428 @@
|
||||
/**
|
||||
* 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.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.util.IOUtil;
|
||||
import sonia.scm.util.RegistryUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class WindowsHgInstaller extends AbstractHgInstaller
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
private static final String FILE_LIBRARY_ZIP = "library.zip";
|
||||
|
||||
/** Field description */
|
||||
private static final String FILE_LIB_MERCURIAL =
|
||||
"Lib\\site-packages\\mercurial";
|
||||
|
||||
/** Field description */
|
||||
private static final String FILE_MERCURIAL_EXE = "hg.exe";
|
||||
|
||||
/** Field description */
|
||||
private static final String FILE_MERCURIAL_SCRIPT = "hg.bat";
|
||||
|
||||
/** Field description */
|
||||
private static final String FILE_SCRIPTS = "Scripts";
|
||||
|
||||
/** Field description */
|
||||
private static final String FILE_TEMPLATES = "templates";
|
||||
|
||||
/** Field description */
|
||||
private static final String[] REGISTRY_HG = new String[]
|
||||
{
|
||||
|
||||
// TortoiseHg
|
||||
"HKEY_CURRENT_USER\\Software\\TortoiseHg",
|
||||
|
||||
// Mercurial
|
||||
"HKEY_CURRENT_USER\\Software\\Mercurial\\InstallDir"
|
||||
};
|
||||
|
||||
/** Field description */
|
||||
private static final String[] REGISTRY_PYTHON = new String[]
|
||||
{
|
||||
|
||||
// .py files
|
||||
"HKEY_CLASSES_ROOT\\Python.File\\shell\\open\\command"
|
||||
};
|
||||
|
||||
/** the logger for WindowsHgInstaller */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(WindowsHgInstaller.class);
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public void install(File baseDirectory, HgConfig config) throws IOException
|
||||
{
|
||||
super.install(baseDirectory, config);
|
||||
|
||||
if (Util.isEmpty(config.getPythonBinary()))
|
||||
{
|
||||
String pythonBinary = getPythonBinary();
|
||||
|
||||
config.setPythonBinary(pythonBinary);
|
||||
}
|
||||
|
||||
if (Util.isEmpty(config.getHgBinary()))
|
||||
{
|
||||
File hgScript = getMercurialScript(config.getPythonBinary());
|
||||
|
||||
if (hgScript != null)
|
||||
{
|
||||
config.setHgBinary(hgScript.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
File hgDirectory = getMercurialDirectory(config.getHgBinary());
|
||||
|
||||
if (hgDirectory != null)
|
||||
{
|
||||
installHg(baseDirectory, config, hgDirectory);
|
||||
}
|
||||
|
||||
checkForOptimizedByteCode(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
*/
|
||||
@Override
|
||||
public void update(File baseDirectory, HgConfig config) {}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<String> getHgInstallations()
|
||||
{
|
||||
return getInstallations(REGISTRY_HG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<String> getPythonInstallations()
|
||||
{
|
||||
return getInstallations(REGISTRY_PYTHON);
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param config
|
||||
*/
|
||||
private void checkForOptimizedByteCode(HgConfig config)
|
||||
{
|
||||
boolean optimized = false;
|
||||
String path = config.getPythonPath();
|
||||
|
||||
if (Util.isNotEmpty(path))
|
||||
{
|
||||
for (String part : path.split(";"))
|
||||
{
|
||||
if (checkForOptimizedByteCode(part))
|
||||
{
|
||||
optimized = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config.setUseOptimizedBytecode(optimized);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param part
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private boolean checkForOptimizedByteCode(String part)
|
||||
{
|
||||
File libDir = new File(part);
|
||||
String[] pyoFiles = libDir.list(new FilenameFilter()
|
||||
{
|
||||
@Override
|
||||
public boolean accept(File file, String name)
|
||||
{
|
||||
return name.toLowerCase().endsWith(".pyo");
|
||||
}
|
||||
});
|
||||
|
||||
return Util.isNotEmpty(pyoFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
* @param hgDirectory
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private void installHg(File baseDirectory, HgConfig config, File hgDirectory)
|
||||
throws IOException
|
||||
{
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info("installing mercurial {}", hgDirectory.getAbsolutePath());
|
||||
}
|
||||
|
||||
File libDir = new File(baseDirectory, "lib\\hg");
|
||||
|
||||
IOUtil.mkdirs(libDir);
|
||||
|
||||
File libraryZip = new File(hgDirectory, FILE_LIBRARY_ZIP);
|
||||
|
||||
if (libraryZip.exists())
|
||||
{
|
||||
IOUtil.extract(libraryZip, libDir);
|
||||
config.setPythonPath(libDir.getAbsolutePath());
|
||||
}
|
||||
|
||||
File templateDirectory = new File(hgDirectory, FILE_TEMPLATES);
|
||||
|
||||
if (templateDirectory.exists())
|
||||
{
|
||||
IOUtil.copy(templateDirectory, new File(libDir, FILE_TEMPLATES));
|
||||
}
|
||||
|
||||
File hg = new File( hgDirectory, FILE_MERCURIAL_EXE );
|
||||
if ( hg.exists() )
|
||||
{
|
||||
config.setHgBinary(hg.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param registryKeys
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<String> getInstallations(String[] registryKeys)
|
||||
{
|
||||
List<String> installations = new ArrayList<String>();
|
||||
|
||||
for (String registryKey : registryKeys)
|
||||
{
|
||||
String path = RegistryUtil.getRegistryValue(registryKey);
|
||||
|
||||
if (path != null)
|
||||
{
|
||||
File file = new File(path, FILE_MERCURIAL_EXE);
|
||||
|
||||
if (file.exists())
|
||||
{
|
||||
installations.add(file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return installations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param hgBinary
|
||||
* @return
|
||||
*/
|
||||
private File getMercurialDirectory(String hgBinary)
|
||||
{
|
||||
File directory = null;
|
||||
|
||||
if ( Util.isNotEmpty(hgBinary) )
|
||||
{
|
||||
File hg = new File(hgBinary);
|
||||
|
||||
if (hg.exists() && hg.isFile())
|
||||
{
|
||||
directory = hg.getParentFile();
|
||||
}
|
||||
}
|
||||
|
||||
if ( directory == null )
|
||||
{
|
||||
directory = getMercurialDirectoryFromRegistry();
|
||||
}
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private File getMercurialDirectoryFromRegistry()
|
||||
{
|
||||
File directory = null;
|
||||
|
||||
for (String registryKey : REGISTRY_HG)
|
||||
{
|
||||
String path = RegistryUtil.getRegistryValue(registryKey);
|
||||
|
||||
if (path != null)
|
||||
{
|
||||
directory = new File(path);
|
||||
|
||||
if (!directory.exists())
|
||||
{
|
||||
directory = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the location of the script to run Mercurial, if Mercurial is
|
||||
* installed as a Python package from source. Only packages that include a
|
||||
* templates directory will be recognized.
|
||||
*
|
||||
* @param pythonBinary
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private File getMercurialScript(String pythonBinary)
|
||||
{
|
||||
File hgScript = null;
|
||||
|
||||
if (pythonBinary != null)
|
||||
{
|
||||
File pythonBinaryFile = new File(pythonBinary);
|
||||
|
||||
if (pythonBinaryFile.exists())
|
||||
{
|
||||
File pythonDir = pythonBinaryFile.getParentFile();
|
||||
File scriptsDir = new File(pythonDir, FILE_SCRIPTS);
|
||||
File potentialHgScript = new File(scriptsDir, FILE_MERCURIAL_SCRIPT);
|
||||
File mercurialPackageDir = new File(pythonDir, FILE_LIB_MERCURIAL);
|
||||
File templatesDir = new File(mercurialPackageDir, FILE_TEMPLATES);
|
||||
|
||||
if (potentialHgScript.exists() && templatesDir.exists())
|
||||
{
|
||||
hgScript = potentialHgScript;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hgScript;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getPythonBinary()
|
||||
{
|
||||
String python = RegistryUtil.getRegistryValue(REGISTRY_PYTHON[0]);
|
||||
|
||||
if (python == null)
|
||||
{
|
||||
python = IOUtil.search(new String[0], "python");
|
||||
}
|
||||
|
||||
return python;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* 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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgChangesetParser
|
||||
{
|
||||
|
||||
/** the logger for HgChangesetParser */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(HgChangesetParser.class);
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param in
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ParserConfigurationException
|
||||
* @throws SAXException
|
||||
*/
|
||||
public List<Changeset> parse(InputSource in)
|
||||
throws SAXException, IOException, ParserConfigurationException
|
||||
{
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
|
||||
return parse(builder.parse(in));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param document
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<Changeset> parse(Document document)
|
||||
{
|
||||
List<Changeset> changesetList = new ArrayList<Changeset>();
|
||||
NodeList changesetNodeList = document.getElementsByTagName("changeset");
|
||||
|
||||
if (changesetNodeList != null)
|
||||
{
|
||||
for (int i = 0; i < changesetNodeList.getLength(); i++)
|
||||
{
|
||||
Node changesetNode = changesetNodeList.item(i);
|
||||
Changeset changeset = parseChangesetNode(changesetNode);
|
||||
|
||||
if ((changeset != null) && changeset.isValid())
|
||||
{
|
||||
changesetList.add(changeset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return changesetList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param changeset
|
||||
* @param node
|
||||
*/
|
||||
private void parseChangesetChildNode(Changeset changeset, Node node)
|
||||
{
|
||||
String name = node.getNodeName();
|
||||
String value = node.getTextContent();
|
||||
|
||||
if (Util.isNotEmpty(value))
|
||||
{
|
||||
if ("id".equals(name))
|
||||
{
|
||||
changeset.setId(value);
|
||||
}
|
||||
else if ("author".equals(name))
|
||||
{
|
||||
changeset.setAuthor(Person.toPerson(value));
|
||||
}
|
||||
else if ("description".equals(name))
|
||||
{
|
||||
changeset.setDescription(value);
|
||||
}
|
||||
else if ("date".equals(name))
|
||||
{
|
||||
try
|
||||
{
|
||||
Date date = dateFormat.parse(value);
|
||||
|
||||
changeset.setDate(date.getTime());
|
||||
}
|
||||
catch (ParseException ex)
|
||||
{
|
||||
logger.warn("could not parse date", ex);
|
||||
}
|
||||
}
|
||||
else if ("tags".equals(name))
|
||||
{
|
||||
changeset.setTags(getList(value));
|
||||
}
|
||||
else if ("branches".equals(name))
|
||||
{
|
||||
changeset.setBranches(getList(value));
|
||||
}
|
||||
else if ("files-added".equals(name))
|
||||
{
|
||||
changeset.getModifications().setAdded(getList(value));
|
||||
}
|
||||
else if ("files-mods".equals(name))
|
||||
{
|
||||
changeset.getModifications().setModified(getList(value));
|
||||
}
|
||||
else if ("files-dels".equals(name))
|
||||
{
|
||||
changeset.getModifications().setRemoved(getList(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param changesetNode
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Changeset parseChangesetNode(Node changesetNode)
|
||||
{
|
||||
Changeset changeset = new Changeset();
|
||||
NodeList childrenNodeList = changesetNode.getChildNodes();
|
||||
|
||||
if (childrenNodeList != null)
|
||||
{
|
||||
for (int i = 0; i < childrenNodeList.getLength(); i++)
|
||||
{
|
||||
Node child = childrenNodeList.item(i);
|
||||
|
||||
parseChangesetChildNode(changeset, child);
|
||||
}
|
||||
}
|
||||
|
||||
return changeset;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param value
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<String> getList(String value)
|
||||
{
|
||||
return Arrays.asList(value.split(" "));
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private SimpleDateFormat dateFormat =
|
||||
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
/**
|
||||
* 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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import sonia.scm.io.Command;
|
||||
import sonia.scm.io.CommandResult;
|
||||
import sonia.scm.io.SimpleCommand;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgChangesetViewer implements ChangesetViewer
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String ID_TIP = "tip";
|
||||
|
||||
/** Field description */
|
||||
//J-
|
||||
public static final String TEMPLATE_CHANGESETS =
|
||||
"\"<changeset>"
|
||||
+ "<id>{rev}:{node|short}</id>"
|
||||
+ "<author>{author|escape}</author>"
|
||||
+ "<description>{desc|escape}</description>"
|
||||
+ "<date>{date|isodatesec}</date>"
|
||||
+ "<tags>{tags}</tags>"
|
||||
+ "<branches>{branches}</branches>"
|
||||
+ "<files-added>{file_adds}</files-added>"
|
||||
+ "<files-mods>{file_mods}</files-mods>"
|
||||
+ "<files-dels>{file_dels}</files-dels>"
|
||||
+ "</changeset>\"";
|
||||
//J+
|
||||
|
||||
/** Field description */
|
||||
public static final String TEMPLATE_TOTAL = "{rev}";
|
||||
|
||||
/** the logger for HgChangesetViewer */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(HgChangesetViewer.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param handler
|
||||
* @param repository
|
||||
*/
|
||||
public HgChangesetViewer(HgRepositoryHandler handler, Repository repository)
|
||||
{
|
||||
this.handler = handler;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param start
|
||||
* @param max
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChangesetPagingResult getChangesets(int start, int max)
|
||||
{
|
||||
ChangesetPagingResult changesets = null;
|
||||
InputStream in = null;
|
||||
|
||||
try
|
||||
{
|
||||
String repositoryPath = getRepositoryPath(repository);
|
||||
int total = getTotalChangesets(repositoryPath);
|
||||
int startRev = total - start;
|
||||
int endRev = total - start - (max - 1);
|
||||
|
||||
if (endRev < 0)
|
||||
{
|
||||
endRev = 0;
|
||||
}
|
||||
|
||||
Command command = new SimpleCommand(handler.getConfig().getHgBinary(),
|
||||
"-R", repositoryPath, "log", "-r",
|
||||
startRev + ":" + endRev, "--template",
|
||||
TEMPLATE_CHANGESETS);
|
||||
CommandResult result = command.execute();
|
||||
|
||||
if (result.isSuccessfull())
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("<changesets>");
|
||||
|
||||
sb.append(result.getOutput()).append("</changesets>");
|
||||
|
||||
List<Changeset> changesetList = new HgChangesetParser().parse(
|
||||
new InputSource(
|
||||
new StringReader(sb.toString())));
|
||||
|
||||
changesets = new ChangesetPagingResult(total, changesetList);
|
||||
}
|
||||
else if ( logger.isErrorEnabled() )
|
||||
{
|
||||
logger.error(
|
||||
"command for fetching changesets failed with exit code {} and output {}",
|
||||
result.getReturnCode(),
|
||||
result.getOutput()
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (ParserConfigurationException ex)
|
||||
{
|
||||
logger.error("could not parse changesets", ex);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.error("could not load changesets", ex);
|
||||
}
|
||||
catch (SAXException ex)
|
||||
{
|
||||
logger.error("could not unmarshall changesets", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(in);
|
||||
}
|
||||
|
||||
return changesets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getRepositoryPath(Repository repository)
|
||||
{
|
||||
return handler.getDirectory(repository).getAbsolutePath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repositoryPath
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private int getTotalChangesets(String repositoryPath) throws IOException
|
||||
{
|
||||
int total = -1;
|
||||
Command command = new SimpleCommand(handler.getConfig().getHgBinary(),
|
||||
"-R", repositoryPath, "tip", "--template",
|
||||
TEMPLATE_TOTAL);
|
||||
CommandResult result = command.execute();
|
||||
|
||||
if (result.isSuccessfull())
|
||||
{
|
||||
total = Integer.parseInt(result.getOutput().trim());
|
||||
}
|
||||
else if ( logger.isErrorEnabled() )
|
||||
{
|
||||
logger.error(
|
||||
"could not read tip revision, command returned with exit code {} and content {}",
|
||||
result.getReturnCode(),
|
||||
result.getOutput()
|
||||
);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private HgRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private Repository repository;
|
||||
}
|
||||
@@ -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.repository;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@XmlRootElement(name = "config")
|
||||
public class HgConfig extends SimpleRepositoryConfig
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*/
|
||||
public HgConfig() {}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getHgBinary()
|
||||
{
|
||||
return hgBinary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPythonBinary()
|
||||
{
|
||||
return pythonBinary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPythonPath()
|
||||
{
|
||||
return pythonPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isUseOptimizedBytecode()
|
||||
{
|
||||
return useOptimizedBytecode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
return super.isValid() && Util.isNotEmpty(hgBinary)
|
||||
&& Util.isNotEmpty(pythonBinary);
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param hgBinary
|
||||
*/
|
||||
public void setHgBinary(String hgBinary)
|
||||
{
|
||||
this.hgBinary = hgBinary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param pythonBinary
|
||||
*/
|
||||
public void setPythonBinary(String pythonBinary)
|
||||
{
|
||||
this.pythonBinary = pythonBinary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param pythonPath
|
||||
*/
|
||||
public void setPythonPath(String pythonPath)
|
||||
{
|
||||
this.pythonPath = pythonPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param useOptimizedBytecode
|
||||
*/
|
||||
public void setUseOptimizedBytecode(boolean useOptimizedBytecode)
|
||||
{
|
||||
this.useOptimizedBytecode = useOptimizedBytecode;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private String hgBinary;
|
||||
|
||||
/** Field description */
|
||||
private String pythonBinary;
|
||||
|
||||
/** Field description */
|
||||
private String pythonPath = "";
|
||||
|
||||
/** Field description */
|
||||
private boolean useOptimizedBytecode = false;
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* 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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.util.IOUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgRepositoryBrowser implements RepositoryBrowser
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String DEFAULT_REVISION = "tip";
|
||||
|
||||
/** Field description */
|
||||
public static final String ENV_PATH = "SCM_PATH";
|
||||
|
||||
/** Field description */
|
||||
public static final String ENV_PYTHON_PATH = "SCM_PYTHON_PATH";
|
||||
|
||||
/** Field description */
|
||||
public static final String ENV_REPOSITORY_PATH = "SCM_REPOSITORY_PATH";
|
||||
|
||||
/** Field description */
|
||||
public static final String ENV_REVISION = "SCM_REVISION";
|
||||
|
||||
/** Field description */
|
||||
public static final String RESOURCE_BROWSE = "/sonia/scm/hgbrowse.py";
|
||||
|
||||
/** the logger for HgRepositoryBrowser */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(HgRepositoryBrowser.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param handler
|
||||
* @param repository
|
||||
* @param browserResultContext
|
||||
*/
|
||||
public HgRepositoryBrowser(HgRepositoryHandler handler,
|
||||
Repository repository,
|
||||
JAXBContext browserResultContext)
|
||||
{
|
||||
this.handler = handler;
|
||||
this.repository = repository;
|
||||
this.browserResultContext = browserResultContext;
|
||||
}
|
||||
|
||||
//~--- 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
|
||||
{
|
||||
if (Util.isEmpty(revision))
|
||||
{
|
||||
revision = DEFAULT_REVISION;
|
||||
}
|
||||
|
||||
File directory = handler.getDirectory(repository);
|
||||
ProcessBuilder builder =
|
||||
new ProcessBuilder(handler.getConfig().getHgBinary(), "cat", "-r",
|
||||
revision, Util.nonNull(path));
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
StringBuilder msg = new StringBuilder();
|
||||
|
||||
for (String param : builder.command())
|
||||
{
|
||||
msg.append(param).append(" ");
|
||||
}
|
||||
|
||||
logger.debug(msg.toString());
|
||||
}
|
||||
|
||||
Process p = builder.directory(directory).start();
|
||||
InputStream input = null;
|
||||
|
||||
try
|
||||
{
|
||||
input = p.getInputStream();
|
||||
IOUtil.copy(input, output);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(input);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param revision
|
||||
* @param path
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Override
|
||||
public BrowserResult getResult(String revision, String path)
|
||||
throws IOException, RepositoryException
|
||||
{
|
||||
HgConfig config = handler.getConfig();
|
||||
ProcessBuilder pb = new ProcessBuilder(config.getPythonBinary());
|
||||
Map<String, String> env = pb.environment();
|
||||
|
||||
env.put(ENV_PYTHON_PATH, Util.nonNull(config.getPythonPath()));
|
||||
|
||||
String directory = handler.getDirectory(repository).getAbsolutePath();
|
||||
|
||||
env.put(ENV_REPOSITORY_PATH, directory);
|
||||
|
||||
if (Util.isEmpty(revision))
|
||||
{
|
||||
revision = DEFAULT_REVISION;
|
||||
}
|
||||
|
||||
env.put(ENV_REVISION, revision);
|
||||
env.put(ENV_PATH, Util.nonNull(path));
|
||||
|
||||
Process p = pb.start();
|
||||
BrowserResult result = null;
|
||||
InputStream resource = null;
|
||||
InputStream input = null;
|
||||
OutputStream output = null;
|
||||
|
||||
try
|
||||
{
|
||||
resource = HgRepositoryBrowser.class.getResourceAsStream(RESOURCE_BROWSE);
|
||||
output = p.getOutputStream();
|
||||
IOUtil.copy(resource, output);
|
||||
output.close();
|
||||
|
||||
// IOUtil.copy(p.getErrorStream(), System.err);
|
||||
input = p.getInputStream();
|
||||
result =
|
||||
(BrowserResult) browserResultContext.createUnmarshaller().unmarshal(
|
||||
input);
|
||||
|
||||
// IOUtil.copy(input, System.out);
|
||||
input.close();
|
||||
}
|
||||
catch (JAXBException ex)
|
||||
{
|
||||
logger.error("could not parse result", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(resource);
|
||||
IOUtil.close(input);
|
||||
IOUtil.close(output);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private JAXBContext browserResultContext;
|
||||
|
||||
/** Field description */
|
||||
private HgRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private Repository repository;
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
/**
|
||||
* 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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.ConfigurationException;
|
||||
import sonia.scm.Type;
|
||||
import sonia.scm.installer.HgInstaller;
|
||||
import sonia.scm.installer.HgInstallerFactory;
|
||||
import sonia.scm.io.ExtendedCommand;
|
||||
import sonia.scm.io.FileSystem;
|
||||
import sonia.scm.io.INIConfiguration;
|
||||
import sonia.scm.io.INIConfigurationWriter;
|
||||
import sonia.scm.io.INISection;
|
||||
import sonia.scm.plugin.ext.Extension;
|
||||
import sonia.scm.store.StoreFactory;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.web.HgWebConfigWriter;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Singleton
|
||||
@Extension
|
||||
public class HgRepositoryHandler
|
||||
extends AbstractSimpleRepositoryHandler<HgConfig>
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String TYPE_DISPLAYNAME = "Mercurial";
|
||||
|
||||
/** Field description */
|
||||
public static final String TYPE_NAME = "hg";
|
||||
|
||||
/** Field description */
|
||||
public static final Type TYPE = new Type(TYPE_NAME, TYPE_DISPLAYNAME);
|
||||
|
||||
/** the logger for HgRepositoryHandler */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(HgRepositoryHandler.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param storeFactory
|
||||
* @param fileSystem
|
||||
*/
|
||||
@Inject
|
||||
public HgRepositoryHandler(StoreFactory storeFactory, FileSystem fileSystem)
|
||||
{
|
||||
super(storeFactory, fileSystem);
|
||||
|
||||
try
|
||||
{
|
||||
this.browserResultContext = JAXBContext.newInstance(BrowserResult.class);
|
||||
}
|
||||
catch (JAXBException ex)
|
||||
{
|
||||
throw new ConfigurationException("could not create jaxbcontext", ex);
|
||||
}
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param autoConfig
|
||||
*/
|
||||
public void doAutoConfiguration(HgConfig autoConfig)
|
||||
{
|
||||
HgInstaller installer = HgInstallerFactory.createInstaller();
|
||||
|
||||
try
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("installing mercurial with {}",
|
||||
installer.getClass().getName());
|
||||
}
|
||||
|
||||
installer.install(baseDirectory, autoConfig);
|
||||
config = autoConfig;
|
||||
storeConfig();
|
||||
new HgWebConfigWriter(config).write();
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
if (logger.isErrorEnabled())
|
||||
{
|
||||
logger.error(
|
||||
"Could not write Hg CGI for inital config. "
|
||||
+ "HgWeb may not function until a new Hg config is set", ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void loadConfig()
|
||||
{
|
||||
super.loadConfig();
|
||||
|
||||
if (config == null)
|
||||
{
|
||||
doAutoConfiguration(new HgConfig());
|
||||
}
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChangesetViewer getChangesetViewer(Repository repository)
|
||||
{
|
||||
HgChangesetViewer changesetViewer = null;
|
||||
|
||||
AssertUtil.assertIsNotNull(repository);
|
||||
|
||||
String type = repository.getType();
|
||||
|
||||
AssertUtil.assertIsNotEmpty(type);
|
||||
|
||||
if (TYPE_NAME.equals(type))
|
||||
{
|
||||
changesetViewer = new HgChangesetViewer(this, repository);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("mercurial repository is required");
|
||||
}
|
||||
|
||||
return changesetViewer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public RepositoryBrowser getRepositoryBrowser(Repository repository)
|
||||
{
|
||||
return new HgRepositoryBrowser(this, repository, browserResultContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
* @param directory
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected ExtendedCommand buildCreateCommand(Repository repository,
|
||||
File directory)
|
||||
{
|
||||
return new ExtendedCommand(config.getHgBinary(), "init",
|
||||
directory.getPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes .hg/hgrc and disables hg access control
|
||||
* see HgPermissionFilter
|
||||
*
|
||||
* @param repository
|
||||
* @param directory
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Override
|
||||
protected void postCreate(Repository repository, File directory)
|
||||
throws IOException, RepositoryException
|
||||
{
|
||||
File hgrcFile = new File(directory,
|
||||
".hg".concat(File.separator).concat("hgrc"));
|
||||
INIConfiguration hgrc = new INIConfiguration();
|
||||
INISection webSection = new INISection("web");
|
||||
|
||||
webSection.setParameter("push_ssl", "false");
|
||||
webSection.setParameter("allow_read", "*");
|
||||
webSection.setParameter("allow_push", "*");
|
||||
hgrc.addSection(webSection);
|
||||
|
||||
INIConfigurationWriter writer = new INIConfigurationWriter();
|
||||
|
||||
writer.write(hgrc, hgrcFile);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected Class<HgConfig> getConfigClass()
|
||||
{
|
||||
return HgConfig.class;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private JAXBContext browserResultContext;
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
* 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 sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.web.cgi.CGIExecutor;
|
||||
import sonia.scm.web.cgi.CGIExecutorFactory;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Singleton
|
||||
public class HgCGIServlet extends HttpServlet
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String ENV_PYTHON_PATH = "SCM_PYTHON_PATH";
|
||||
|
||||
/** Field description */
|
||||
public static final String ENV_REPOSITORY_NAME = "REPO_NAME";
|
||||
|
||||
/** Field description */
|
||||
public static final String ENV_REPOSITORY_PATH = "SCM_REPOSITORY_PATH";
|
||||
|
||||
/** Field description */
|
||||
private static final long serialVersionUID = -3492811300905099810L;
|
||||
|
||||
/** Field description */
|
||||
public static final Pattern PATTERN_REPOSITORYNAME =
|
||||
Pattern.compile("/[^/]+/([^/]+)(?:/.*)?");
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param cgiExecutorFactory
|
||||
* @param configuration
|
||||
* @param repositoryManager
|
||||
* @param handler
|
||||
*/
|
||||
@Inject
|
||||
public HgCGIServlet(CGIExecutorFactory cgiExecutorFactory,
|
||||
ScmConfiguration configuration,
|
||||
RepositoryManager repositoryManager,
|
||||
HgRepositoryHandler handler)
|
||||
{
|
||||
this.cgiExecutorFactory = cgiExecutorFactory;
|
||||
this.configuration = configuration;
|
||||
this.repositoryManager = repositoryManager;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Override
|
||||
public void init() throws ServletException
|
||||
{
|
||||
command = HgUtil.getCGI();
|
||||
super.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Override
|
||||
protected void service(HttpServletRequest request,
|
||||
HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
Repository repository = getRepository(request);
|
||||
|
||||
if (repository == null)
|
||||
{
|
||||
throw new ServletException("repository not found");
|
||||
}
|
||||
|
||||
String name = repository.getName();
|
||||
File directory = handler.getDirectory(repository);
|
||||
String pythonPath = "";
|
||||
HgConfig config = handler.getConfig();
|
||||
|
||||
if (config != null)
|
||||
{
|
||||
pythonPath = config.getPythonPath();
|
||||
|
||||
if (pythonPath == null)
|
||||
{
|
||||
pythonPath = "";
|
||||
}
|
||||
}
|
||||
|
||||
CGIExecutor executor = cgiExecutorFactory.createExecutor(configuration,
|
||||
getServletContext(), request, response);
|
||||
|
||||
executor.getEnvironment().set(ENV_REPOSITORY_NAME, name);
|
||||
executor.getEnvironment().set(ENV_REPOSITORY_PATH,
|
||||
directory.getAbsolutePath());
|
||||
executor.getEnvironment().set(ENV_PYTHON_PATH, pythonPath);
|
||||
|
||||
String interpreter = getInterpreter();
|
||||
|
||||
if (interpreter != null)
|
||||
{
|
||||
executor.setInterpreter(interpreter);
|
||||
}
|
||||
|
||||
executor.execute(command.getAbsolutePath());
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getInterpreter()
|
||||
{
|
||||
HgConfig config = handler.getConfig();
|
||||
|
||||
AssertUtil.assertIsNotNull(config);
|
||||
|
||||
String python = config.getPythonBinary();
|
||||
|
||||
if ((python != null) && config.isUseOptimizedBytecode())
|
||||
{
|
||||
python = python.concat(" -O");
|
||||
}
|
||||
|
||||
return python;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Repository getRepository(HttpServletRequest request)
|
||||
{
|
||||
Repository repository = null;
|
||||
String uri = request.getRequestURI();
|
||||
|
||||
uri = uri.substring(request.getContextPath().length());
|
||||
|
||||
Matcher m = PATTERN_REPOSITORYNAME.matcher(uri);
|
||||
|
||||
if (m.matches())
|
||||
{
|
||||
String repositoryname = m.group(1);
|
||||
|
||||
repository = getRepository(repositoryname);
|
||||
}
|
||||
|
||||
return repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repositoryname
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Repository getRepository(String repositoryname)
|
||||
{
|
||||
return repositoryManager.get(HgRepositoryHandler.TYPE_NAME, repositoryname);
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private CGIExecutorFactory cgiExecutorFactory;
|
||||
|
||||
/** Field description */
|
||||
private File command;
|
||||
|
||||
/** Field description */
|
||||
private ScmConfiguration configuration;
|
||||
|
||||
/** Field description */
|
||||
private HgRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private RepositoryManager repositoryManager;
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* 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.HgRepositoryHandler;
|
||||
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 HgPermissionFilter extends RegexPermissionFilter
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param securityContextProvider
|
||||
* @param repositoryManager
|
||||
*/
|
||||
@Inject
|
||||
public HgPermissionFilter(
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryManager repositoryManager)
|
||||
{
|
||||
super(securityContextProvider, repositoryManager);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected String getType()
|
||||
{
|
||||
return HgRepositoryHandler.TYPE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected boolean isWriteRequest(HttpServletRequest request)
|
||||
{
|
||||
return !request.getMethod().equalsIgnoreCase("GET");
|
||||
}
|
||||
}
|
||||
@@ -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 HgServletModule extends ServletModule
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String MAPPING_HG = "/hg/*";
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
protected void configureServlets()
|
||||
{
|
||||
filter(MAPPING_HG).through(BasicAuthenticationFilter.class);
|
||||
filter(MAPPING_HG).through(HgPermissionFilter.class);
|
||||
serve(MAPPING_HG).with(HgCGIServlet.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 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 sonia.scm.SCMContext;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgUtil
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String CGI_DIRECTORY = "cgi-bin";
|
||||
|
||||
/** Field description */
|
||||
public static final String CGI_NAME = "hgweb.py";
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static File getCGI()
|
||||
{
|
||||
File cgiDirectory = new File(SCMContext.getContext().getBaseDirectory(),
|
||||
CGI_DIRECTORY);
|
||||
|
||||
if (!cgiDirectory.exists() &&!cgiDirectory.mkdirs())
|
||||
{
|
||||
throw new RuntimeException(
|
||||
"could not create directory".concat(cgiDirectory.getPath()));
|
||||
}
|
||||
|
||||
return new File(cgiDirectory, CGI_NAME);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* 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 sonia.scm.io.RegexResourceProcessor;
|
||||
import sonia.scm.io.ResourceProcessor;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgWebConfigWriter
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String CGI_TEMPLATE = "/sonia/scm/hgweb.py";
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param config
|
||||
*/
|
||||
public HgWebConfigWriter(HgConfig config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void write() throws IOException
|
||||
{
|
||||
File cgiFile = HgUtil.getCGI();
|
||||
|
||||
writeCGIFile(cgiFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param cgiFile
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private void writeCGIFile(File cgiFile) throws IOException
|
||||
{
|
||||
InputStream input = null;
|
||||
OutputStream output = null;
|
||||
|
||||
try
|
||||
{
|
||||
input = HgWebConfigWriter.class.getResourceAsStream(CGI_TEMPLATE);
|
||||
output = new FileOutputStream(cgiFile);
|
||||
|
||||
ResourceProcessor rp = new RegexResourceProcessor();
|
||||
|
||||
rp.addVariable("python", config.getPythonBinary());
|
||||
rp.process(input, output);
|
||||
cgiFile.setExecutable(true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(input);
|
||||
IOUtil.close(output);
|
||||
}
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private HgConfig config;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
|
||||
-->
|
||||
|
||||
<!--
|
||||
Document : plugin.xml
|
||||
Created on : October 12, 2010, 8:29 AM
|
||||
Author : sdorra
|
||||
Description:
|
||||
Purpose of the document follows.
|
||||
-->
|
||||
|
||||
<plugin>
|
||||
|
||||
<information>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>${project.artifactId}</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<name>${project.name}</name>
|
||||
<description>${project.description}</description>
|
||||
<author>Sebastian Sdorra</author>
|
||||
<url>${project.url}</url>
|
||||
</information>
|
||||
|
||||
<conditions>
|
||||
<min-version>1.1</min-version>
|
||||
</conditions>
|
||||
|
||||
<resources>
|
||||
<script>/sonia/scm/hg.config.js</script>
|
||||
<script>/sonia/scm/hg.config-wizard.js</script>
|
||||
</resources>
|
||||
|
||||
</plugin>
|
||||
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
Ext.ns("Sonia.hg");
|
||||
|
||||
Sonia.hg.ConfigWizard = Ext.extend(Ext.Window,{
|
||||
|
||||
hgConfig: null,
|
||||
title: 'Mercurial Configuration Wizard',
|
||||
|
||||
initComponent: function(){
|
||||
|
||||
this.addEvents('finish');
|
||||
|
||||
var config = {
|
||||
title: this.title,
|
||||
layout: 'fit',
|
||||
width: 420,
|
||||
height: 140,
|
||||
closable: true,
|
||||
resizable: true,
|
||||
plain: true,
|
||||
border: false,
|
||||
modal: true,
|
||||
bodyCssClass: 'x-panel-mc',
|
||||
items: [{
|
||||
id: 'hgConfigWizardPanel',
|
||||
xtype: 'hgConfigWizardPanel',
|
||||
hgConfig: this.hgConfig,
|
||||
listeners: {
|
||||
finish: {
|
||||
fn: this.onFinish,
|
||||
scope: this
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
Sonia.hg.ConfigWizard.superclass.initComponent.apply(this, arguments);
|
||||
},
|
||||
|
||||
onFinish: function(config){
|
||||
this.fireEvent('finish', config);
|
||||
this.close();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Sonia.hg.InstallationJsonReader = function(){
|
||||
this.RecordType = Ext.data.Record.create([{
|
||||
name: "path",
|
||||
mapping: "path",
|
||||
type: "string"
|
||||
}]);
|
||||
};
|
||||
|
||||
Ext.extend(Sonia.hg.InstallationJsonReader, Ext.data.JsonReader, {
|
||||
|
||||
readRecords: function(o){
|
||||
this.jsonData = o;
|
||||
|
||||
if (debug){
|
||||
console.debug('read installation data from json');
|
||||
console.debug(o);
|
||||
}
|
||||
|
||||
var records = [];
|
||||
var paths = o.path;
|
||||
for ( var i=0; i<paths.length; i++ ){
|
||||
records.push(new this.RecordType({
|
||||
'path': paths[i]
|
||||
}));
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
records: records,
|
||||
totalRecords: records.length
|
||||
};
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Sonia.hg.ConfigWizardPanel = Ext.extend(Ext.Panel,{
|
||||
|
||||
hgConfig: null,
|
||||
packageTemplate: '<tpl for="."><div class="x-combo-list-item">\
|
||||
{id} (hg: {hg-version}, py: {python-version}, size: {size:fileSize})\
|
||||
</div></tpl>',
|
||||
|
||||
// text
|
||||
backText: 'Back',
|
||||
nextText: 'Next',
|
||||
finishText: 'Finish',
|
||||
configureLocalText: 'Configure local installation',
|
||||
configureRemoteText: 'Download and install',
|
||||
loadingText: 'Loading ...',
|
||||
hgInstallationText: 'Mercurial Installation',
|
||||
pythonInstallationText: 'Python Installation',
|
||||
hgPackageText: 'Mercurial Package',
|
||||
errorTitleText: 'Error',
|
||||
packageInstallationFailedText: 'Package installation failed',
|
||||
installPackageText: 'install mercurial package {0}',
|
||||
|
||||
initComponent: function(){
|
||||
this.addEvents('finish');
|
||||
|
||||
var packageStore = new Ext.data.JsonStore({
|
||||
storeId: 'pkgStore',
|
||||
proxy: new Ext.data.HttpProxy({
|
||||
url: restUrl + 'config/repositories/hg/packages.json',
|
||||
disableCaching: false
|
||||
}),
|
||||
fields: [ 'id', 'hg-version', 'python-version', 'size' ],
|
||||
root: 'package',
|
||||
listeners: {
|
||||
load: {
|
||||
fn: this.checkIfPackageAvailable,
|
||||
scope: this
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var hgInstallationStore = new Ext.data.Store({
|
||||
proxy: new Ext.data.HttpProxy({
|
||||
url: restUrl + 'config/repositories/hg/installations/hg.json'
|
||||
}),
|
||||
fields: [ 'path' ],
|
||||
reader: new Sonia.hg.InstallationJsonReader(),
|
||||
autoLoad: true,
|
||||
autoDestroy: true
|
||||
});
|
||||
|
||||
var pythonInstallationStore = new Ext.data.Store({
|
||||
proxy: new Ext.data.HttpProxy({
|
||||
url: restUrl + 'config/repositories/hg/installations/python.json'
|
||||
}),
|
||||
fields: [ 'path' ],
|
||||
reader: new Sonia.hg.InstallationJsonReader(),
|
||||
autoLoad: true,
|
||||
autoDestroy: true
|
||||
});
|
||||
|
||||
var config = {
|
||||
layout: 'card',
|
||||
activeItem: 0,
|
||||
bodyStyle: 'padding: 5px',
|
||||
defaults: {
|
||||
bodyCssClass: 'x-panel-mc',
|
||||
border: false,
|
||||
labelWidth: 120,
|
||||
width: 250
|
||||
},
|
||||
bbar: ['->',{
|
||||
id: 'move-prev',
|
||||
text: this.backText,
|
||||
handler: this.navHandler.createDelegate(this, [-1]),
|
||||
disabled: true,
|
||||
scope: this
|
||||
},{
|
||||
id: 'move-next',
|
||||
text: this.nextText,
|
||||
handler: this.navHandler.createDelegate(this, [1]),
|
||||
scope: this
|
||||
},{
|
||||
id: 'finish',
|
||||
text: this.finishText,
|
||||
handler: this.applyChanges,
|
||||
scope: this,
|
||||
disabled: true
|
||||
}],
|
||||
items: [{
|
||||
id: 'cod',
|
||||
items: [{
|
||||
id: 'configureOrDownload',
|
||||
xtype: 'radiogroup',
|
||||
name: 'configureOrDownload',
|
||||
columns: 1,
|
||||
items: [{
|
||||
boxLabel: this.configureLocalText,
|
||||
name: 'cod',
|
||||
inputValue: 'localInstall',
|
||||
checked: true
|
||||
},{
|
||||
id: 'remoteInstallRadio',
|
||||
boxLabel: this.configureRemoteText,
|
||||
name: 'cod',
|
||||
inputValue: 'remoteInstall',
|
||||
disabled: true
|
||||
}]
|
||||
}],
|
||||
listeners: {
|
||||
render: {
|
||||
fn: function(panel){
|
||||
panel.body.mask(this.loadingText);
|
||||
var store = Ext.StoreMgr.lookup('pkgStore');
|
||||
store.load.defer(100, store);
|
||||
},
|
||||
scope: this
|
||||
}
|
||||
}
|
||||
},{
|
||||
id: 'localInstall',
|
||||
layout: 'form',
|
||||
defaults: {
|
||||
width: 250
|
||||
},
|
||||
items: [{
|
||||
id: 'mercurial',
|
||||
fieldLabel: this.hgInstallationText,
|
||||
name: 'mercurial',
|
||||
xtype: 'combo',
|
||||
readOnly: false,
|
||||
triggerAction: 'all',
|
||||
lazyRender: true,
|
||||
mode: 'local',
|
||||
editable: true,
|
||||
store: hgInstallationStore,
|
||||
valueField: 'path',
|
||||
displayField: 'path',
|
||||
allowBlank: false,
|
||||
value: this.hgConfig.hgBinary
|
||||
},{
|
||||
id: 'python',
|
||||
fieldLabel: this.pythonInstallationText,
|
||||
name: 'python',
|
||||
xtype: 'combo',
|
||||
readOnly: false,
|
||||
triggerAction: 'all',
|
||||
lazyRender: true,
|
||||
mode: 'local',
|
||||
editable: true,
|
||||
store: pythonInstallationStore,
|
||||
valueField: 'path',
|
||||
displayField: 'path',
|
||||
allowBlank: false,
|
||||
value: this.hgConfig.pythonBinary
|
||||
}]
|
||||
},{
|
||||
id: 'remoteInstall',
|
||||
layout: 'form',
|
||||
defaults: {
|
||||
width: 250
|
||||
},
|
||||
items: [{
|
||||
id: 'package',
|
||||
fieldLabel: this.hgPackageText,
|
||||
name: 'package',
|
||||
xtype: 'combo',
|
||||
readOnly: false,
|
||||
triggerAction: 'all',
|
||||
lazyRender: true,
|
||||
mode: 'local',
|
||||
editable: false,
|
||||
store: packageStore,
|
||||
valueField: 'id',
|
||||
displayField: 'id',
|
||||
allowBlank: false,
|
||||
tpl: this.packageTemplate,
|
||||
listeners: {
|
||||
select: function(){
|
||||
Ext.getCmp('finish').setDisabled(false);
|
||||
}
|
||||
}
|
||||
}]
|
||||
}]
|
||||
}
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
Sonia.hg.ConfigWizardPanel.superclass.initComponent.apply(this, arguments);
|
||||
},
|
||||
|
||||
checkIfPackageAvailable: function(store){
|
||||
Ext.getCmp('cod').body.unmask();
|
||||
var c = store.getTotalCount();
|
||||
if ( debug ){
|
||||
console.debug( "found " + c + " package(s)" );
|
||||
}
|
||||
if ( c > 0 ){
|
||||
Ext.getCmp('remoteInstallRadio').setDisabled(false);
|
||||
}
|
||||
},
|
||||
|
||||
navHandler: function(direction){
|
||||
var layout = this.getLayout();
|
||||
var id = layout.activeItem.id;
|
||||
|
||||
var next = -1;
|
||||
|
||||
if ( id == 'cod' && direction == 1 ){
|
||||
var v = Ext.getCmp('configureOrDownload').getValue().getRawValue();
|
||||
var df = false;
|
||||
if ( v == 'localInstall' ){
|
||||
next = 1;
|
||||
} else if ( v == 'remoteInstall' ){
|
||||
next = 2;
|
||||
df = true;
|
||||
}
|
||||
Ext.getCmp('move-prev').setDisabled(false);
|
||||
Ext.getCmp('move-next').setDisabled(true);
|
||||
Ext.getCmp('finish').setDisabled(df);
|
||||
}
|
||||
else if (direction == -1 && (id == 'localInstall' || id == 'remoteInstall')) {
|
||||
next = 0;
|
||||
Ext.getCmp('move-prev').setDisabled(true);
|
||||
Ext.getCmp('move-next').setDisabled(false);
|
||||
Ext.getCmp('finish').setDisabled(true);
|
||||
}
|
||||
|
||||
if ( next >= 0 ){
|
||||
layout.setActiveItem(next);
|
||||
}
|
||||
},
|
||||
|
||||
applyChanges: function(){
|
||||
var v = Ext.getCmp('configureOrDownload').getValue().getRawValue();
|
||||
if ( v == 'localInstall' ){
|
||||
this.applyLocalConfiguration();
|
||||
} else if ( v == 'remoteInstall' ){
|
||||
this.applyRemoteConfiguration();
|
||||
}
|
||||
},
|
||||
|
||||
applyRemoteConfiguration: function(){
|
||||
if ( debug ){
|
||||
console.debug( "apply remote configuration" );
|
||||
}
|
||||
|
||||
var pkg = Ext.getCmp('package').getValue();
|
||||
if ( debug ){
|
||||
console.debug( 'install mercurial package ' + pkg );
|
||||
}
|
||||
|
||||
var lbox = Ext.MessageBox.show({
|
||||
title: this.loadingText,
|
||||
msg: String.format(this.installPackageText, pkg),
|
||||
width: 300,
|
||||
wait: true,
|
||||
animate: true,
|
||||
progress: true,
|
||||
closable: false
|
||||
});
|
||||
|
||||
Ext.Ajax.request({
|
||||
url: restUrl + 'config/repositories/hg/packages/' + pkg + '.json',
|
||||
method: 'POST',
|
||||
scope: this,
|
||||
timeout: 900000, // 15min
|
||||
success: function(){
|
||||
if ( debug ){
|
||||
console.debug('package successfully installed');
|
||||
}
|
||||
lbox.hide();
|
||||
this.fireEvent('finish');
|
||||
},
|
||||
failure: function(){
|
||||
if ( debug ){
|
||||
console.debug('package installation failed');
|
||||
}
|
||||
lbox.hide();
|
||||
Ext.MessageBox.show({
|
||||
title: this.errorTitleText,
|
||||
msg: this.packageInstallationFailedText,
|
||||
buttons: Ext.MessageBox.OK,
|
||||
icon:Ext.MessageBox.ERROR
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
|
||||
applyLocalConfiguration: function(){
|
||||
if ( debug ){
|
||||
console.debug( "apply remote configuration" );
|
||||
}
|
||||
var mercurial = Ext.getCmp('mercurial').getValue();
|
||||
var python = Ext.getCmp('python').getValue();
|
||||
if (debug){
|
||||
console.debug( 'configure mercurial=' + mercurial + " and python=" + python );
|
||||
}
|
||||
delete this.hgConfig.pythonPath;
|
||||
delete this.hgConfig.useOptimizedBytecode;
|
||||
this.hgConfig.hgBinary = mercurial;
|
||||
this.hgConfig.pythonBinary = python;
|
||||
|
||||
if ( debug ){
|
||||
console.debug( this.hgConfig );
|
||||
}
|
||||
|
||||
this.fireEvent('finish', this.hgConfig);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// register xtype
|
||||
Ext.reg('hgConfigWizardPanel', Sonia.hg.ConfigWizardPanel);
|
||||
|
||||
|
||||
// i18n
|
||||
|
||||
if ( i18n != null && i18n.country == 'de' ){
|
||||
|
||||
Ext.override(Sonia.hg.ConfigWizardPanel, {
|
||||
|
||||
backText: 'Zurück',
|
||||
nextText: 'Weiter',
|
||||
finishText: 'Fertigstellen',
|
||||
configureLocalText: 'Eine lokale Installation Konfigurieren',
|
||||
configureRemoteText: 'Herunterladen und installieren',
|
||||
loadingText: 'Lade ...',
|
||||
hgInstallationText: 'Mercurial Installation',
|
||||
pythonInstallationText: 'Python Installation',
|
||||
hgPackageText: 'Mercurial Package',
|
||||
errorTitleText: 'Fehler',
|
||||
packageInstallationFailedText: 'Package Installation fehlgeschlagen',
|
||||
installPackageText: 'Installiere Mercurial-Package {0}'
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
Ext.ns("Sonia.hg");
|
||||
|
||||
Sonia.hg.ConfigPanel = Ext.extend(Sonia.config.ConfigForm, {
|
||||
|
||||
// labels
|
||||
titleText: 'Mercurial Settings',
|
||||
hgBinaryText: 'HG Binary',
|
||||
pythonBinaryText: 'Python Binary',
|
||||
pythonPathText: 'Python Module Search Path',
|
||||
repositoryDirectoryText: 'Repository directory',
|
||||
useOptimizedBytecodeText: 'Optimized Bytecode (.pyo)',
|
||||
configWizardText: 'Start Configuration Wizard',
|
||||
configWizardLabelText: 'Start Configuration Wizard',
|
||||
|
||||
// helpText
|
||||
hgBinaryHelpText: 'Location of Mercurial binary.',
|
||||
pythonBinaryHelpText: 'Location of Python binary.',
|
||||
pythonPathHelpText: 'Python Module Search Path (PYTHONPATH).',
|
||||
repositoryDirectoryHelpText: 'Location of the Mercurial repositories.',
|
||||
useOptimizedBytecodeHelpText: 'Use the Python "-O" switch.',
|
||||
|
||||
initComponent: function(){
|
||||
|
||||
var config = {
|
||||
title : this.titleText,
|
||||
items : [{
|
||||
xtype : 'textfield',
|
||||
fieldLabel : this.hgBinaryText,
|
||||
name : 'hgBinary',
|
||||
allowBlank : false,
|
||||
helpText: this.hgBinaryHelpText
|
||||
},{
|
||||
xtype : 'textfield',
|
||||
fieldLabel : this.pythonBinaryText,
|
||||
name : 'pythonBinary',
|
||||
allowBlank : false,
|
||||
helpText: this.pythonBinaryHelpText
|
||||
},{
|
||||
xtype : 'textfield',
|
||||
fieldLabel : this.pythonPathText,
|
||||
name : 'pythonPath',
|
||||
helpText: this.pythonPathHelpText
|
||||
},{
|
||||
xtype: 'textfield',
|
||||
name: 'repositoryDirectory',
|
||||
fieldLabel: this.repositoryDirectoryText,
|
||||
helpText: this.repositoryDirectoryHelpText,
|
||||
allowBlank : false
|
||||
},{
|
||||
xtype: 'checkbox',
|
||||
name: 'useOptimizedBytecode',
|
||||
fieldLabel: this.useOptimizedBytecodeText,
|
||||
inputValue: 'true',
|
||||
helpText: this.useOptimizedBytecodeHelpText
|
||||
},{
|
||||
xtype: 'button',
|
||||
text: this.configWizardText,
|
||||
fieldLabel: this.configWizardLabelText,
|
||||
handler: function(){
|
||||
var config = this.getForm().getValues();
|
||||
var wizard = new Sonia.hg.ConfigWizard({
|
||||
hgConfig: config
|
||||
});
|
||||
wizard.on('finish', function(config){
|
||||
var self = Ext.getCmp('hgConfigForm');
|
||||
if ( config != null ){
|
||||
if (debug){
|
||||
console.debug( 'load config from wizard and submit to server' );
|
||||
}
|
||||
self.loadConfig( self.el, 'config/repositories/hg/auto-configuration.json', 'POST', config );
|
||||
} else {
|
||||
if (debug){
|
||||
console.debug( 'reload config' );
|
||||
}
|
||||
self.onLoad(self.el);
|
||||
}
|
||||
}, this);
|
||||
wizard.show();
|
||||
},
|
||||
scope: this
|
||||
}]
|
||||
}
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
Sonia.hg.ConfigPanel.superclass.initComponent.apply(this, arguments);
|
||||
},
|
||||
|
||||
onSubmit: function(values){
|
||||
this.el.mask(this.submitText);
|
||||
Ext.Ajax.request({
|
||||
url: restUrl + 'config/repositories/hg.json',
|
||||
method: 'POST',
|
||||
jsonData: values,
|
||||
scope: this,
|
||||
disableCaching: true,
|
||||
success: function(){
|
||||
this.el.unmask();
|
||||
},
|
||||
failure: function(){
|
||||
this.el.unmask();
|
||||
alert('failure');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onLoad: function(el){
|
||||
this.loadConfig(el, 'config/repositories/hg.json', 'GET');
|
||||
},
|
||||
|
||||
loadConfig: function(el, url, method, config){
|
||||
var tid = setTimeout( function(){ el.mask(this.loadingText); }, 100);
|
||||
Ext.Ajax.request({
|
||||
url: restUrl + url,
|
||||
method: method,
|
||||
jsonData: config,
|
||||
scope: this,
|
||||
disableCaching: true,
|
||||
success: function(response){
|
||||
var obj = Ext.decode(response.responseText);
|
||||
this.load(obj);
|
||||
clearTimeout(tid);
|
||||
el.unmask();
|
||||
},
|
||||
failure: function(){
|
||||
el.unmask();
|
||||
clearTimeout(tid);
|
||||
alert('failure');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Ext.reg("hgConfigPanel", Sonia.hg.ConfigPanel);
|
||||
|
||||
// i18n
|
||||
|
||||
if ( i18n != null && i18n.country == 'de' ){
|
||||
|
||||
Ext.override(Sonia.hg.ConfigPanel, {
|
||||
|
||||
// labels
|
||||
titleText: 'Mercurial Einstellungen',
|
||||
hgBinaryText: 'HG Pfad',
|
||||
pythonBinaryText: 'Python Pfad',
|
||||
pythonPathText: 'Python Modul Suchpfad',
|
||||
repositoryDirectoryText: 'Repository-Verzeichnis',
|
||||
useOptimizedBytecodeText: 'Optimierter Bytecode (.pyo)',
|
||||
autoConfigText: 'Einstellungen automatisch laden',
|
||||
autoConfigLabelText: 'Automatische Einstellung',
|
||||
configWizardText: 'Konfigurations-Assistenten starten',
|
||||
configWizardLabelText: 'Konfigurations-Assistent',
|
||||
|
||||
// helpText
|
||||
hgBinaryHelpText: 'Pfad zum "hg" Befehl.',
|
||||
pythonBinaryHelpText: 'Pfad zum "python" Befehl.',
|
||||
pythonPathHelpText: 'Python Modul Suchpfad (PYTHONPATH).',
|
||||
repositoryDirectoryHelpText: 'Verzeichnis der Mercurial-Repositories.',
|
||||
useOptimizedBytecodeHelpText: 'Optimierten Bytecode verwenden (python -O).'
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// register information panel
|
||||
|
||||
initCallbacks.push(function(main){
|
||||
main.registerInfoPanel('hg', {
|
||||
checkoutTemplate: 'hg clone <a href="{0}" target="_blank">{0}</a>',
|
||||
xtype: 'repositoryExtendedInfoPanel'
|
||||
});
|
||||
});
|
||||
|
||||
// register config panel
|
||||
|
||||
registerConfigPanel({
|
||||
id: 'hgConfigForm',
|
||||
xtype : 'hgConfigPanel'
|
||||
});
|
||||
@@ -0,0 +1,82 @@
|
||||
import os
|
||||
|
||||
pythonPath = os.environ['SCM_PYTHON_PATH']
|
||||
|
||||
if len(pythonPath) > 0:
|
||||
pathParts = pythonPath.split(os.pathsep)
|
||||
for i in range(len(pathParts)):
|
||||
sys.path.insert(i, pathParts[i])
|
||||
|
||||
|
||||
from mercurial import hg, ui
|
||||
import datetime, time
|
||||
|
||||
def getName(path):
|
||||
parts = path.split('/')
|
||||
length = len(parts)
|
||||
if path.endswith('/'):
|
||||
length =- 1
|
||||
return parts[length - 1]
|
||||
|
||||
repositoryPath = os.environ['SCM_REPOSITORY_PATH']
|
||||
|
||||
revision = os.environ['SCM_REVISION']
|
||||
path = os.environ['SCM_PATH']
|
||||
name = getName(path)
|
||||
length = 0
|
||||
paths = []
|
||||
repo = hg.repository(ui.ui(), path = repositoryPath)
|
||||
mf = repo[revision].manifest()
|
||||
|
||||
if path is "":
|
||||
length = 1
|
||||
for f in mf:
|
||||
paths.append(f)
|
||||
else:
|
||||
length = len(path.split('/')) + 1
|
||||
for f in mf:
|
||||
if f.startswith(path):
|
||||
paths.append(f)
|
||||
|
||||
files = []
|
||||
directories = []
|
||||
|
||||
for p in paths:
|
||||
parts = p.split('/')
|
||||
depth = len(parts)
|
||||
if depth is length:
|
||||
file = repo[revision][p]
|
||||
files.append(file)
|
||||
elif depth > length:
|
||||
dirpath = ''
|
||||
for i in range(0, length):
|
||||
dirpath += parts[i] + '/'
|
||||
if not dirpath in directories:
|
||||
directories.append(dirpath)
|
||||
|
||||
print '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
||||
print '<browser-result>'
|
||||
print ' <revision>' + revision + '</revision>'
|
||||
# todo print tag, and branch
|
||||
print ' <files>'
|
||||
for dir in directories:
|
||||
print ' <file>'
|
||||
print ' <name>' + getName(dir) + '</name>'
|
||||
print ' <path>' + dir + '</path>'
|
||||
print ' <directory>true</directory>'
|
||||
print ' </file>'
|
||||
|
||||
for file in files:
|
||||
linkrev = repo[file.linkrev()]
|
||||
time = int(linkrev.date()[0]) * 1000
|
||||
desc = linkrev.description()
|
||||
print ' <file>'
|
||||
print ' <name>' + getName(file.path()) + '</name>'
|
||||
print ' <path>' + file.path() + '</path>'
|
||||
print ' <directory>false</directory>'
|
||||
print ' <length>' + str(file.size()) + '</length>'
|
||||
print ' <lastModified>' + str(time).split('.')[0] + '</lastModified>'
|
||||
print ' <description>' + desc + '</description>'
|
||||
print ' </file>'
|
||||
print ' </files>'
|
||||
print '</browser-result>'
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env ${python}
|
||||
|
||||
import os, sys
|
||||
pythonPath = os.environ['SCM_PYTHON_PATH']
|
||||
|
||||
if len(pythonPath) > 0:
|
||||
pathParts = pythonPath.split(os.pathsep)
|
||||
for i in range(len(pathParts)):
|
||||
sys.path.insert(i, pathParts[i])
|
||||
|
||||
repositoryPath = os.environ['SCM_REPOSITORY_PATH']
|
||||
|
||||
from mercurial import demandimport; demandimport.enable()
|
||||
from mercurial.hgweb import hgweb, wsgicgi
|
||||
application = hgweb(repositoryPath)
|
||||
wsgicgi.launch(application)
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* 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 sonia.scm.io.DefaultFileSystem;
|
||||
import sonia.scm.store.StoreFactory;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assume.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param directory
|
||||
*/
|
||||
@Override
|
||||
protected void checkDirectory(File directory)
|
||||
{
|
||||
File hgDirectory = new File(directory, ".hg");
|
||||
|
||||
assertTrue(hgDirectory.exists());
|
||||
assertTrue(hgDirectory.isDirectory());
|
||||
|
||||
File hgrc = new File(hgDirectory, "hgrc");
|
||||
|
||||
assertTrue(hgrc.exists());
|
||||
assertTrue(hgrc.isFile());
|
||||
assertTrue(hgrc.length() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param factory
|
||||
* @param directory
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected RepositoryHandler createRepositoryHandler(StoreFactory factory,
|
||||
File directory)
|
||||
{
|
||||
HgRepositoryHandler handler = new HgRepositoryHandler(factory,
|
||||
new DefaultFileSystem());
|
||||
|
||||
handler.init(contextProvider);
|
||||
handler.getConfig().setRepositoryDirectory(directory);
|
||||
|
||||
// skip tests if hg not in path
|
||||
if (! handler.isConfigured())
|
||||
{
|
||||
System.out.println("WARNING could not find hg, skipping test");
|
||||
assumeTrue(false);
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
70
scm-plugins/scm-svn-plugin/pom.xml
Normal file
70
scm-plugins/scm-svn-plugin/pom.xml
Normal file
@@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<artifactId>scm-plugins</artifactId>
|
||||
<groupId>sonia.scm.plugins</groupId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>sonia.scm.plugins</groupId>
|
||||
<artifactId>scm-svn-plugin</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
<name>scm-svn-plugin</name>
|
||||
<url>https://bitbucket.org/sdorra/scm-manager</url>
|
||||
<description>Plugin for the version control system Subversion</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>${servlet.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.tmatesoft.svnkit</groupId>
|
||||
<artifactId>svnkit-dav</artifactId>
|
||||
<version>${svnkit-dav.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>trilead-ssh2</artifactId>
|
||||
<groupId>org.tmatesoft.svnkit</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>sqljet</artifactId>
|
||||
<groupId>org.tmatesoft.sqljet</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- test scope -->
|
||||
|
||||
<dependency>
|
||||
<groupId>sonia.scm</groupId>
|
||||
<artifactId>scm-test</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<svnkit-dav.version>1.3.5.4</svnkit-dav.version>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
|
||||
<repository>
|
||||
<id>maven.scm-manager.org</id>
|
||||
<name>scm-manager release repository</name>
|
||||
<url>http://maven.scm-manager.org/nexus/content/groups/public</url>
|
||||
</repository>
|
||||
|
||||
</repositories>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* 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.RepositoryManager;
|
||||
import sonia.scm.repository.SvnConfig;
|
||||
import sonia.scm.repository.SvnRepositoryHandler;
|
||||
|
||||
//~--- 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/svn")
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public class SvnConfigResource
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param repositoryManager
|
||||
*/
|
||||
@Inject
|
||||
public SvnConfigResource(RepositoryManager repositoryManager)
|
||||
{
|
||||
repositoryHandler = (SvnRepositoryHandler) repositoryManager.getHandler(
|
||||
SvnRepositoryHandler.TYPE_NAME);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
public SvnConfig getConfig()
|
||||
{
|
||||
SvnConfig config = repositoryHandler.getConfig();
|
||||
|
||||
if (config == null)
|
||||
{
|
||||
config = new SvnConfig();
|
||||
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, SvnConfig config)
|
||||
{
|
||||
repositoryHandler.setConfig(config);
|
||||
repositoryHandler.storeConfig();
|
||||
|
||||
return Response.created(uriInfo.getRequestUri()).build();
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private SvnRepositoryHandler repositoryHandler;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public enum Compatibility
|
||||
{
|
||||
NONE(false, false, false), PRE14(true, true, true), PRE15(false, true, true),
|
||||
PRE16(false, false, true);
|
||||
|
||||
/**
|
||||
* Field description
|
||||
*
|
||||
* @param pre14Compatible
|
||||
* @param pre15Compatible
|
||||
* @param pre16Compatible
|
||||
*/
|
||||
private Compatibility(boolean pre14Compatible, boolean pre15Compatible,
|
||||
boolean pre16Compatible)
|
||||
{
|
||||
this.pre14Compatible = pre14Compatible;
|
||||
this.pre15Compatible = pre15Compatible;
|
||||
this.pre16Compatible = pre16Compatible;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isPre14Compatible()
|
||||
{
|
||||
return pre14Compatible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isPre15Compatible()
|
||||
{
|
||||
return pre15Compatible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isPre16Compatible()
|
||||
{
|
||||
return pre16Compatible;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private boolean pre14Compatible;
|
||||
|
||||
/** Field description */
|
||||
private boolean pre15Compatible;
|
||||
|
||||
/** Field description */
|
||||
private boolean pre16Compatible;
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
/**
|
||||
* 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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNLogEntry;
|
||||
import org.tmatesoft.svn.core.SVNLogEntryPath;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.io.SVNRepository;
|
||||
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
|
||||
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class SvnChangesetViewer implements ChangesetViewer
|
||||
{
|
||||
|
||||
/** the logger for SvnChangesetViewer */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(SvnChangesetViewer.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param handler
|
||||
* @param repostory
|
||||
*/
|
||||
public SvnChangesetViewer(SvnRepositoryHandler handler, Repository repostory)
|
||||
{
|
||||
this.handler = handler;
|
||||
this.repostory = repostory;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param start
|
||||
* @param max
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChangesetPagingResult getChangesets(int start, int max)
|
||||
{
|
||||
ChangesetPagingResult changesets = null;
|
||||
File directory = handler.getDirectory(repostory);
|
||||
SVNRepository repository = null;
|
||||
|
||||
try
|
||||
{
|
||||
repository = SVNRepositoryFactory.create(SVNURL.fromFile(directory));
|
||||
|
||||
long total = repository.getLatestRevision();
|
||||
long startRev = total - start;
|
||||
long endRev = total - start - (max - 1);
|
||||
|
||||
if (endRev < 0)
|
||||
{
|
||||
endRev = 0;
|
||||
}
|
||||
|
||||
List<Changeset> changesetList = new ArrayList<Changeset>();
|
||||
Collection<SVNLogEntry> entries = repository.log(new String[] { "" },
|
||||
null, startRev, endRev, true, true);
|
||||
|
||||
for (SVNLogEntry entry : entries)
|
||||
{
|
||||
changesetList.add(createChangeset(entry));
|
||||
}
|
||||
|
||||
changesets = new ChangesetPagingResult((int) total, changesetList);
|
||||
}
|
||||
catch (SVNException ex)
|
||||
{
|
||||
logger.error("could not open repository", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
repository.closeSession();
|
||||
}
|
||||
|
||||
return changesets;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* TODO: type replaced
|
||||
*
|
||||
*
|
||||
* @param modifications
|
||||
* @param entry
|
||||
*/
|
||||
private void appendModification(Modifications modifications,
|
||||
SVNLogEntryPath entry)
|
||||
{
|
||||
switch (entry.getType())
|
||||
{
|
||||
case SVNLogEntryPath.TYPE_ADDED :
|
||||
modifications.getAdded().add(entry.getPath());
|
||||
|
||||
break;
|
||||
|
||||
case SVNLogEntryPath.TYPE_DELETED :
|
||||
modifications.getRemoved().add(entry.getPath());
|
||||
|
||||
break;
|
||||
|
||||
case SVNLogEntryPath.TYPE_MODIFIED :
|
||||
modifications.getModified().add(entry.getPath());
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param entry
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Changeset createChangeset(SVNLogEntry entry)
|
||||
{
|
||||
Changeset changeset = new Changeset(String.valueOf(entry.getRevision()),
|
||||
entry.getDate().getTime(),
|
||||
Person.toPerson(entry.getAuthor()),
|
||||
entry.getMessage());
|
||||
Map<String, SVNLogEntryPath> changeMap = entry.getChangedPaths();
|
||||
|
||||
if (Util.isNotEmpty(changeMap))
|
||||
{
|
||||
Modifications modifications = changeset.getModifications();
|
||||
|
||||
for (SVNLogEntryPath e : changeMap.values())
|
||||
{
|
||||
appendModification(modifications, e);
|
||||
}
|
||||
}
|
||||
|
||||
return changeset;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private SvnRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private Repository repostory;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* 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 SvnConfig extends SimpleRepositoryConfig
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Compatibility getCompatibility()
|
||||
{
|
||||
if (compatibility == null)
|
||||
{
|
||||
compatibility = Compatibility.NONE;
|
||||
}
|
||||
|
||||
return compatibility;
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param compatibility
|
||||
*/
|
||||
public void setCompatibility(Compatibility compatibility)
|
||||
{
|
||||
this.compatibility = compatibility;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Compatibility compatibility = Compatibility.NONE;
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
/**
|
||||
* 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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.tmatesoft.svn.core.SVNDirEntry;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNNodeKind;
|
||||
import org.tmatesoft.svn.core.SVNProperties;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.io.SVNRepository;
|
||||
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
|
||||
|
||||
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.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class SvnRepositoryBrowser implements RepositoryBrowser
|
||||
{
|
||||
|
||||
/** the logger for SvnRepositoryBrowser */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(SvnRepositoryBrowser.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param handler
|
||||
* @param repository
|
||||
*/
|
||||
public SvnRepositoryBrowser(SvnRepositoryHandler handler,
|
||||
Repository repository)
|
||||
{
|
||||
this.handler = handler;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* http://wiki.svnkit.com/Printing_Out_File_Contents
|
||||
*
|
||||
*
|
||||
* @param revision
|
||||
* @param path
|
||||
* @param output
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Override
|
||||
public void getContent(String revision, String path, OutputStream output)
|
||||
throws IOException, RepositoryException
|
||||
{
|
||||
long revisionNumber = getRevisionNumber(revision);
|
||||
SVNRepository svnRepository = null;
|
||||
|
||||
try
|
||||
{
|
||||
svnRepository = getSvnRepository();
|
||||
svnRepository.getFile(path, revisionNumber, new SVNProperties(), output);
|
||||
}
|
||||
catch (SVNException ex)
|
||||
{
|
||||
logger.error("could not open repository", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
close(svnRepository);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param revision
|
||||
* @param path
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Override
|
||||
public BrowserResult getResult(String revision, String path)
|
||||
throws IOException, RepositoryException
|
||||
{
|
||||
long revisionNumber = getRevisionNumber(revision);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("browser repository {} in path {} at revision {}",
|
||||
new Object[] { repository.getName(),
|
||||
path, revision });
|
||||
}
|
||||
|
||||
BrowserResult result = null;
|
||||
SVNRepository svnRepository = null;
|
||||
|
||||
try
|
||||
{
|
||||
svnRepository = getSvnRepository();
|
||||
|
||||
Collection<SVNDirEntry> entries =
|
||||
svnRepository.getDir(Util.nonNull(path), revisionNumber, null,
|
||||
(Collection) null);
|
||||
List<FileObject> children = new ArrayList<FileObject>();
|
||||
String basePath = Util.EMPTY_STRING;
|
||||
|
||||
if (Util.isNotEmpty(path))
|
||||
{
|
||||
basePath = path;
|
||||
|
||||
if (!basePath.endsWith("/"))
|
||||
{
|
||||
basePath = basePath.concat("/");
|
||||
}
|
||||
}
|
||||
|
||||
for (SVNDirEntry entry : entries)
|
||||
{
|
||||
children.add(createFileObject(entry, basePath));
|
||||
}
|
||||
|
||||
result = new BrowserResult();
|
||||
result.setRevision(revision);
|
||||
result.setFiles(children);
|
||||
}
|
||||
catch (SVNException ex)
|
||||
{
|
||||
logger.error("could not open repository", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
close(svnRepository);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param svnRepository
|
||||
*/
|
||||
private void close(SVNRepository svnRepository)
|
||||
{
|
||||
if (svnRepository != null)
|
||||
{
|
||||
svnRepository.closeSession();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param entry
|
||||
* @param path
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private FileObject createFileObject(SVNDirEntry entry, String path)
|
||||
{
|
||||
FileObject fileObject = new FileObject();
|
||||
|
||||
fileObject.setName(entry.getName());
|
||||
fileObject.setPath(path.concat(entry.getRelativePath()));
|
||||
fileObject.setDirectory(entry.getKind() == SVNNodeKind.DIR);
|
||||
|
||||
if (entry.getDate() != null)
|
||||
{
|
||||
fileObject.setLastModified(entry.getDate().getTime());
|
||||
}
|
||||
|
||||
fileObject.setLength(entry.getSize());
|
||||
fileObject.setDescription(entry.getCommitMessage());
|
||||
|
||||
return fileObject;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param revision
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
private long getRevisionNumber(String revision) throws RepositoryException
|
||||
{
|
||||
long revisionNumber = -1;
|
||||
|
||||
if (Util.isNotEmpty(revision))
|
||||
{
|
||||
try
|
||||
{
|
||||
revisionNumber = Long.parseLong(revision);
|
||||
}
|
||||
catch (NumberFormatException ex)
|
||||
{
|
||||
throw new RepositoryException("given revision is not a svnrevision");
|
||||
}
|
||||
}
|
||||
|
||||
return revisionNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws SVNException
|
||||
*/
|
||||
private SVNRepository getSvnRepository() throws SVNException
|
||||
{
|
||||
File directory = handler.getDirectory(repository);
|
||||
|
||||
return SVNRepositoryFactory.create(SVNURL.fromFile(directory));
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private SvnRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private Repository repository;
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/**
|
||||
* 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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory;
|
||||
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
|
||||
|
||||
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 SvnRepositoryHandler
|
||||
extends AbstractSimpleRepositoryHandler<SvnConfig>
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String TYPE_DISPLAYNAME = "Subversion";
|
||||
|
||||
/** Field description */
|
||||
public static final String TYPE_NAME = "svn";
|
||||
|
||||
/** Field description */
|
||||
public static final Type TYPE = new Type(TYPE_NAME, TYPE_DISPLAYNAME);
|
||||
|
||||
/** the logger for SvnRepositoryHandler */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(SvnRepositoryHandler.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param storeFactory
|
||||
* @param fileSystem
|
||||
*/
|
||||
@Inject
|
||||
public SvnRepositoryHandler(StoreFactory storeFactory, FileSystem fileSystem)
|
||||
{
|
||||
super(storeFactory, fileSystem);
|
||||
|
||||
// setup FSRepositoryFactory for SvnRepositoryBrowser
|
||||
FSRepositoryFactory.setup();
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChangesetViewer getChangesetViewer(Repository repository)
|
||||
{
|
||||
SvnChangesetViewer changesetViewer = null;
|
||||
|
||||
AssertUtil.assertIsNotNull(repository);
|
||||
|
||||
String type = repository.getType();
|
||||
|
||||
AssertUtil.assertIsNotEmpty(type);
|
||||
|
||||
if (TYPE_NAME.equals(type))
|
||||
{
|
||||
changesetViewer = new SvnChangesetViewer(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 SvnRepositoryBrowser(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
|
||||
{
|
||||
Compatibility comp = config.getCompatibility();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
StringBuilder log = new StringBuilder("create svn repository \"");
|
||||
|
||||
log.append(directory.getName()).append("\": pre14Compatible=");
|
||||
log.append(comp.isPre14Compatible()).append(", pre15Compatible=");
|
||||
log.append(comp.isPre15Compatible()).append(", pre16Compatible=");
|
||||
log.append(comp.isPre16Compatible());
|
||||
logger.debug(log.toString());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
SVNRepositoryFactory.createLocalRepository(directory, null, true, false,
|
||||
comp.isPre14Compatible(), comp.isPre15Compatible(),
|
||||
comp.isPre16Compatible());
|
||||
}
|
||||
catch (SVNException ex)
|
||||
{
|
||||
throw new RepositoryException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected SvnConfig createInitialConfig()
|
||||
{
|
||||
return new SvnConfig();
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected Class<SvnConfig> getConfigClass()
|
||||
{
|
||||
return SvnConfig.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
/**
|
||||
* 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.tmatesoft.svn.core.internal.server.dav.DAVConfig;
|
||||
import org.tmatesoft.svn.core.internal.server.dav.SVNPathBasedAccess;
|
||||
|
||||
import sonia.scm.repository.SvnConfig;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class SvnDAVConfig extends DAVConfig
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param davConfig
|
||||
* @param config
|
||||
*/
|
||||
public SvnDAVConfig(DAVConfig davConfig, SvnConfig config)
|
||||
{
|
||||
this.davConfig = davConfig;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getActivitiesDBPath()
|
||||
{
|
||||
return davConfig.getActivitiesDBPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getRepositoryName()
|
||||
{
|
||||
return davConfig.getRepositoryName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getRepositoryParentPath()
|
||||
{
|
||||
return config.getRepositoryDirectory().getAbsolutePath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getRepositoryPath()
|
||||
{
|
||||
return davConfig.getRepositoryPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public SVNPathBasedAccess getSVNAccess()
|
||||
{
|
||||
return davConfig.getSVNAccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getXSLTIndex()
|
||||
{
|
||||
return davConfig.getXSLTIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isAllowBulkUpdates()
|
||||
{
|
||||
return davConfig.isAllowBulkUpdates();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isAllowDepthInfinity()
|
||||
{
|
||||
return davConfig.isAllowDepthInfinity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isAnonymousAllowed()
|
||||
{
|
||||
return davConfig.isAnonymousAllowed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isAutoVersioning()
|
||||
{
|
||||
return davConfig.isAutoVersioning();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isListParentPath()
|
||||
{
|
||||
return davConfig.isListParentPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isNoAuthIfAnonymousAllowed()
|
||||
{
|
||||
return davConfig.isNoAuthIfAnonymousAllowed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isUsingPBA()
|
||||
{
|
||||
return davConfig.isUsingPBA();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isUsingRepositoryPathDirective()
|
||||
{
|
||||
return davConfig.isUsingRepositoryPathDirective();
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private SvnConfig config;
|
||||
|
||||
/** Field description */
|
||||
private DAVConfig davConfig;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* 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.tmatesoft.svn.core.internal.server.dav.DAVConfig;
|
||||
import org.tmatesoft.svn.core.internal.server.dav.DAVServlet;
|
||||
|
||||
import sonia.scm.repository.SvnRepositoryHandler;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Singleton
|
||||
public class SvnDAVServlet extends DAVServlet
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
private static final long serialVersionUID = -1462257085465785945L;
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param handler
|
||||
*/
|
||||
@Inject
|
||||
public SvnDAVServlet(SvnRepositoryHandler handler)
|
||||
{
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected DAVConfig getDAVConfig()
|
||||
{
|
||||
return new SvnDAVConfig(super.getDAVConfig(), handler.getConfig());
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private SvnRepositoryHandler handler;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* 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.RepositoryManager;
|
||||
import sonia.scm.repository.SvnRepositoryHandler;
|
||||
import sonia.scm.web.filter.RegexPermissionFilter;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Singleton
|
||||
public class SvnPermissionFilter extends RegexPermissionFilter
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
private static Set<String> WRITEMETHOD_SET =
|
||||
new HashSet<String>(Arrays.asList("MKACTIVITY", "PROPPATCH", "PUT",
|
||||
"CHECKOUT", "MKCOL", "MOVE", "COPY", "DELETE", "LOCK", "UNLOCK",
|
||||
"MERGE"));
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param securityContextProvider
|
||||
* @param repositoryManager
|
||||
*/
|
||||
@Inject
|
||||
public SvnPermissionFilter(
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryManager repositoryManager)
|
||||
{
|
||||
super(securityContextProvider, repositoryManager);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected String getType()
|
||||
{
|
||||
return SvnRepositoryHandler.TYPE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected boolean isWriteRequest(HttpServletRequest request)
|
||||
{
|
||||
return WRITEMETHOD_SET.contains(request.getMethod().toUpperCase());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* 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.web.filter.BasicAuthenticationFilter;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import sonia.scm.plugin.ext.Extension;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Extension
|
||||
public class SvnServletModule extends ServletModule
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String PARAMETER_SVN_PARENTPATH = "SVNParentPath";
|
||||
|
||||
/** Field description */
|
||||
public static final String PATTERN_SVN = "/svn/*";
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
protected void configureServlets()
|
||||
{
|
||||
filter(PATTERN_SVN).through(BasicAuthenticationFilter.class);
|
||||
filter(PATTERN_SVN).through(SvnPermissionFilter.class);
|
||||
|
||||
Map<String, String> parameters = new HashMap<String, String>();
|
||||
|
||||
parameters.put(PARAMETER_SVN_PARENTPATH,
|
||||
System.getProperty("java.io.tmpdir"));
|
||||
serve(PATTERN_SVN).with(SvnDAVServlet.class, parameters);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
|
||||
-->
|
||||
|
||||
<!--
|
||||
Document : plugin.xml
|
||||
Created on : October 12, 2010, 8:29 AM
|
||||
Author : sdorra
|
||||
Description:
|
||||
Purpose of the document follows.
|
||||
-->
|
||||
|
||||
<plugin>
|
||||
|
||||
<information>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>${project.artifactId}</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<name>${project.name}</name>
|
||||
<description>${project.description}</description>
|
||||
<author>Sebastian Sdorra</author>
|
||||
<url>${project.url}</url>
|
||||
</information>
|
||||
|
||||
<conditions>
|
||||
<min-version>1.1</min-version>
|
||||
</conditions>
|
||||
|
||||
<resources>
|
||||
<script>/sonia/scm/svn.config.js</script>
|
||||
</resources>
|
||||
|
||||
</plugin>
|
||||
@@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
Ext.ns("Sonia.svn");
|
||||
|
||||
Sonia.svn.ConfigPanel = Ext.extend(Sonia.config.SimpleConfigForm, {
|
||||
|
||||
// labels
|
||||
titleText: 'Subversion Settings',
|
||||
repositoryDirectoryText: 'Repository directory',
|
||||
noneCompatibility: 'No compatibility modus',
|
||||
pre14CompatibleText: 'Pre 1.4 Compatible',
|
||||
pre15CompatibleText: 'Pre 1.5 Compatible',
|
||||
pre16CompatibleText: 'Pre 1.6 Compatible',
|
||||
|
||||
// helpTexts
|
||||
repositoryDirectoryHelpText: 'Location of the Suberversion repositories.',
|
||||
|
||||
initComponent: function(){
|
||||
|
||||
var config = {
|
||||
title : this.titleText,
|
||||
configUrl: restUrl + 'config/repositories/svn.json',
|
||||
items : [{
|
||||
xtype: 'textfield',
|
||||
name: 'repositoryDirectory',
|
||||
fieldLabel: this.repositoryDirectoryText,
|
||||
helpText: this.repositoryDirectoryHelpText,
|
||||
allowBlank : false
|
||||
},{
|
||||
xtype: 'radiogroup',
|
||||
name: 'compatibility',
|
||||
columns: 1,
|
||||
items: [{
|
||||
boxLabel: this.noneCompatibility,
|
||||
inputValue: 'NONE',
|
||||
name: 'compatibility'
|
||||
},{
|
||||
boxLabel: this.pre14CompatibleText,
|
||||
inputValue: 'PRE14',
|
||||
name: 'compatibility'
|
||||
},{
|
||||
boxLabel: this.pre15CompatibleText,
|
||||
inputValue: 'PRE15',
|
||||
name: 'compatibility'
|
||||
},{
|
||||
boxLabel: this.pre16CompatibleText,
|
||||
inputValue: 'PRE16',
|
||||
name: 'compatibility'
|
||||
}]
|
||||
}]
|
||||
}
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
Sonia.svn.ConfigPanel.superclass.initComponent.apply(this, arguments);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Ext.reg("svnConfigPanel", Sonia.svn.ConfigPanel);
|
||||
|
||||
// i18n
|
||||
|
||||
if ( i18n != null && i18n.country == 'de' ){
|
||||
|
||||
Ext.override(Sonia.svn.ConfigPanel, {
|
||||
|
||||
// labels
|
||||
titleText: 'Subversion Einstellungen',
|
||||
repositoryDirectoryText: 'Repository-Verzeichnis',
|
||||
noneCompatibility: 'Kein Kompatiblitätsmodus',
|
||||
pre14CompatibleText: 'Mit Versionen vor 1.4 kompatibel',
|
||||
pre15CompatibleText: 'Mit Versionen vor 1.5 kompatibel',
|
||||
pre16CompatibleText: 'Mit Versionen vor 1.6 kompatibel',
|
||||
|
||||
// helpTexts
|
||||
repositoryDirectoryHelpText: 'Verzeichnis der Subversion-Repositories.'
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// register information panel
|
||||
|
||||
initCallbacks.push(function(main){
|
||||
main.registerInfoPanel('svn', {
|
||||
checkoutTemplate: 'svn checkout <a href="{0}" target="_blank">{0}</a>',
|
||||
xtype: 'repositoryExtendedInfoPanel'
|
||||
});
|
||||
});
|
||||
|
||||
// register panel
|
||||
|
||||
registerConfigPanel({
|
||||
xtype : 'svnConfigPanel'
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* 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 sonia.scm.io.DefaultFileSystem;
|
||||
import sonia.scm.store.StoreFactory;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class SvnRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param directory
|
||||
*/
|
||||
@Override
|
||||
protected void checkDirectory(File directory)
|
||||
{
|
||||
File format = new File(directory, "format");
|
||||
|
||||
assertTrue(format.exists());
|
||||
assertTrue(format.isFile());
|
||||
|
||||
File db = new File(directory, "db");
|
||||
|
||||
assertTrue(db.exists());
|
||||
assertTrue(db.isDirectory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param factory
|
||||
* @param directory
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected RepositoryHandler createRepositoryHandler(StoreFactory factory,
|
||||
File directory)
|
||||
{
|
||||
SvnRepositoryHandler handler = new SvnRepositoryHandler(factory,
|
||||
new DefaultFileSystem());
|
||||
|
||||
handler.init(contextProvider);
|
||||
|
||||
SvnConfig config = new SvnConfig();
|
||||
|
||||
config.setRepositoryDirectory(directory);
|
||||
handler.setConfig(config);
|
||||
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user