improve scm-hg-plugin

This commit is contained in:
Sebastian Sdorra
2010-11-25 18:25:01 +01:00
parent ceedb19bb1
commit c036b7ac7c
10 changed files with 109 additions and 964 deletions

View File

@@ -66,31 +66,6 @@ public class GitRepositoryHandler
//~--- get methods ----------------------------------------------------------
/**
* TODO dont use getAll
*
*
* @param name
*
* @return
*/
public Repository getByName(String name)
{
Repository repository = null;
for (Repository r : getAll())
{
if (r.getName().equals(name))
{
repository = r;
break;
}
}
return repository;
}
/**
* Method description
*

View File

@@ -62,7 +62,6 @@ import javax.ws.rs.core.UriInfo;
*/
@Singleton
@Path("config/repositories/hg")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public class HgConfigResource
{
@@ -88,6 +87,7 @@ public class HgConfigResource
* @return
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public HgConfig getConfig()
{
HgConfig config = handler.getConfig();

View File

@@ -1,175 +0,0 @@
/**
* 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.group.Group;
//~--- JDK imports ------------------------------------------------------------
import java.util.Collection;
/**
*
* @author Sebastian Sdorra
*/
public class HgPermissionBuilder
{
/**
* Constructs ...
*
*
* @param permissions
*/
public HgPermissionBuilder(Collection<Permission> permissions)
{
buildPermissions(permissions);
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
public String getReadPermission()
{
return read.toString();
}
/**
* Method description
*
*
* @return
*/
public String getWritePermission()
{
return write.toString();
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param permissions
*/
private void buildPermissions(Collection<Permission> permissions)
{
boolean firstRead = true;
boolean firstWrite = true;
for (Permission permission : permissions)
{
String name = permission.getName();
if (permission.isGroupPermission())
{
name = createGroupString(name);
}
if (!firstRead)
{
read.append(", ");
}
else
{
firstRead = false;
}
read.append(name);
if (permission.isWriteable())
{
if (!firstWrite)
{
write.append(", ");
}
else
{
firstWrite = false;
}
write.append(name);
}
}
}
/**
* Method description
*
*
* @param name
*
* @return
*/
private String createGroupString(String name)
{
StringBuilder result = new StringBuilder();
result.append("__").append(name).append(", ");
Group group = /* SCMContext.getContext().getGroupManager().get(name); */
null;
if (group != null)
{
Collection<String> memerbers = group.getMembers();
if (memerbers != null)
{
for (String member : memerbers)
{
result.append(member).append(", ");
}
}
}
result.append("__").append(name);
return result.toString();
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private StringBuilder read = new StringBuilder();
/** Field description */
private StringBuilder write = new StringBuilder();
}

View File

@@ -1,187 +0,0 @@
/**
* 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 java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
*
* @author Sebastian Sdorra
*/
public class HgPermissionReader
{
/**
* Method description
*
*
* @param read
* @param write
*
* @return
*/
public List<Permission> readPermissions(String read, String write)
{
List<String> readPerms = createPermList(read);
List<String> writePerms = createPermList(write);
return createPermissionList(readPerms, writePerms);
}
/**
* Method description
*
*
* @param perms
*
* @return
*/
private List<String> createGroups(List<String> perms)
{
List<String> groups = new ArrayList<String>();
boolean start = false;
Iterator<String> permIt = perms.iterator();
while (permIt.hasNext())
{
String perm = permIt.next();
if (perm.startsWith("__"))
{
if (start)
{
start = false;
}
else
{
start = true;
groups.add(perm.substring(2));
}
permIt.remove();
}
else if (start)
{
permIt.remove();
}
}
return groups;
}
/**
* Method description
*
*
* @param value
*
* @return
*/
private List<String> createPermList(String value)
{
List<String> perms = new ArrayList<String>();
if (Util.isNotEmpty(value))
{
String[] values = value.split(",");
for (String name : values)
{
perms.add(name.trim());
}
}
return perms;
}
/**
* Method description
*
*
* @param readPerms
* @param writePerms
*
* @return
*/
private List<Permission> createPermissionList(List<String> readPerms,
List<String> writePerms)
{
List<Permission> permissions = new ArrayList<Permission>();
List<String> readGroups = createGroups(readPerms);
List<String> writeGroups = createGroups(writePerms);
createPermissions(permissions, readPerms, writePerms, false);
createPermissions(permissions, readGroups, writeGroups, true);
return permissions;
}
/**
* Method description
*
*
* @param permissions
* @param readPermissions
* @param writePermissions
* @param group
*/
private void createPermissions(List<Permission> permissions,
List<String> readPermissions,
List<String> writePermissions, boolean group)
{
for (String readPerm : readPermissions)
{
boolean write = false;
if (writePermissions.contains(readPerm))
{
write = true;
writePermissions.remove(readPerm);
}
permissions.add(new Permission(readPerm, write, group));
}
for (String writePerm : writePermissions)
{
permissions.add(new Permission(writePerm, true, group));
}
}
}

View File

@@ -37,39 +37,24 @@ package sonia.scm.repository;
import com.google.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.ConfigurationException;
import sonia.scm.Type;
import sonia.scm.io.CommandResult;
import sonia.scm.io.ExtendedCommand;
import sonia.scm.io.INIConfiguration;
import sonia.scm.io.INIConfigurationReader;
import sonia.scm.io.INIConfigurationWriter;
import sonia.scm.io.INISection;
import sonia.scm.util.IOUtil;
import sonia.scm.util.Util;
import sonia.scm.web.HgWebConfigWriter;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
*
* @author Sebastian Sdorra
*/
@Singleton
public class HgRepositoryHandler extends AbstractRepositoryHandler<HgConfig>
public class HgRepositoryHandler
extends AbstractSimpleRepositoryHandler<HgConfig>
{
/** Field description */
@@ -81,55 +66,8 @@ public class HgRepositoryHandler extends AbstractRepositoryHandler<HgConfig>
/** Field description */
public static final Type TYPE = new Type(TYPE_NAME, TYPE_DISPLAYNAME);
/** Field description */
private static final Logger logger =
LoggerFactory.getLogger(HgRepositoryHandler.class);
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param repository
*
* @throws IOException
* @throws RepositoryException
*/
@Override
public void create(Repository repository)
throws RepositoryException, IOException
{
initNewRepository(repository);
File directory = getDirectory(repository);
if (directory.exists())
{
throw new RepositoryAllreadyExistExeption();
}
ExtendedCommand command = new ExtendedCommand(config.getHgBinary(), "init",
directory.getPath());
CommandResult result = command.execute();
if (!result.isSuccessfull())
{
StringBuilder msg = new StringBuilder("hg exit with error ");
msg.append(result.getReturnCode()).append(" and message: '");
msg.append(result.getOutput()).append("'");
throw new RepositoryException(msg.toString());
}
repository.setType(TYPE_NAME);
File hgDirectory = new File(directory, ".hg");
storeRepository(repository, hgDirectory);
}
/**
* Method description
*
@@ -144,210 +82,8 @@ public class HgRepositoryHandler extends AbstractRepositoryHandler<HgConfig>
return "/hg/".concat(repository.getName());
}
/**
* Method description
*
*
* @param repository
*
* @throws IOException
* @throws RepositoryException
*/
@Override
public void delete(Repository repository)
throws RepositoryException, IOException
{
File directory = getDirectory(repository);
if (new File(directory, ".hg").exists())
{
IOUtil.delete(directory);
}
else
{
throw new RepositoryException("repository does not exists");
}
}
/**
* Method description
*
*/
@Override
public void loadConfig()
{
super.loadConfig();
if (config == null)
{
try
{
config =
new HgInitialConfigBuilder(baseDirectory).createInitialConfig();
storeConfig();
new HgWebConfigWriter(config).write();
}
catch (IOException ex)
{
logger.error(ex.getMessage(), ex);
}
}
}
/**
* Method description
*
*
* @param repository
*
* @throws IOException
* @throws RepositoryException
*/
@Override
public void modify(Repository repository)
throws RepositoryException, IOException
{
File directory = getDirectory(repository);
File hgDirectory = new File(directory, ".hg");
if (hgDirectory.exists())
{
storeRepository(repository, hgDirectory);
}
}
/**
* Method description
*
*
* @param repository
*
* @throws IOException
* @throws RepositoryException
*/
@Override
public void refresh(Repository repository)
throws RepositoryException, IOException
{
File directory = getDirectory(repository);
File hgDirectory = new File(directory, ".hg");
if (hgDirectory.exists())
{
loadRepository(repository, hgDirectory);
}
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param id
*
* @return
*/
@Override
public Repository get(String id)
{
Repository repository = null;
File[] directories = getRepositoryDirectory().listFiles();
for (File directory : directories)
{
File hgDirectory = new File(directory, ".hg");
if (hgDirectory.exists() && hgDirectory.isDirectory())
{
repository = new Repository();
repository.setType(TYPE_NAME);
repository.setName(directory.getName());
loadRepository(repository, hgDirectory);
if (!id.equals(repository.getId()))
{
repository = null;
}
else
{
break;
}
}
}
return repository;
}
/**
* Method description
*
*
* @return
*/
@Override
public Collection<Repository> getAll()
{
List<Repository> repositories = new ArrayList<Repository>();
String[] repositoryNames = getRepositoryDirectory().list();
if ((repositoryNames != null) && (repositoryNames.length > 0))
{
for (String repositoryName : repositoryNames)
{
Repository repository = buildRepository(repositoryName);
if (repository != null)
{
if (Util.isNotEmpty(repository.getId()))
{
repositories.add(repository);
}
}
}
}
return repositories;
}
/**
* Method description
*
*
* @param repositoryname
*
* @return
*/
public Repository getByName(String repositoryname)
{
Repository repository = null;
for (Repository r : getAll())
{
if (r.getName().equals(repositoryname))
{
repository = r;
break;
}
}
return repository;
}
/**
* Method description
*
*
* @param repository
*
* @return
*/
public File getDirectory(Repository repository)
{
return new File(config.getRepositoryDirectory(), repository.getName());
}
/**
* Method description
*
@@ -360,6 +96,56 @@ public class HgRepositoryHandler extends AbstractRepositoryHandler<HgConfig>
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
*
@@ -371,228 +157,4 @@ public class HgRepositoryHandler extends AbstractRepositoryHandler<HgConfig>
{
return HgConfig.class;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param section
* @param permissions
*/
private void appendPermission(INISection section,
Collection<Permission> permissions)
{
HgPermissionBuilder builder = new HgPermissionBuilder(permissions);
section.setParameter("allow_read", builder.getReadPermission());
section.setParameter("allow_push", builder.getWritePermission());
}
/**
* Method description
*
*
* @param name
*
* @return
*/
private Repository buildRepository(String name)
{
Repository repository = null;
File directory = getDirectory(name);
if (directory.exists() && directory.isDirectory())
{
File hgDirectory = new File(directory, ".hg");
if (hgDirectory.exists() && hgDirectory.isDirectory())
{
repository = new Repository();
repository.setType(TYPE_NAME);
repository.setName(name);
loadRepository(repository, hgDirectory);
}
}
return repository;
}
/**
* Method description
*
*
* @param repository
* @param hgDirectory
*/
private void loadRepository(Repository repository, File hgDirectory)
{
File hgrc = new File(hgDirectory, "hgrc");
if (hgrc.exists() && hgrc.isFile())
{
try
{
INIConfiguration iniConfig = new INIConfigurationReader().read(hgrc);
INISection section = iniConfig.getSection("web");
if (section != null)
{
repository.setDescription(section.getParameter("description"));
repository.setContact(section.getParameter("contact"));
String read = section.getParameter("allow_read");
String write = section.getParameter("allow_push");
if ((read != null) || (write != null))
{
if (read == null)
{
read = "";
}
if (write == null)
{
write = "";
}
List<Permission> permissions =
new HgPermissionReader().readPermissions(read, write);
repository.setPermissions(permissions);
}
}
INISection scmSection = iniConfig.getSection("scm");
if (scmSection != null)
{
String id = scmSection.getParameter("id");
repository.setId(id);
String creationDateString = scmSection.getParameter("creationDate");
if (Util.isNotEmpty(creationDateString))
{
try
{
repository.setCreationDate(
Util.parseDate(creationDateString).getTime());
}
catch (ParseException ex)
{
logger.error(ex.getMessage(), ex);
}
}
}
}
catch (IOException ex)
{
logger.error(ex.getMessage(), ex);
}
}
}
/**
* Method description
*
*
* @param repository
* @param hgDirectory
*
* @throws IOException
*/
private void storeRepository(Repository repository, File hgDirectory)
throws IOException
{
INISection section = new INISection("web");
section.setParameter("name", repository.getName());
String description = repository.getDescription();
if (Util.isNotEmpty(description))
{
section.setParameter("description", description);
}
String contact = repository.getContact();
if (Util.isNotEmpty(contact))
{
section.setParameter("contact", contact);
}
section.setParameter("push_ssl", "false");
Collection<Permission> permissions = repository.getPermissions();
if (permissions != null)
{
appendPermission(section, permissions);
}
INISection scmSection = new INISection("scm");
scmSection.setParameter("id", repository.getId());
long creationDate = repository.getCreationDate();
if (creationDate >= -1)
{
scmSection.setParameter("creationDate",
Util.formatDate(new Date(creationDate)));
}
INIConfiguration iniConfig = new INIConfiguration();
iniConfig.addSection(section);
iniConfig.addSection(scmSection);
File hgrc = new File(hgDirectory, "hgrc");
INIConfigurationWriter writer = new INIConfigurationWriter();
writer.write(iniConfig, hgrc);
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param id
*
* @return
*/
private File getDirectory(String id)
{
return new File(config.getRepositoryDirectory(), id);
}
/**
* Method description
*
*
* @return
*/
private File getRepositoryDirectory()
{
File directory = null;
if (isConfigured())
{
directory = config.getRepositoryDirectory();
if (!directory.exists() &&!directory.mkdirs())
{
throw new ConfigurationException(
"could not create directory ".concat(directory.getPath()));
}
}
return directory;
}
}

View File

@@ -29,6 +29,8 @@
*
*/
package sonia.scm.web;
//~--- non-JDK imports --------------------------------------------------------
@@ -50,7 +52,7 @@ public class HgUtil
public static final String CGI_DIRECTORY = "cgi-bin";
/** Field description */
public static final String CGI_NAME = "hgweb.cgi";
public static final String CGI_NAME = "hgweb.py";
//~--- get methods ----------------------------------------------------------

View File

@@ -59,10 +59,8 @@ public class HgWebConfigWriter
{
/** Field description */
public static final String CGI_TEMPLATE = "/sonia/scm/hgweb.cgi";
public static final String CGI_TEMPLATE = "/sonia/scm/hgweb.py";
/** Field description */
public static final String CONFIG_NAME = "hgweb.config";
//~--- constructors ---------------------------------------------------------
@@ -88,13 +86,9 @@ public class HgWebConfigWriter
*/
public void write() throws IOException
{
File webConfigFile = new File(config.getRepositoryDirectory(), CONFIG_NAME);
writeWebConfigFile(webConfigFile);
File cgiFile = HgUtil.getCGI();
writeCGIFile(cgiFile, webConfigFile);
writeCGIFile(cgiFile);
}
/**
@@ -102,11 +96,10 @@ public class HgWebConfigWriter
*
*
* @param cgiFile
* @param webConfigFile
*
* @throws IOException
*/
private void writeCGIFile(File cgiFile, File webConfigFile) throws IOException
private void writeCGIFile(File cgiFile) throws IOException
{
InputStream input = null;
OutputStream output = null;
@@ -119,7 +112,6 @@ public class HgWebConfigWriter
ResourceProcessor rp = new RegexResourceProcessor();
rp.addVariable("python", config.getPythonBinary());
rp.addVariable("config", webConfigFile.getAbsolutePath());
rp.process(input, output);
cgiFile.setExecutable(true);
}
@@ -130,30 +122,6 @@ public class HgWebConfigWriter
}
}
/**
* Method description
*
*
* @param webConfigFile
*
* @throws IOException
*/
private void writeWebConfigFile(File webConfigFile) throws IOException
{
INIConfiguration webConfig = new INIConfiguration();
INISection pathsSection = new INISection("paths");
String path = config.getRepositoryDirectory().getAbsolutePath();
if (!path.endsWith(File.separator))
{
path = path.concat(File.separator);
}
pathsSection.setParameter("/", path.concat("*"));
webConfig.addSection(pathsSection);
new INIConfigurationWriter().write(webConfig, webConfigFile);
}
//~--- fields ---------------------------------------------------------------
/** Field description */

View File

@@ -67,31 +67,6 @@ public class SvnRepositoryHandler
//~--- get methods ----------------------------------------------------------
/**
* TODO dont use getAll
*
*
* @param name
*
* @return
*/
public Repository getByName(String name)
{
Repository repository = null;
for (Repository r : getAll())
{
if (r.getName().equals(name))
{
repository = r;
break;
}
}
return repository;
}
/**
* Method description
*

View File

@@ -301,6 +301,56 @@ public abstract class AbstractSimpleRepositoryHandler<C extends SimpleRepository
return repositories;
}
/**
* Method description
*
*
* @param repositoryname
*
* @return
*/
public Repository getByName(String repositoryname)
{
Repository repository = null;
for (Repository r : getAll())
{
if (r.getName().equals(repositoryname))
{
repository = r;
break;
}
}
return repository;
}
/**
* Method description
*
*
* @param repository
*
* @return
*/
public File getDirectory(Repository repository)
{
File directory = null;
if (isConfigured())
{
directory = new File(config.getRepositoryDirectory(),
repository.getName());
}
else
{
throw new ConfigurationException("RepositoryHandler is not configured");
}
return directory;
}
//~--- methods --------------------------------------------------------------
/**
@@ -400,31 +450,6 @@ public abstract class AbstractSimpleRepositoryHandler<C extends SimpleRepository
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param repository
*
* @return
*/
protected File getDirectory(Repository repository)
{
File directory = null;
if (isConfigured())
{
directory = new File(config.getRepositoryDirectory(),
repository.getName());
}
else
{
throw new ConfigurationException("RepositoryHandler is not configured");
}
return directory;
}
/**
* Method description
*