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

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

View File

@@ -0,0 +1,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;
}

View File

@@ -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();
}
}

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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");
}

View File

@@ -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;
}

View File

@@ -0,0 +1,176 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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");
}
}

View File

@@ -0,0 +1,67 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.web;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.servlet.ServletModule;
import sonia.scm.plugin.ext.Extension;
import sonia.scm.web.filter.BasicAuthenticationFilter;
/**
*
* @author Sebastian Sdorra
*/
@Extension
public class 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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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}'
});
}

View File

@@ -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'
});

View File

@@ -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>'

View File

@@ -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)

View File

@@ -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;
}
}