mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-08 22:45:45 +01:00
move core plugins back to main repository, because of a broken release management
This commit is contained in:
@@ -0,0 +1,351 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.api.rest.resources;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import sonia.scm.SCMContext;
|
||||
import sonia.scm.cache.CacheManager;
|
||||
import sonia.scm.installer.HgInstallerFactory;
|
||||
import sonia.scm.installer.HgPackage;
|
||||
import sonia.scm.installer.HgPackageReader;
|
||||
import sonia.scm.installer.HgPackages;
|
||||
import sonia.scm.net.HttpClient;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.web.HgWebConfigWriter;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Singleton
|
||||
@Path("config/repositories/hg")
|
||||
public class HgConfigResource
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param client
|
||||
* @param handler
|
||||
* @param cacheManager
|
||||
*/
|
||||
@Inject
|
||||
public HgConfigResource(HttpClient client, HgRepositoryHandler handler,
|
||||
CacheManager cacheManager)
|
||||
{
|
||||
this.client = client;
|
||||
this.handler = handler;
|
||||
this.pkgReader = new HgPackageReader(cacheManager);
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param uriInfo
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@POST
|
||||
@Path("auto-configuration")
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public HgConfig autoConfiguration(@Context UriInfo uriInfo)
|
||||
{
|
||||
return autoConfiguration(uriInfo, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param uriInfo
|
||||
* @param config
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@POST
|
||||
@Path("auto-configuration")
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public HgConfig autoConfiguration(@Context UriInfo uriInfo, HgConfig config)
|
||||
{
|
||||
if (config == null)
|
||||
{
|
||||
config = new HgConfig();
|
||||
}
|
||||
|
||||
handler.doAutoConfiguration(config);
|
||||
|
||||
return handler.getConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@POST
|
||||
@Path("packages/{pkgId}")
|
||||
public Response installPackage(@PathParam("pkgId") String id)
|
||||
{
|
||||
Response response = null;
|
||||
HgPackage pkg = pkgReader.getPackage(id);
|
||||
|
||||
if (pkg != null)
|
||||
{
|
||||
if (HgInstallerFactory.createInstaller().installPackage(client, handler,
|
||||
SCMContext.getContext().getBaseDirectory(), pkg))
|
||||
{
|
||||
response = Response.noContent().build();
|
||||
}
|
||||
else
|
||||
{
|
||||
response =
|
||||
Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response = Response.status(Response.Status.NOT_FOUND).build();
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public HgConfig getConfig()
|
||||
{
|
||||
HgConfig config = handler.getConfig();
|
||||
|
||||
if (config == null)
|
||||
{
|
||||
config = new HgConfig();
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Path("installations/hg")
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public InstallationsResponse getHgInstallations()
|
||||
{
|
||||
List<String> installations =
|
||||
HgInstallerFactory.createInstaller().getHgInstallations();
|
||||
|
||||
return new InstallationsResponse(installations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Path("packages")
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public HgPackages getPackages()
|
||||
{
|
||||
return pkgReader.getPackages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Path("installations/python")
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public InstallationsResponse getPythonInstallations()
|
||||
{
|
||||
List<String> installations =
|
||||
HgInstallerFactory.createInstaller().getPythonInstallations();
|
||||
|
||||
return new InstallationsResponse(installations);
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param uriInfo
|
||||
* @param config
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public Response setConfig(@Context UriInfo uriInfo, HgConfig config)
|
||||
throws IOException
|
||||
{
|
||||
handler.setConfig(config);
|
||||
handler.storeConfig();
|
||||
new HgWebConfigWriter(config).write();
|
||||
|
||||
return Response.created(uriInfo.getRequestUri()).build();
|
||||
}
|
||||
|
||||
//~--- inner classes --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class description
|
||||
*
|
||||
*
|
||||
* @version Enter version here..., 11/04/25
|
||||
* @author Enter your name here...
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlRootElement(name = "installations")
|
||||
public static class InstallationsResponse
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*/
|
||||
public InstallationsResponse() {}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param paths
|
||||
*/
|
||||
public InstallationsResponse(List<String> paths)
|
||||
{
|
||||
this.paths = paths;
|
||||
}
|
||||
|
||||
//~--- get methods --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<String> getPaths()
|
||||
{
|
||||
return paths;
|
||||
}
|
||||
|
||||
//~--- set methods --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param paths
|
||||
*/
|
||||
public void setPaths(List<String> paths)
|
||||
{
|
||||
this.paths = paths;
|
||||
}
|
||||
|
||||
//~--- fields -------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "path")
|
||||
private List<String> paths;
|
||||
}
|
||||
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private HttpClient client;
|
||||
|
||||
/** Field description */
|
||||
private HgRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private HgPackageReader pkgReader;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.net.HttpClient;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public abstract class AbstractHgInstaller implements HgInstaller
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String DIRECTORY_REPOSITORY = "repositories";
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public void install(File baseDirectory, HgConfig config) throws IOException
|
||||
{
|
||||
File repoDirectory = new File(
|
||||
baseDirectory,
|
||||
DIRECTORY_REPOSITORY.concat(File.separator).concat(
|
||||
HgRepositoryHandler.TYPE_NAME));
|
||||
|
||||
IOUtil.mkdirs(repoDirectory);
|
||||
config.setRepositoryDirectory(repoDirectory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param client
|
||||
* @param handler
|
||||
* @param baseDirectory
|
||||
* @param pkg
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean installPackage(HttpClient client, HgRepositoryHandler handler,
|
||||
File baseDirectory, HgPackage pkg)
|
||||
{
|
||||
return new HgPackageInstaller(client, handler, baseDirectory,
|
||||
pkg).install();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.net.HttpClient;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public interface HgInstaller
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void install(File baseDirectory, HgConfig config) throws IOException;
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param client
|
||||
* @param handler
|
||||
* @param baseDirectory
|
||||
* @param pkg
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean installPackage(HttpClient client, HgRepositoryHandler handler,
|
||||
File baseDirectory, HgPackage pkg);
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void update(File baseDirectory, HgConfig config) throws IOException;
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<String> getHgInstallations();
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<String> getPythonInstallations();
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.util.SystemUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgInstallerFactory
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static HgInstaller createInstaller()
|
||||
{
|
||||
HgInstaller installer = null;
|
||||
|
||||
if (SystemUtil.isWindows())
|
||||
{
|
||||
installer = new WindowsHgInstaller();
|
||||
}
|
||||
else
|
||||
{
|
||||
installer = new UnixHgInstaller();
|
||||
}
|
||||
|
||||
return installer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.repository.HgConfig;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@XmlRootElement(name = "package")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class HgPackage
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getArch()
|
||||
{
|
||||
return arch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public HgConfig getHgConfigTemplate()
|
||||
{
|
||||
return hgConfigTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getHgVersion()
|
||||
{
|
||||
return hgVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPlatform()
|
||||
{
|
||||
return platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPythonVersion()
|
||||
{
|
||||
return pythonVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public long getSize()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getUrl()
|
||||
{
|
||||
return url;
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param arch
|
||||
*/
|
||||
public void setArch(String arch)
|
||||
{
|
||||
this.arch = arch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param hgConfigTemplate
|
||||
*/
|
||||
public void setHgConfigTemplate(HgConfig hgConfigTemplate)
|
||||
{
|
||||
this.hgConfigTemplate = hgConfigTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param hgVersion
|
||||
*/
|
||||
public void setHgVersion(String hgVersion)
|
||||
{
|
||||
this.hgVersion = hgVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
public void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param platform
|
||||
*/
|
||||
public void setPlatform(String platform)
|
||||
{
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param pythonVersion
|
||||
*/
|
||||
public void setPythonVersion(String pythonVersion)
|
||||
{
|
||||
this.pythonVersion = pythonVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param size
|
||||
*/
|
||||
public void setSize(long size)
|
||||
{
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
public void setUrl(String url)
|
||||
{
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private String arch;
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "hg-config-template")
|
||||
private HgConfig hgConfigTemplate;
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "hg-version")
|
||||
private String hgVersion;
|
||||
|
||||
/** Field description */
|
||||
private String id;
|
||||
|
||||
/** Field description */
|
||||
private String platform;
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "python-version")
|
||||
private String pythonVersion;
|
||||
|
||||
/** Field description */
|
||||
private long size;
|
||||
|
||||
/** Field description */
|
||||
private String url;
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.io.ZipUnArchiver;
|
||||
import sonia.scm.net.HttpClient;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgPackageInstaller implements Runnable
|
||||
{
|
||||
|
||||
/** the logger for HgPackageInstaller */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(HgPackageInstaller.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param client
|
||||
* @param handler
|
||||
* @param baseDirectory
|
||||
* @param pkg
|
||||
*/
|
||||
public HgPackageInstaller(HttpClient client, HgRepositoryHandler handler,
|
||||
File baseDirectory, HgPackage pkg)
|
||||
{
|
||||
this.client = client;
|
||||
this.handler = handler;
|
||||
this.baseDirectory = baseDirectory;
|
||||
this.pkg = pkg;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean install()
|
||||
{
|
||||
boolean success = false;
|
||||
File downloadedFile = downloadFile();
|
||||
|
||||
if ((downloadedFile != null) && downloadedFile.exists())
|
||||
{
|
||||
File directory = extractPackage(downloadedFile);
|
||||
|
||||
if ((directory != null) && directory.exists())
|
||||
{
|
||||
updateConfig(directory);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (!install())
|
||||
{
|
||||
logger.error("installation of pkg {} failed", pkg.getId());
|
||||
}
|
||||
else if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info("successfully installed pkg {}", pkg.getId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private File downloadFile()
|
||||
{
|
||||
File file = null;
|
||||
InputStream input = null;
|
||||
OutputStream output = null;
|
||||
|
||||
try
|
||||
{
|
||||
file = File.createTempFile("scm-hg-", ".pkg");
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("download package to {}", file.getAbsolutePath());
|
||||
}
|
||||
|
||||
// TODO error handling
|
||||
input = client.get(pkg.getUrl()).getContent();
|
||||
output = new FileOutputStream(file);
|
||||
IOUtil.copy(input, output);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.error("could not downlaod file ".concat(pkg.getUrl()), ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(input);
|
||||
IOUtil.close(output);
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param file
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private File extractPackage(File file)
|
||||
{
|
||||
File directory = new File(baseDirectory,
|
||||
"pkg".concat(File.separator).concat(pkg.getId()));
|
||||
|
||||
IOUtil.mkdirs(directory);
|
||||
|
||||
try
|
||||
{
|
||||
IOUtil.extract(file, directory, ZipUnArchiver.EXTENSION);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
directory = null;
|
||||
logger.error("could not extract pacakge ".concat(pkg.getId()), ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
// delete temp file
|
||||
try
|
||||
{
|
||||
IOUtil.delete(file, true);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.error(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param directory
|
||||
*/
|
||||
private void updateConfig(File directory)
|
||||
{
|
||||
String path = directory.getAbsolutePath();
|
||||
HgConfig template = pkg.getHgConfigTemplate();
|
||||
HgConfig config = handler.getConfig();
|
||||
|
||||
config.setHgBinary(getTemplateValue(template.getHgBinary(), path));
|
||||
config.setPythonBinary(getTemplateValue(template.getPythonBinary(), path));
|
||||
config.setPythonPath(getTemplateValue(template.getPythonPath(), path));
|
||||
config.setUseOptimizedBytecode(template.isUseOptimizedBytecode());
|
||||
handler.storeConfig();
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param template
|
||||
* @param path
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getTemplateValue(String template, String path)
|
||||
{
|
||||
String result = null;
|
||||
|
||||
if (template != null)
|
||||
{
|
||||
result = MessageFormat.format(template, path);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private File baseDirectory;
|
||||
|
||||
/** Field description */
|
||||
private HttpClient client;
|
||||
|
||||
/** Field description */
|
||||
private HgRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private HgPackage pkg;
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.PlatformType;
|
||||
import sonia.scm.cache.Cache;
|
||||
import sonia.scm.cache.CacheManager;
|
||||
import sonia.scm.util.IOUtil;
|
||||
import sonia.scm.util.SystemUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import javax.xml.bind.JAXB;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgPackageReader
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String CACHENAME = "sonia.scm.hg.packages";
|
||||
|
||||
/** Field description */
|
||||
public static final String PACKAGEURL =
|
||||
"http://download.scm-manager.org/pkg/mercurial/packages.xml.gz";
|
||||
|
||||
/** the logger for HgPackageReader */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(HgPackageReader.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param cacheManager
|
||||
*/
|
||||
public HgPackageReader(CacheManager cacheManager)
|
||||
{
|
||||
cache = cacheManager.getCache(String.class, HgPackages.class, CACHENAME);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public HgPackage getPackage(String id)
|
||||
{
|
||||
HgPackage pkg = null;
|
||||
|
||||
for (HgPackage p : getPackages())
|
||||
{
|
||||
if (id.equals(p.getId()))
|
||||
{
|
||||
pkg = p;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pkg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public HgPackages getPackages()
|
||||
{
|
||||
HgPackages packages = cache.get(HgPackages.class.getName());
|
||||
|
||||
if (packages == null)
|
||||
{
|
||||
packages = getRemptePackages();
|
||||
filterPackage(packages);
|
||||
cache.put(HgPackages.class.getName(), packages);
|
||||
}
|
||||
|
||||
return packages;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param packages
|
||||
*/
|
||||
private void filterPackage(HgPackages packages)
|
||||
{
|
||||
List<HgPackage> pkgList = new ArrayList<HgPackage>();
|
||||
|
||||
for (HgPackage pkg : packages)
|
||||
{
|
||||
boolean add = true;
|
||||
|
||||
if (Util.isNotEmpty(pkg.getPlatform()))
|
||||
{
|
||||
PlatformType pt = PlatformType.createPlatformType(pkg.getPlatform());
|
||||
|
||||
if (SystemUtil.getPlatform().getType() != pt)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("reject package {}, because of wrong platform {}",
|
||||
pkg.getId(), pkg.getPlatform());
|
||||
}
|
||||
|
||||
add = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (add && Util.isNotEmpty(pkg.getArch()))
|
||||
{
|
||||
if (!SystemUtil.getArch().equals(pkg.getArch()))
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("reject package {}, because of wrong arch {}",
|
||||
pkg.getId(), pkg.getArch());
|
||||
}
|
||||
|
||||
add = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (add)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("added HgPackage {}", pkg.getId());
|
||||
}
|
||||
|
||||
pkgList.add(pkg);
|
||||
}
|
||||
}
|
||||
|
||||
packages.setPackages(pkgList);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private HgPackages getRemptePackages()
|
||||
{
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info("fetch HgPackages from {}", PACKAGEURL);
|
||||
}
|
||||
|
||||
HgPackages packages = null;
|
||||
InputStream input = null;
|
||||
|
||||
try
|
||||
{
|
||||
URL url = new URL(PACKAGEURL);
|
||||
|
||||
if (PACKAGEURL.endsWith(".gz"))
|
||||
{
|
||||
input = new GZIPInputStream(url.openStream());
|
||||
}
|
||||
else
|
||||
{
|
||||
input = url.openStream();
|
||||
}
|
||||
|
||||
packages = JAXB.unmarshal(input, HgPackages.class);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.error("could not read HgPackages from {}", PACKAGEURL);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(input);
|
||||
}
|
||||
|
||||
if (packages == null)
|
||||
{
|
||||
packages = new HgPackages();
|
||||
packages.setPackages(new ArrayList<HgPackage>());
|
||||
}
|
||||
|
||||
return packages;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Cache<String, HgPackages> cache;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.installer;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@XmlRootElement(name = "packages")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class HgPackages implements Iterable<HgPackage>
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Iterator<HgPackage> iterator()
|
||||
{
|
||||
return packages.iterator();
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<HgPackage> getPackages()
|
||||
{
|
||||
return packages;
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param packages
|
||||
*/
|
||||
public void setPackages(List<HgPackage> packages)
|
||||
{
|
||||
this.packages = packages;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "package")
|
||||
private List<HgPackage> packages;
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.util.IOUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class UnixHgInstaller extends AbstractHgInstaller
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String COMMAND_HG = "hg";
|
||||
|
||||
/** Field description */
|
||||
public static final String COMMAND_PYTHON = "python";
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public void install(File baseDirectory, HgConfig config) throws IOException
|
||||
{
|
||||
super.install(baseDirectory, config);
|
||||
|
||||
// search mercurial (hg)
|
||||
|
||||
if (Util.isEmpty(config.getHgBinary()))
|
||||
{
|
||||
String hg = IOUtil.search(COMMAND_HG);
|
||||
|
||||
if (Util.isNotEmpty(hg))
|
||||
{
|
||||
config.setHgBinary(hg);
|
||||
|
||||
// search python in the same folder
|
||||
File hgFile = new File(hg);
|
||||
|
||||
if (hgFile.exists())
|
||||
{
|
||||
File pythonFile = new File(hgFile.getParentFile(), COMMAND_PYTHON);
|
||||
|
||||
if (pythonFile.exists())
|
||||
{
|
||||
config.setPythonBinary(pythonFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// search python
|
||||
|
||||
if (Util.isEmpty(config.getPythonBinary()))
|
||||
{
|
||||
config.setPythonBinary(IOUtil.search(COMMAND_PYTHON));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
*/
|
||||
@Override
|
||||
public void update(File baseDirectory, HgConfig config)
|
||||
{
|
||||
|
||||
// do nothing
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<String> getHgInstallations()
|
||||
{
|
||||
return IOUtil.searchAll(COMMAND_HG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<String> getPythonInstallations()
|
||||
{
|
||||
return IOUtil.searchAll(COMMAND_PYTHON);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,428 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.installer;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.util.IOUtil;
|
||||
import sonia.scm.util.RegistryUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class WindowsHgInstaller extends AbstractHgInstaller
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
private static final String FILE_LIBRARY_ZIP = "library.zip";
|
||||
|
||||
/** Field description */
|
||||
private static final String FILE_LIB_MERCURIAL =
|
||||
"Lib\\site-packages\\mercurial";
|
||||
|
||||
/** Field description */
|
||||
private static final String FILE_MERCURIAL_EXE = "hg.exe";
|
||||
|
||||
/** Field description */
|
||||
private static final String FILE_MERCURIAL_SCRIPT = "hg.bat";
|
||||
|
||||
/** Field description */
|
||||
private static final String FILE_SCRIPTS = "Scripts";
|
||||
|
||||
/** Field description */
|
||||
private static final String FILE_TEMPLATES = "templates";
|
||||
|
||||
/** Field description */
|
||||
private static final String[] REGISTRY_HG = new String[]
|
||||
{
|
||||
|
||||
// TortoiseHg
|
||||
"HKEY_CURRENT_USER\\Software\\TortoiseHg",
|
||||
|
||||
// Mercurial
|
||||
"HKEY_CURRENT_USER\\Software\\Mercurial\\InstallDir"
|
||||
};
|
||||
|
||||
/** Field description */
|
||||
private static final String[] REGISTRY_PYTHON = new String[]
|
||||
{
|
||||
|
||||
// .py files
|
||||
"HKEY_CLASSES_ROOT\\Python.File\\shell\\open\\command"
|
||||
};
|
||||
|
||||
/** the logger for WindowsHgInstaller */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(WindowsHgInstaller.class);
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public void install(File baseDirectory, HgConfig config) throws IOException
|
||||
{
|
||||
super.install(baseDirectory, config);
|
||||
|
||||
if (Util.isEmpty(config.getPythonBinary()))
|
||||
{
|
||||
String pythonBinary = getPythonBinary();
|
||||
|
||||
config.setPythonBinary(pythonBinary);
|
||||
}
|
||||
|
||||
if (Util.isEmpty(config.getHgBinary()))
|
||||
{
|
||||
File hgScript = getMercurialScript(config.getPythonBinary());
|
||||
|
||||
if (hgScript != null)
|
||||
{
|
||||
config.setHgBinary(hgScript.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
File hgDirectory = getMercurialDirectory(config.getHgBinary());
|
||||
|
||||
if (hgDirectory != null)
|
||||
{
|
||||
installHg(baseDirectory, config, hgDirectory);
|
||||
}
|
||||
|
||||
checkForOptimizedByteCode(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
*/
|
||||
@Override
|
||||
public void update(File baseDirectory, HgConfig config) {}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<String> getHgInstallations()
|
||||
{
|
||||
return getInstallations(REGISTRY_HG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<String> getPythonInstallations()
|
||||
{
|
||||
return getInstallations(REGISTRY_PYTHON);
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param config
|
||||
*/
|
||||
private void checkForOptimizedByteCode(HgConfig config)
|
||||
{
|
||||
boolean optimized = false;
|
||||
String path = config.getPythonPath();
|
||||
|
||||
if (Util.isNotEmpty(path))
|
||||
{
|
||||
for (String part : path.split(";"))
|
||||
{
|
||||
if (checkForOptimizedByteCode(part))
|
||||
{
|
||||
optimized = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config.setUseOptimizedBytecode(optimized);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param part
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private boolean checkForOptimizedByteCode(String part)
|
||||
{
|
||||
File libDir = new File(part);
|
||||
String[] pyoFiles = libDir.list(new FilenameFilter()
|
||||
{
|
||||
@Override
|
||||
public boolean accept(File file, String name)
|
||||
{
|
||||
return name.toLowerCase().endsWith(".pyo");
|
||||
}
|
||||
});
|
||||
|
||||
return Util.isNotEmpty(pyoFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param baseDirectory
|
||||
* @param config
|
||||
* @param hgDirectory
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private void installHg(File baseDirectory, HgConfig config, File hgDirectory)
|
||||
throws IOException
|
||||
{
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info("installing mercurial {}", hgDirectory.getAbsolutePath());
|
||||
}
|
||||
|
||||
File libDir = new File(baseDirectory, "lib\\hg");
|
||||
|
||||
IOUtil.mkdirs(libDir);
|
||||
|
||||
File libraryZip = new File(hgDirectory, FILE_LIBRARY_ZIP);
|
||||
|
||||
if (libraryZip.exists())
|
||||
{
|
||||
IOUtil.extract(libraryZip, libDir);
|
||||
config.setPythonPath(libDir.getAbsolutePath());
|
||||
}
|
||||
|
||||
File templateDirectory = new File(hgDirectory, FILE_TEMPLATES);
|
||||
|
||||
if (templateDirectory.exists())
|
||||
{
|
||||
IOUtil.copy(templateDirectory, new File(libDir, FILE_TEMPLATES));
|
||||
}
|
||||
|
||||
File hg = new File( hgDirectory, FILE_MERCURIAL_EXE );
|
||||
if ( hg.exists() )
|
||||
{
|
||||
config.setHgBinary(hg.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param registryKeys
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<String> getInstallations(String[] registryKeys)
|
||||
{
|
||||
List<String> installations = new ArrayList<String>();
|
||||
|
||||
for (String registryKey : registryKeys)
|
||||
{
|
||||
String path = RegistryUtil.getRegistryValue(registryKey);
|
||||
|
||||
if (path != null)
|
||||
{
|
||||
File file = new File(path, FILE_MERCURIAL_EXE);
|
||||
|
||||
if (file.exists())
|
||||
{
|
||||
installations.add(file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return installations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param hgBinary
|
||||
* @return
|
||||
*/
|
||||
private File getMercurialDirectory(String hgBinary)
|
||||
{
|
||||
File directory = null;
|
||||
|
||||
if ( Util.isNotEmpty(hgBinary) )
|
||||
{
|
||||
File hg = new File(hgBinary);
|
||||
|
||||
if (hg.exists() && hg.isFile())
|
||||
{
|
||||
directory = hg.getParentFile();
|
||||
}
|
||||
}
|
||||
|
||||
if ( directory == null )
|
||||
{
|
||||
directory = getMercurialDirectoryFromRegistry();
|
||||
}
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private File getMercurialDirectoryFromRegistry()
|
||||
{
|
||||
File directory = null;
|
||||
|
||||
for (String registryKey : REGISTRY_HG)
|
||||
{
|
||||
String path = RegistryUtil.getRegistryValue(registryKey);
|
||||
|
||||
if (path != null)
|
||||
{
|
||||
directory = new File(path);
|
||||
|
||||
if (!directory.exists())
|
||||
{
|
||||
directory = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the location of the script to run Mercurial, if Mercurial is
|
||||
* installed as a Python package from source. Only packages that include a
|
||||
* templates directory will be recognized.
|
||||
*
|
||||
* @param pythonBinary
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private File getMercurialScript(String pythonBinary)
|
||||
{
|
||||
File hgScript = null;
|
||||
|
||||
if (pythonBinary != null)
|
||||
{
|
||||
File pythonBinaryFile = new File(pythonBinary);
|
||||
|
||||
if (pythonBinaryFile.exists())
|
||||
{
|
||||
File pythonDir = pythonBinaryFile.getParentFile();
|
||||
File scriptsDir = new File(pythonDir, FILE_SCRIPTS);
|
||||
File potentialHgScript = new File(scriptsDir, FILE_MERCURIAL_SCRIPT);
|
||||
File mercurialPackageDir = new File(pythonDir, FILE_LIB_MERCURIAL);
|
||||
File templatesDir = new File(mercurialPackageDir, FILE_TEMPLATES);
|
||||
|
||||
if (potentialHgScript.exists() && templatesDir.exists())
|
||||
{
|
||||
hgScript = potentialHgScript;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hgScript;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getPythonBinary()
|
||||
{
|
||||
String python = RegistryUtil.getRegistryValue(REGISTRY_PYTHON[0]);
|
||||
|
||||
if (python == null)
|
||||
{
|
||||
python = IOUtil.search(new String[0], "python");
|
||||
}
|
||||
|
||||
return python;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgChangesetParser
|
||||
{
|
||||
|
||||
/** the logger for HgChangesetParser */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(HgChangesetParser.class);
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param in
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ParserConfigurationException
|
||||
* @throws SAXException
|
||||
*/
|
||||
public List<Changeset> parse(InputSource in)
|
||||
throws SAXException, IOException, ParserConfigurationException
|
||||
{
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
|
||||
return parse(builder.parse(in));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param document
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<Changeset> parse(Document document)
|
||||
{
|
||||
List<Changeset> changesetList = new ArrayList<Changeset>();
|
||||
NodeList changesetNodeList = document.getElementsByTagName("changeset");
|
||||
|
||||
if (changesetNodeList != null)
|
||||
{
|
||||
for (int i = 0; i < changesetNodeList.getLength(); i++)
|
||||
{
|
||||
Node changesetNode = changesetNodeList.item(i);
|
||||
Changeset changeset = parseChangesetNode(changesetNode);
|
||||
|
||||
if ((changeset != null) && changeset.isValid())
|
||||
{
|
||||
changesetList.add(changeset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return changesetList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param changeset
|
||||
* @param node
|
||||
*/
|
||||
private void parseChangesetChildNode(Changeset changeset, Node node)
|
||||
{
|
||||
String name = node.getNodeName();
|
||||
String value = node.getTextContent();
|
||||
|
||||
if (Util.isNotEmpty(value))
|
||||
{
|
||||
if ("id".equals(name))
|
||||
{
|
||||
changeset.setId(value);
|
||||
}
|
||||
else if ("author".equals(name))
|
||||
{
|
||||
changeset.setAuthor(Person.toPerson(value));
|
||||
}
|
||||
else if ("description".equals(name))
|
||||
{
|
||||
changeset.setDescription(value);
|
||||
}
|
||||
else if ("date".equals(name))
|
||||
{
|
||||
try
|
||||
{
|
||||
Date date = dateFormat.parse(value);
|
||||
|
||||
changeset.setDate(date.getTime());
|
||||
}
|
||||
catch (ParseException ex)
|
||||
{
|
||||
logger.warn("could not parse date", ex);
|
||||
}
|
||||
}
|
||||
else if ("tags".equals(name))
|
||||
{
|
||||
changeset.setTags(getList(value));
|
||||
}
|
||||
else if ("branches".equals(name))
|
||||
{
|
||||
changeset.setBranches(getList(value));
|
||||
}
|
||||
else if ("files-added".equals(name))
|
||||
{
|
||||
changeset.getModifications().setAdded(getList(value));
|
||||
}
|
||||
else if ("files-mods".equals(name))
|
||||
{
|
||||
changeset.getModifications().setModified(getList(value));
|
||||
}
|
||||
else if ("files-dels".equals(name))
|
||||
{
|
||||
changeset.getModifications().setRemoved(getList(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param changesetNode
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Changeset parseChangesetNode(Node changesetNode)
|
||||
{
|
||||
Changeset changeset = new Changeset();
|
||||
NodeList childrenNodeList = changesetNode.getChildNodes();
|
||||
|
||||
if (childrenNodeList != null)
|
||||
{
|
||||
for (int i = 0; i < childrenNodeList.getLength(); i++)
|
||||
{
|
||||
Node child = childrenNodeList.item(i);
|
||||
|
||||
parseChangesetChildNode(changeset, child);
|
||||
}
|
||||
}
|
||||
|
||||
return changeset;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param value
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<String> getList(String value)
|
||||
{
|
||||
return Arrays.asList(value.split(" "));
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private SimpleDateFormat dateFormat =
|
||||
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import sonia.scm.io.Command;
|
||||
import sonia.scm.io.CommandResult;
|
||||
import sonia.scm.io.SimpleCommand;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgChangesetViewer implements ChangesetViewer
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String ID_TIP = "tip";
|
||||
|
||||
/** Field description */
|
||||
//J-
|
||||
public static final String TEMPLATE_CHANGESETS =
|
||||
"\"<changeset>"
|
||||
+ "<id>{rev}:{node|short}</id>"
|
||||
+ "<author>{author|escape}</author>"
|
||||
+ "<description>{desc|escape}</description>"
|
||||
+ "<date>{date|isodatesec}</date>"
|
||||
+ "<tags>{tags}</tags>"
|
||||
+ "<branches>{branches}</branches>"
|
||||
+ "<files-added>{file_adds}</files-added>"
|
||||
+ "<files-mods>{file_mods}</files-mods>"
|
||||
+ "<files-dels>{file_dels}</files-dels>"
|
||||
+ "</changeset>\"";
|
||||
//J+
|
||||
|
||||
/** Field description */
|
||||
public static final String TEMPLATE_TOTAL = "{rev}";
|
||||
|
||||
/** the logger for HgChangesetViewer */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(HgChangesetViewer.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param handler
|
||||
* @param repository
|
||||
*/
|
||||
public HgChangesetViewer(HgRepositoryHandler handler, Repository repository)
|
||||
{
|
||||
this.handler = handler;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param start
|
||||
* @param max
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChangesetPagingResult getChangesets(int start, int max)
|
||||
{
|
||||
ChangesetPagingResult changesets = null;
|
||||
InputStream in = null;
|
||||
|
||||
try
|
||||
{
|
||||
String repositoryPath = getRepositoryPath(repository);
|
||||
int total = getTotalChangesets(repositoryPath);
|
||||
int startRev = total - start;
|
||||
int endRev = total - start - (max - 1);
|
||||
|
||||
if (endRev < 0)
|
||||
{
|
||||
endRev = 0;
|
||||
}
|
||||
|
||||
Command command = new SimpleCommand(handler.getConfig().getHgBinary(),
|
||||
"-R", repositoryPath, "log", "-r",
|
||||
startRev + ":" + endRev, "--template",
|
||||
TEMPLATE_CHANGESETS);
|
||||
CommandResult result = command.execute();
|
||||
|
||||
if (result.isSuccessfull())
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("<changesets>");
|
||||
|
||||
sb.append(result.getOutput()).append("</changesets>");
|
||||
|
||||
List<Changeset> changesetList = new HgChangesetParser().parse(
|
||||
new InputSource(
|
||||
new StringReader(sb.toString())));
|
||||
|
||||
changesets = new ChangesetPagingResult(total, changesetList);
|
||||
}
|
||||
else if ( logger.isErrorEnabled() )
|
||||
{
|
||||
logger.error(
|
||||
"command for fetching changesets failed with exit code {} and output {}",
|
||||
result.getReturnCode(),
|
||||
result.getOutput()
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (ParserConfigurationException ex)
|
||||
{
|
||||
logger.error("could not parse changesets", ex);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.error("could not load changesets", ex);
|
||||
}
|
||||
catch (SAXException ex)
|
||||
{
|
||||
logger.error("could not unmarshall changesets", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(in);
|
||||
}
|
||||
|
||||
return changesets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getRepositoryPath(Repository repository)
|
||||
{
|
||||
return handler.getDirectory(repository).getAbsolutePath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repositoryPath
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private int getTotalChangesets(String repositoryPath) throws IOException
|
||||
{
|
||||
int total = -1;
|
||||
Command command = new SimpleCommand(handler.getConfig().getHgBinary(),
|
||||
"-R", repositoryPath, "tip", "--template",
|
||||
TEMPLATE_TOTAL);
|
||||
CommandResult result = command.execute();
|
||||
|
||||
if (result.isSuccessfull())
|
||||
{
|
||||
total = Integer.parseInt(result.getOutput().trim());
|
||||
}
|
||||
else if ( logger.isErrorEnabled() )
|
||||
{
|
||||
logger.error(
|
||||
"could not read tip revision, command returned with exit code {} and content {}",
|
||||
result.getReturnCode(),
|
||||
result.getOutput()
|
||||
);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private HgRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private Repository repository;
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@XmlRootElement(name = "config")
|
||||
public class HgConfig extends SimpleRepositoryConfig
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*/
|
||||
public HgConfig() {}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getHgBinary()
|
||||
{
|
||||
return hgBinary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPythonBinary()
|
||||
{
|
||||
return pythonBinary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPythonPath()
|
||||
{
|
||||
return pythonPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isUseOptimizedBytecode()
|
||||
{
|
||||
return useOptimizedBytecode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
return super.isValid() && Util.isNotEmpty(hgBinary)
|
||||
&& Util.isNotEmpty(pythonBinary);
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param hgBinary
|
||||
*/
|
||||
public void setHgBinary(String hgBinary)
|
||||
{
|
||||
this.hgBinary = hgBinary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param pythonBinary
|
||||
*/
|
||||
public void setPythonBinary(String pythonBinary)
|
||||
{
|
||||
this.pythonBinary = pythonBinary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param pythonPath
|
||||
*/
|
||||
public void setPythonPath(String pythonPath)
|
||||
{
|
||||
this.pythonPath = pythonPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param useOptimizedBytecode
|
||||
*/
|
||||
public void setUseOptimizedBytecode(boolean useOptimizedBytecode)
|
||||
{
|
||||
this.useOptimizedBytecode = useOptimizedBytecode;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private String hgBinary;
|
||||
|
||||
/** Field description */
|
||||
private String pythonBinary;
|
||||
|
||||
/** Field description */
|
||||
private String pythonPath = "";
|
||||
|
||||
/** Field description */
|
||||
private boolean useOptimizedBytecode = false;
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.util.IOUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgRepositoryBrowser implements RepositoryBrowser
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String DEFAULT_REVISION = "tip";
|
||||
|
||||
/** Field description */
|
||||
public static final String ENV_PATH = "SCM_PATH";
|
||||
|
||||
/** Field description */
|
||||
public static final String ENV_PYTHON_PATH = "SCM_PYTHON_PATH";
|
||||
|
||||
/** Field description */
|
||||
public static final String ENV_REPOSITORY_PATH = "SCM_REPOSITORY_PATH";
|
||||
|
||||
/** Field description */
|
||||
public static final String ENV_REVISION = "SCM_REVISION";
|
||||
|
||||
/** Field description */
|
||||
public static final String RESOURCE_BROWSE = "/sonia/scm/hgbrowse.py";
|
||||
|
||||
/** the logger for HgRepositoryBrowser */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(HgRepositoryBrowser.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param handler
|
||||
* @param repository
|
||||
* @param browserResultContext
|
||||
*/
|
||||
public HgRepositoryBrowser(HgRepositoryHandler handler,
|
||||
Repository repository,
|
||||
JAXBContext browserResultContext)
|
||||
{
|
||||
this.handler = handler;
|
||||
this.repository = repository;
|
||||
this.browserResultContext = browserResultContext;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param revision
|
||||
* @param path
|
||||
* @param output
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Override
|
||||
public void getContent(String revision, String path, OutputStream output)
|
||||
throws IOException, RepositoryException
|
||||
{
|
||||
if (Util.isEmpty(revision))
|
||||
{
|
||||
revision = DEFAULT_REVISION;
|
||||
}
|
||||
|
||||
File directory = handler.getDirectory(repository);
|
||||
ProcessBuilder builder =
|
||||
new ProcessBuilder(handler.getConfig().getHgBinary(), "cat", "-r",
|
||||
revision, Util.nonNull(path));
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
StringBuilder msg = new StringBuilder();
|
||||
|
||||
for (String param : builder.command())
|
||||
{
|
||||
msg.append(param).append(" ");
|
||||
}
|
||||
|
||||
logger.debug(msg.toString());
|
||||
}
|
||||
|
||||
Process p = builder.directory(directory).start();
|
||||
InputStream input = null;
|
||||
|
||||
try
|
||||
{
|
||||
input = p.getInputStream();
|
||||
IOUtil.copy(input, output);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(input);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param revision
|
||||
* @param path
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Override
|
||||
public BrowserResult getResult(String revision, String path)
|
||||
throws IOException, RepositoryException
|
||||
{
|
||||
HgConfig config = handler.getConfig();
|
||||
ProcessBuilder pb = new ProcessBuilder(config.getPythonBinary());
|
||||
Map<String, String> env = pb.environment();
|
||||
|
||||
env.put(ENV_PYTHON_PATH, Util.nonNull(config.getPythonPath()));
|
||||
|
||||
String directory = handler.getDirectory(repository).getAbsolutePath();
|
||||
|
||||
env.put(ENV_REPOSITORY_PATH, directory);
|
||||
|
||||
if (Util.isEmpty(revision))
|
||||
{
|
||||
revision = DEFAULT_REVISION;
|
||||
}
|
||||
|
||||
env.put(ENV_REVISION, revision);
|
||||
env.put(ENV_PATH, Util.nonNull(path));
|
||||
|
||||
Process p = pb.start();
|
||||
BrowserResult result = null;
|
||||
InputStream resource = null;
|
||||
InputStream input = null;
|
||||
OutputStream output = null;
|
||||
|
||||
try
|
||||
{
|
||||
resource = HgRepositoryBrowser.class.getResourceAsStream(RESOURCE_BROWSE);
|
||||
output = p.getOutputStream();
|
||||
IOUtil.copy(resource, output);
|
||||
output.close();
|
||||
|
||||
// IOUtil.copy(p.getErrorStream(), System.err);
|
||||
input = p.getInputStream();
|
||||
result =
|
||||
(BrowserResult) browserResultContext.createUnmarshaller().unmarshal(
|
||||
input);
|
||||
|
||||
// IOUtil.copy(input, System.out);
|
||||
input.close();
|
||||
}
|
||||
catch (JAXBException ex)
|
||||
{
|
||||
logger.error("could not parse result", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(resource);
|
||||
IOUtil.close(input);
|
||||
IOUtil.close(output);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private JAXBContext browserResultContext;
|
||||
|
||||
/** Field description */
|
||||
private HgRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private Repository repository;
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.ConfigurationException;
|
||||
import sonia.scm.Type;
|
||||
import sonia.scm.installer.HgInstaller;
|
||||
import sonia.scm.installer.HgInstallerFactory;
|
||||
import sonia.scm.io.ExtendedCommand;
|
||||
import sonia.scm.io.FileSystem;
|
||||
import sonia.scm.io.INIConfiguration;
|
||||
import sonia.scm.io.INIConfigurationWriter;
|
||||
import sonia.scm.io.INISection;
|
||||
import sonia.scm.plugin.ext.Extension;
|
||||
import sonia.scm.store.StoreFactory;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.web.HgWebConfigWriter;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Singleton
|
||||
@Extension
|
||||
public class HgRepositoryHandler
|
||||
extends AbstractSimpleRepositoryHandler<HgConfig>
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String TYPE_DISPLAYNAME = "Mercurial";
|
||||
|
||||
/** Field description */
|
||||
public static final String TYPE_NAME = "hg";
|
||||
|
||||
/** Field description */
|
||||
public static final Type TYPE = new Type(TYPE_NAME, TYPE_DISPLAYNAME);
|
||||
|
||||
/** the logger for HgRepositoryHandler */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(HgRepositoryHandler.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param storeFactory
|
||||
* @param fileSystem
|
||||
*/
|
||||
@Inject
|
||||
public HgRepositoryHandler(StoreFactory storeFactory, FileSystem fileSystem)
|
||||
{
|
||||
super(storeFactory, fileSystem);
|
||||
|
||||
try
|
||||
{
|
||||
this.browserResultContext = JAXBContext.newInstance(BrowserResult.class);
|
||||
}
|
||||
catch (JAXBException ex)
|
||||
{
|
||||
throw new ConfigurationException("could not create jaxbcontext", ex);
|
||||
}
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param autoConfig
|
||||
*/
|
||||
public void doAutoConfiguration(HgConfig autoConfig)
|
||||
{
|
||||
HgInstaller installer = HgInstallerFactory.createInstaller();
|
||||
|
||||
try
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("installing mercurial with {}",
|
||||
installer.getClass().getName());
|
||||
}
|
||||
|
||||
installer.install(baseDirectory, autoConfig);
|
||||
config = autoConfig;
|
||||
storeConfig();
|
||||
new HgWebConfigWriter(config).write();
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
if (logger.isErrorEnabled())
|
||||
{
|
||||
logger.error(
|
||||
"Could not write Hg CGI for inital config. "
|
||||
+ "HgWeb may not function until a new Hg config is set", ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void loadConfig()
|
||||
{
|
||||
super.loadConfig();
|
||||
|
||||
if (config == null)
|
||||
{
|
||||
doAutoConfiguration(new HgConfig());
|
||||
}
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChangesetViewer getChangesetViewer(Repository repository)
|
||||
{
|
||||
HgChangesetViewer changesetViewer = null;
|
||||
|
||||
AssertUtil.assertIsNotNull(repository);
|
||||
|
||||
String type = repository.getType();
|
||||
|
||||
AssertUtil.assertIsNotEmpty(type);
|
||||
|
||||
if (TYPE_NAME.equals(type))
|
||||
{
|
||||
changesetViewer = new HgChangesetViewer(this, repository);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("mercurial repository is required");
|
||||
}
|
||||
|
||||
return changesetViewer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public RepositoryBrowser getRepositoryBrowser(Repository repository)
|
||||
{
|
||||
return new HgRepositoryBrowser(this, repository, browserResultContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
* @param directory
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected ExtendedCommand buildCreateCommand(Repository repository,
|
||||
File directory)
|
||||
{
|
||||
return new ExtendedCommand(config.getHgBinary(), "init",
|
||||
directory.getPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes .hg/hgrc and disables hg access control
|
||||
* see HgPermissionFilter
|
||||
*
|
||||
* @param repository
|
||||
* @param directory
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Override
|
||||
protected void postCreate(Repository repository, File directory)
|
||||
throws IOException, RepositoryException
|
||||
{
|
||||
File hgrcFile = new File(directory,
|
||||
".hg".concat(File.separator).concat("hgrc"));
|
||||
INIConfiguration hgrc = new INIConfiguration();
|
||||
INISection webSection = new INISection("web");
|
||||
|
||||
webSection.setParameter("push_ssl", "false");
|
||||
webSection.setParameter("allow_read", "*");
|
||||
webSection.setParameter("allow_push", "*");
|
||||
hgrc.addSection(webSection);
|
||||
|
||||
INIConfigurationWriter writer = new INIConfigurationWriter();
|
||||
|
||||
writer.write(hgrc, hgrcFile);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected Class<HgConfig> getConfigClass()
|
||||
{
|
||||
return HgConfig.class;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private JAXBContext browserResultContext;
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.web;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.web.cgi.CGIExecutor;
|
||||
import sonia.scm.web.cgi.CGIExecutorFactory;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Singleton
|
||||
public class HgCGIServlet extends HttpServlet
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String ENV_PYTHON_PATH = "SCM_PYTHON_PATH";
|
||||
|
||||
/** Field description */
|
||||
public static final String ENV_REPOSITORY_NAME = "REPO_NAME";
|
||||
|
||||
/** Field description */
|
||||
public static final String ENV_REPOSITORY_PATH = "SCM_REPOSITORY_PATH";
|
||||
|
||||
/** Field description */
|
||||
private static final long serialVersionUID = -3492811300905099810L;
|
||||
|
||||
/** Field description */
|
||||
public static final Pattern PATTERN_REPOSITORYNAME =
|
||||
Pattern.compile("/[^/]+/([^/]+)(?:/.*)?");
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param cgiExecutorFactory
|
||||
* @param configuration
|
||||
* @param repositoryManager
|
||||
* @param handler
|
||||
*/
|
||||
@Inject
|
||||
public HgCGIServlet(CGIExecutorFactory cgiExecutorFactory,
|
||||
ScmConfiguration configuration,
|
||||
RepositoryManager repositoryManager,
|
||||
HgRepositoryHandler handler)
|
||||
{
|
||||
this.cgiExecutorFactory = cgiExecutorFactory;
|
||||
this.configuration = configuration;
|
||||
this.repositoryManager = repositoryManager;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Override
|
||||
public void init() throws ServletException
|
||||
{
|
||||
command = HgUtil.getCGI();
|
||||
super.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Override
|
||||
protected void service(HttpServletRequest request,
|
||||
HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
Repository repository = getRepository(request);
|
||||
|
||||
if (repository == null)
|
||||
{
|
||||
throw new ServletException("repository not found");
|
||||
}
|
||||
|
||||
String name = repository.getName();
|
||||
File directory = handler.getDirectory(repository);
|
||||
String pythonPath = "";
|
||||
HgConfig config = handler.getConfig();
|
||||
|
||||
if (config != null)
|
||||
{
|
||||
pythonPath = config.getPythonPath();
|
||||
|
||||
if (pythonPath == null)
|
||||
{
|
||||
pythonPath = "";
|
||||
}
|
||||
}
|
||||
|
||||
CGIExecutor executor = cgiExecutorFactory.createExecutor(configuration,
|
||||
getServletContext(), request, response);
|
||||
|
||||
executor.getEnvironment().set(ENV_REPOSITORY_NAME, name);
|
||||
executor.getEnvironment().set(ENV_REPOSITORY_PATH,
|
||||
directory.getAbsolutePath());
|
||||
executor.getEnvironment().set(ENV_PYTHON_PATH, pythonPath);
|
||||
|
||||
String interpreter = getInterpreter();
|
||||
|
||||
if (interpreter != null)
|
||||
{
|
||||
executor.setInterpreter(interpreter);
|
||||
}
|
||||
|
||||
executor.execute(command.getAbsolutePath());
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getInterpreter()
|
||||
{
|
||||
HgConfig config = handler.getConfig();
|
||||
|
||||
AssertUtil.assertIsNotNull(config);
|
||||
|
||||
String python = config.getPythonBinary();
|
||||
|
||||
if ((python != null) && config.isUseOptimizedBytecode())
|
||||
{
|
||||
python = python.concat(" -O");
|
||||
}
|
||||
|
||||
return python;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Repository getRepository(HttpServletRequest request)
|
||||
{
|
||||
Repository repository = null;
|
||||
String uri = request.getRequestURI();
|
||||
|
||||
uri = uri.substring(request.getContextPath().length());
|
||||
|
||||
Matcher m = PATTERN_REPOSITORYNAME.matcher(uri);
|
||||
|
||||
if (m.matches())
|
||||
{
|
||||
String repositoryname = m.group(1);
|
||||
|
||||
repository = getRepository(repositoryname);
|
||||
}
|
||||
|
||||
return repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repositoryname
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Repository getRepository(String repositoryname)
|
||||
{
|
||||
return repositoryManager.get(HgRepositoryHandler.TYPE_NAME, repositoryname);
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private CGIExecutorFactory cgiExecutorFactory;
|
||||
|
||||
/** Field description */
|
||||
private File command;
|
||||
|
||||
/** Field description */
|
||||
private ScmConfiguration configuration;
|
||||
|
||||
/** Field description */
|
||||
private HgRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private RepositoryManager repositoryManager;
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.web;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.web.filter.RegexPermissionFilter;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Singleton
|
||||
public class HgPermissionFilter extends RegexPermissionFilter
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param securityContextProvider
|
||||
* @param repositoryManager
|
||||
*/
|
||||
@Inject
|
||||
public HgPermissionFilter(
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryManager repositoryManager)
|
||||
{
|
||||
super(securityContextProvider, repositoryManager);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected String getType()
|
||||
{
|
||||
return HgRepositoryHandler.TYPE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected boolean isWriteRequest(HttpServletRequest request)
|
||||
{
|
||||
return !request.getMethod().equalsIgnoreCase("GET");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.web;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.servlet.ServletModule;
|
||||
import sonia.scm.plugin.ext.Extension;
|
||||
|
||||
import sonia.scm.web.filter.BasicAuthenticationFilter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Extension
|
||||
public class HgServletModule extends ServletModule
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String MAPPING_HG = "/hg/*";
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
protected void configureServlets()
|
||||
{
|
||||
filter(MAPPING_HG).through(BasicAuthenticationFilter.class);
|
||||
filter(MAPPING_HG).through(HgPermissionFilter.class);
|
||||
serve(MAPPING_HG).with(HgCGIServlet.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.web;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.SCMContext;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgUtil
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String CGI_DIRECTORY = "cgi-bin";
|
||||
|
||||
/** Field description */
|
||||
public static final String CGI_NAME = "hgweb.py";
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static File getCGI()
|
||||
{
|
||||
File cgiDirectory = new File(SCMContext.getContext().getBaseDirectory(),
|
||||
CGI_DIRECTORY);
|
||||
|
||||
if (!cgiDirectory.exists() &&!cgiDirectory.mkdirs())
|
||||
{
|
||||
throw new RuntimeException(
|
||||
"could not create directory".concat(cgiDirectory.getPath()));
|
||||
}
|
||||
|
||||
return new File(cgiDirectory, CGI_NAME);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.web;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.io.RegexResourceProcessor;
|
||||
import sonia.scm.io.ResourceProcessor;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class HgWebConfigWriter
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String CGI_TEMPLATE = "/sonia/scm/hgweb.py";
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param config
|
||||
*/
|
||||
public HgWebConfigWriter(HgConfig config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void write() throws IOException
|
||||
{
|
||||
File cgiFile = HgUtil.getCGI();
|
||||
|
||||
writeCGIFile(cgiFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param cgiFile
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private void writeCGIFile(File cgiFile) throws IOException
|
||||
{
|
||||
InputStream input = null;
|
||||
OutputStream output = null;
|
||||
|
||||
try
|
||||
{
|
||||
input = HgWebConfigWriter.class.getResourceAsStream(CGI_TEMPLATE);
|
||||
output = new FileOutputStream(cgiFile);
|
||||
|
||||
ResourceProcessor rp = new RegexResourceProcessor();
|
||||
|
||||
rp.addVariable("python", config.getPythonBinary());
|
||||
rp.process(input, output);
|
||||
cgiFile.setExecutable(true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(input);
|
||||
IOUtil.close(output);
|
||||
}
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private HgConfig config;
|
||||
}
|
||||
Reference in New Issue
Block a user