mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-06-15 21:50:46 +02:00
merge with branch issue-47
This commit is contained in:
@@ -59,6 +59,20 @@ public class ScmClientConfig
|
||||
this.dateFormat = dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs {@link ScmClientConfig} object
|
||||
*
|
||||
* @since 1.9
|
||||
*
|
||||
* @param dateFormat
|
||||
* @param disableGroupingGrid true to disable repository grouping
|
||||
*/
|
||||
public ScmClientConfig(String dateFormat, boolean disableGroupingGrid)
|
||||
{
|
||||
this.dateFormat = dateFormat;
|
||||
this.disableGroupingGrid = disableGroupingGrid;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -74,6 +88,18 @@ public class ScmClientConfig
|
||||
return dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the grouping of repositories is disabled.
|
||||
*
|
||||
* @since 1.9
|
||||
*
|
||||
* @return true if the grouping of repositories is disabled
|
||||
*/
|
||||
public boolean isDisableGroupingGrid()
|
||||
{
|
||||
return disableGroupingGrid;
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -88,8 +114,24 @@ public class ScmClientConfig
|
||||
this.dateFormat = dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the grouping of repositories.
|
||||
*
|
||||
* @since 1.9
|
||||
*
|
||||
*
|
||||
* @param disableGroupingGrid
|
||||
*/
|
||||
public void setDisableGroupingGrid(boolean disableGroupingGrid)
|
||||
{
|
||||
this.disableGroupingGrid = disableGroupingGrid;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private String dateFormat;
|
||||
|
||||
/** Field description */
|
||||
private boolean disableGroupingGrid = true;
|
||||
}
|
||||
|
||||
@@ -164,6 +164,7 @@ public class ScmConfiguration
|
||||
this.proxyPassword = other.proxyPassword;
|
||||
this.forceBaseUrl = other.forceBaseUrl;
|
||||
this.baseUrl = other.baseUrl;
|
||||
this.disableGroupingGrid = other.disableGroupingGrid;
|
||||
|
||||
// deprecated fields
|
||||
this.sslPort = other.sslPort;
|
||||
@@ -345,6 +346,17 @@ public class ScmConfiguration
|
||||
return anonymousAccessEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
* @since 1.9
|
||||
* @return
|
||||
*/
|
||||
public boolean isDisableGroupingGrid()
|
||||
{
|
||||
return disableGroupingGrid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if port forwarding is enabled.
|
||||
*
|
||||
@@ -451,6 +463,18 @@ public class ScmConfiguration
|
||||
this.dateFormat = dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
* @since 1.9
|
||||
*
|
||||
* @param disableGroupingGrid
|
||||
*/
|
||||
public void setDisableGroupingGrid(boolean disableGroupingGrid)
|
||||
{
|
||||
this.disableGroupingGrid = disableGroupingGrid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -658,6 +682,9 @@ public class ScmConfiguration
|
||||
private Set<ConfigChangedListener> listeners =
|
||||
new HashSet<ConfigChangedListener>();
|
||||
|
||||
/** Field description */
|
||||
private boolean disableGroupingGrid = false;
|
||||
|
||||
/**
|
||||
* JavaScript date format, see http://jacwright.com/projects/javascript/date_format
|
||||
*/
|
||||
|
||||
@@ -64,6 +64,9 @@ public abstract class AbstractSimpleRepositoryHandler<C extends SimpleRepository
|
||||
/** Field description */
|
||||
public static final String DIRECTORY_REPOSITORY = "repositories";
|
||||
|
||||
/** Field description */
|
||||
public static final String DOT = ".";
|
||||
|
||||
/** the logger for AbstractSimpleRepositoryHandler */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(AbstractSimpleRepositoryHandler.class);
|
||||
@@ -106,6 +109,7 @@ public abstract class AbstractSimpleRepositoryHandler<C extends SimpleRepository
|
||||
throw new RepositoryAllreadyExistExeption();
|
||||
}
|
||||
|
||||
checkPath(directory);
|
||||
fileSystem.create(directory);
|
||||
create(repository, directory);
|
||||
postCreate(repository, directory);
|
||||
@@ -219,8 +223,18 @@ public abstract class AbstractSimpleRepositoryHandler<C extends SimpleRepository
|
||||
|
||||
if (isConfigured())
|
||||
{
|
||||
directory = new File(config.getRepositoryDirectory(),
|
||||
repository.getName());
|
||||
File repositoryDirectory = config.getRepositoryDirectory();
|
||||
|
||||
directory = new File(repositoryDirectory, repository.getName());
|
||||
|
||||
if (!IOUtil.isChild(repositoryDirectory, directory))
|
||||
{
|
||||
StringBuilder msg = new StringBuilder(directory.getPath());
|
||||
|
||||
msg.append("is not a child of ").append(repositoryDirectory.getPath());
|
||||
|
||||
throw new ConfigurationException(msg.toString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -298,6 +312,58 @@ public abstract class AbstractSimpleRepositoryHandler<C extends SimpleRepository
|
||||
protected void postCreate(Repository repository, File directory)
|
||||
throws IOException, RepositoryException {}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns true if the directory is a repository.
|
||||
*
|
||||
*
|
||||
* @param directory directory to check
|
||||
*
|
||||
* @return true if the directory is a repository
|
||||
* @since 1.9
|
||||
*/
|
||||
protected boolean isRepository(File directory)
|
||||
{
|
||||
return new File(directory, DOT.concat(getType().getName())).exists();
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Check path for existing repositories
|
||||
*
|
||||
*
|
||||
* @param directory repository target directory
|
||||
*
|
||||
* @throws RepositoryAllreadyExistExeption
|
||||
*/
|
||||
private void checkPath(File directory) throws RepositoryAllreadyExistExeption
|
||||
{
|
||||
File repositoryDirectory = config.getRepositoryDirectory();
|
||||
File parent = directory.getParentFile();
|
||||
|
||||
while ((parent != null) &&!repositoryDirectory.equals(parent))
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("check {} for existing repository", parent);
|
||||
}
|
||||
|
||||
if (isRepository(parent))
|
||||
{
|
||||
if (logger.isErrorEnabled())
|
||||
{
|
||||
logger.error("parent path {} is a repository", parent);
|
||||
}
|
||||
|
||||
throw new RepositoryAllreadyExistExeption();
|
||||
}
|
||||
|
||||
parent = parent.getParentFile();
|
||||
}
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
|
||||
@@ -434,7 +434,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject
|
||||
/**
|
||||
* Returns true if the {@link Repository} is valid.
|
||||
* <ul>
|
||||
* <li>The name is not empty and contains only A-z, 0-9, _, -</li>
|
||||
* <li>The name is not empty and contains only A-z, 0-9, _, -, /</li>
|
||||
* <li>The type is not empty</li>
|
||||
* <li>The contact is empty or contains a valid email address</li>
|
||||
* </ul>
|
||||
@@ -445,7 +445,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
return ValidationUtil.isNameValid(name) && Util.isNotEmpty(type)
|
||||
return ValidationUtil.isRepositoryNameValid(name) && Util.isNotEmpty(type)
|
||||
&& ((Util.isEmpty(contact))
|
||||
|| ValidationUtil.isMailAddressValid(contact));
|
||||
}
|
||||
|
||||
@@ -43,6 +43,8 @@ import sonia.scm.TypeManager;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* The central class for managing {@link Repository} objects.
|
||||
* This class is a singleton and is available via injection.
|
||||
@@ -80,6 +82,41 @@ public interface RepositoryManager
|
||||
*/
|
||||
public Collection<Type> getConfiguredTypes();
|
||||
|
||||
/**
|
||||
* Returns the {@link Repository} associated to the request uri.
|
||||
*
|
||||
*
|
||||
* @param request the current http request
|
||||
*
|
||||
* @return associated to the request uri
|
||||
* @since 1.9
|
||||
*/
|
||||
public Repository getFromRequest(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* Returns the {@link Repository} associated to the given type and path.
|
||||
*
|
||||
*
|
||||
* @param type type of the repository (hg, git ...)
|
||||
* @param uri
|
||||
*
|
||||
* @return the {@link Repository} associated to the given type and path
|
||||
* @since 1.9
|
||||
*/
|
||||
public Repository getFromTypeAndUri(String type, String uri);
|
||||
|
||||
/**
|
||||
* Returns the {@link Repository} associated to the request uri.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param uri request uri without context path
|
||||
*
|
||||
* @return associated to the request uri
|
||||
* @since 1.9
|
||||
*/
|
||||
public Repository getFromUri(String uri);
|
||||
|
||||
/**
|
||||
* Returns a {@link RepositoryHandler} by the given type (hg, git, svn ...).
|
||||
*
|
||||
|
||||
@@ -592,6 +592,30 @@ public class IOUtil
|
||||
return cmds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
*
|
||||
* @return
|
||||
* @since 1.9
|
||||
*/
|
||||
public static String trimSeperatorChars(String name)
|
||||
{
|
||||
if (name.startsWith(File.separator))
|
||||
{
|
||||
name = name.substring(1);
|
||||
}
|
||||
|
||||
if (name.endsWith(File.separator))
|
||||
{
|
||||
name = name.substring(0, name.length() - 1);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -664,6 +688,29 @@ public class IOUtil
|
||||
return getScript(baseFile, baseFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param parent
|
||||
* @param child
|
||||
* @since 1.9
|
||||
*
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public static boolean isChild(File parent, File child)
|
||||
{
|
||||
try
|
||||
{
|
||||
return child.getCanonicalPath().startsWith(parent.getCanonicalPath());
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -51,6 +51,9 @@ public class ValidationUtil
|
||||
/** Field description */
|
||||
private static final String REGEX_NAME = "^[A-z0-9\\.\\-_]+$";
|
||||
|
||||
/** Field description */
|
||||
private static final String REGEX_REPOSITORYNAME = "^[A-z0-9\\.\\-_/]+$";
|
||||
|
||||
/** Field description */
|
||||
private static final String REGEX_USERNAME = "^[^ ][A-z0-9\\.\\-_@ ]+[^ ]$";
|
||||
|
||||
@@ -125,6 +128,20 @@ public class ValidationUtil
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* @since 1.9
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static boolean isRepositoryNameValid(String name)
|
||||
{
|
||||
return Util.isNotEmpty(name) && name.matches(REGEX_REPOSITORYNAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* 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.filter;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.9
|
||||
*/
|
||||
public abstract class ProviderPermissionFilter extends PermissionFilter
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param securityContextProvider
|
||||
* @param repositoryProvider
|
||||
*/
|
||||
public ProviderPermissionFilter(
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
Provider<Repository> repositoryProvider)
|
||||
{
|
||||
super(securityContextProvider);
|
||||
this.repositoryProvider = repositoryProvider;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected Repository getRepository(HttpServletRequest request)
|
||||
{
|
||||
return repositoryProvider.get();
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Provider<Repository> repositoryProvider;
|
||||
}
|
||||
@@ -62,6 +62,9 @@ public class GitRepositoryHandler
|
||||
extends AbstractSimpleRepositoryHandler<GitConfig>
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String DIRECTORY_REFS = "refs";
|
||||
|
||||
/** Field description */
|
||||
public static final String TYPE_DISPLAYNAME = "Git";
|
||||
|
||||
@@ -267,4 +270,18 @@ public class GitRepositoryHandler
|
||||
{
|
||||
return GitConfig.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param directory
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected boolean isRepository(File directory)
|
||||
{
|
||||
return new File(directory, DIRECTORY_REFS).exists();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,9 +39,8 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import sonia.scm.repository.GitRepositoryHandler;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.web.filter.RegexPermissionFilter;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.web.filter.ProviderPermissionFilter;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
@@ -53,7 +52,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Singleton
|
||||
public class GitPermissionFilter extends RegexPermissionFilter
|
||||
public class GitPermissionFilter extends ProviderPermissionFilter
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
@@ -76,30 +75,18 @@ public class GitPermissionFilter extends RegexPermissionFilter
|
||||
*
|
||||
*
|
||||
* @param securityContextProvider
|
||||
* @param repositoryManager
|
||||
* @param repositoryProvider
|
||||
*/
|
||||
@Inject
|
||||
public GitPermissionFilter(
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryManager repositoryManager)
|
||||
Provider<Repository> repositoryProvider)
|
||||
{
|
||||
super(securityContextProvider, repositoryManager);
|
||||
super(securityContextProvider, repositoryProvider);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected String getType()
|
||||
{
|
||||
return GitRepositoryHandler.TYPE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
@@ -86,56 +86,6 @@ public class GitRepositoryResolver
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static boolean isUnreasonableName(final String name)
|
||||
{
|
||||
if (name.length() == 0)
|
||||
{
|
||||
return true; // no empty paths
|
||||
}
|
||||
|
||||
if (name.indexOf('\\') >= 0)
|
||||
{
|
||||
return true; // no windows/dos style paths
|
||||
}
|
||||
|
||||
if (new File(name).isAbsolute())
|
||||
{
|
||||
return true; // no absolute paths
|
||||
}
|
||||
|
||||
if (name.startsWith("../"))
|
||||
{
|
||||
return true; // no "l../etc/passwd"
|
||||
}
|
||||
|
||||
if (name.contains("/../"))
|
||||
{
|
||||
return true; // no "foo/../etc/passwd"
|
||||
}
|
||||
|
||||
if (name.contains("/./"))
|
||||
{
|
||||
return true; // "foo/./foo" is insane to ask
|
||||
}
|
||||
|
||||
if (name.contains("//"))
|
||||
{
|
||||
return true; // double slashes is sloppy, don't use it
|
||||
}
|
||||
|
||||
return false; // is a reasonable name
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -158,11 +108,6 @@ public class GitRepositoryResolver
|
||||
{
|
||||
Repository repository = null;
|
||||
|
||||
if (isUnreasonableName(repositoryName))
|
||||
{
|
||||
throw new RepositoryNotFoundException(repositoryName);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
GitConfig config = handler.getConfig();
|
||||
|
||||
@@ -36,21 +36,20 @@ package sonia.scm.web;
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.jgit.http.server.GitServlet;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.transport.resolver.RepositoryResolver;
|
||||
|
||||
import sonia.scm.repository.GitUtil;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -70,10 +69,6 @@ public class ScmGitServlet extends GitServlet
|
||||
/** Field description */
|
||||
private static final long serialVersionUID = -7712897339207470674L;
|
||||
|
||||
/** Field description */
|
||||
private static final Pattern REGEX_REPOSITORYNAME =
|
||||
Pattern.compile("/git/([^/]+)/?.*");
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -83,12 +78,16 @@ public class ScmGitServlet extends GitServlet
|
||||
*
|
||||
* @param repositoryResolver
|
||||
* @param receivePackFactory
|
||||
* @param repositoryProvider
|
||||
*/
|
||||
@Inject
|
||||
public ScmGitServlet(GitRepositoryResolver repositoryResolver,
|
||||
GitReceivePackFactory receivePackFactory)
|
||||
public ScmGitServlet(
|
||||
GitRepositoryResolver repositoryResolver,
|
||||
GitReceivePackFactory receivePackFactory,
|
||||
Provider<sonia.scm.repository.Repository> repositoryProvider)
|
||||
{
|
||||
this.resolver = repositoryResolver;
|
||||
this.repositoryProvider = repositoryProvider;
|
||||
setRepositoryResolver(repositoryResolver);
|
||||
setReceivePackFactory(receivePackFactory);
|
||||
}
|
||||
@@ -137,43 +136,38 @@ public class ScmGitServlet extends GitServlet
|
||||
HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
String uri = HttpUtil.getStrippedURI(request);
|
||||
Matcher m = REGEX_REPOSITORYNAME.matcher(uri);
|
||||
String name = null;
|
||||
Repository repository = null;
|
||||
sonia.scm.repository.Repository scmRepository = repositoryProvider.get();
|
||||
|
||||
try
|
||||
if (scmRepository != null)
|
||||
{
|
||||
if (m.matches())
|
||||
{
|
||||
name = m.group(1);
|
||||
repository = resolver.open(request, name);
|
||||
}
|
||||
Repository repository = null;
|
||||
|
||||
if (repository != null)
|
||||
try
|
||||
{
|
||||
new GitRepositoryViewer().handleRequest(response, repository, name);
|
||||
repository = resolver.open(request, scmRepository.getName());
|
||||
new GitRepositoryViewer().handleRequest(response, repository,
|
||||
scmRepository.getName());
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
throw new ServletException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
GitUtil.close(repository);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
throw new ServletException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (repository != null)
|
||||
{
|
||||
repository.close();
|
||||
}
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Provider<sonia.scm.repository.Repository> repositoryProvider;
|
||||
|
||||
/** Field description */
|
||||
private RepositoryResolver<HttpServletRequest> resolver;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,6 @@ public class UnixHgInstaller extends AbstractHgInstaller
|
||||
super.install(baseDirectory, config);
|
||||
|
||||
// search mercurial (hg)
|
||||
|
||||
if (Util.isEmpty(config.getHgBinary()))
|
||||
{
|
||||
String hg = IOUtil.search(COMMAND_HG);
|
||||
@@ -100,9 +99,8 @@ public class UnixHgInstaller extends AbstractHgInstaller
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// search python
|
||||
|
||||
// search python
|
||||
if (Util.isEmpty(config.getPythonBinary()))
|
||||
{
|
||||
config.setPythonBinary(IOUtil.search(COMMAND_PYTHON));
|
||||
|
||||
@@ -272,8 +272,9 @@ public class WindowsHgInstaller extends AbstractHgInstaller
|
||||
IOUtil.copy(templateDirectory, new File(libDir, FILE_TEMPLATES));
|
||||
}
|
||||
|
||||
File hg = new File( hgDirectory, FILE_MERCURIAL_EXE );
|
||||
if ( hg.exists() )
|
||||
File hg = new File(hgDirectory, FILE_MERCURIAL_EXE);
|
||||
|
||||
if (hg.exists())
|
||||
{
|
||||
config.setHgBinary(hg.getAbsolutePath());
|
||||
}
|
||||
@@ -322,8 +323,8 @@ public class WindowsHgInstaller extends AbstractHgInstaller
|
||||
private File getMercurialDirectory(String hgBinary)
|
||||
{
|
||||
File directory = null;
|
||||
|
||||
if ( Util.isNotEmpty(hgBinary) )
|
||||
|
||||
if (Util.isNotEmpty(hgBinary))
|
||||
{
|
||||
File hg = new File(hgBinary);
|
||||
|
||||
@@ -332,8 +333,8 @@ public class WindowsHgInstaller extends AbstractHgInstaller
|
||||
directory = hg.getParentFile();
|
||||
}
|
||||
}
|
||||
|
||||
if ( directory == null )
|
||||
|
||||
if (directory == null)
|
||||
{
|
||||
directory = getMercurialDirectoryFromRegistry();
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ 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.config.ScmConfiguration;
|
||||
@@ -55,7 +56,6 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
@@ -102,19 +102,19 @@ public class HgCGIServlet extends HttpServlet
|
||||
*
|
||||
* @param cgiExecutorFactory
|
||||
* @param configuration
|
||||
* @param repositoryManager
|
||||
* @param repositoryProvider
|
||||
* @param handler
|
||||
* @param hookManager
|
||||
*/
|
||||
@Inject
|
||||
public HgCGIServlet(CGIExecutorFactory cgiExecutorFactory,
|
||||
ScmConfiguration configuration,
|
||||
RepositoryManager repositoryManager,
|
||||
Provider<Repository> repositoryProvider,
|
||||
HgRepositoryHandler handler, HgHookManager hookManager)
|
||||
{
|
||||
this.cgiExecutorFactory = cgiExecutorFactory;
|
||||
this.configuration = configuration;
|
||||
this.repositoryManager = repositoryManager;
|
||||
this.repositoryProvider = repositoryProvider;
|
||||
this.handler = handler;
|
||||
this.hookManager = hookManager;
|
||||
}
|
||||
@@ -149,7 +149,7 @@ public class HgCGIServlet extends HttpServlet
|
||||
HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
Repository repository = getRepository(request);
|
||||
Repository repository = repositoryProvider.get();
|
||||
|
||||
if (repository == null)
|
||||
{
|
||||
@@ -244,46 +244,6 @@ public class HgCGIServlet extends HttpServlet
|
||||
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 */
|
||||
@@ -302,5 +262,5 @@ public class HgCGIServlet extends HttpServlet
|
||||
private HgHookManager hookManager;
|
||||
|
||||
/** Field description */
|
||||
private RepositoryManager repositoryManager;
|
||||
private Provider<Repository> repositoryProvider;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.security.CipherUtil;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
import sonia.scm.util.IOUtil;
|
||||
import sonia.scm.util.Util;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
|
||||
@@ -80,6 +81,9 @@ public class HgHookCallbackServlet extends HttpServlet
|
||||
/** Field description */
|
||||
public static final String HGHOOK_PRE_RECEIVE = "pretxnchangegroup";
|
||||
|
||||
/** Field description */
|
||||
public static final String PARAM_REPOSITORYPATH = "repositoryPath";
|
||||
|
||||
/** Field description */
|
||||
private static final String PARAM_CHALLENGE = "challenge";
|
||||
|
||||
@@ -91,7 +95,7 @@ public class HgHookCallbackServlet extends HttpServlet
|
||||
|
||||
/** Field description */
|
||||
private static final Pattern REGEX_URL =
|
||||
Pattern.compile("^/hook/hg/([^/]+)/([^/]+)$");
|
||||
Pattern.compile("^/hook/hg/([^/]+)$");
|
||||
|
||||
/** the logger for HgHookCallbackServlet */
|
||||
private static final Logger logger =
|
||||
@@ -144,8 +148,8 @@ public class HgHookCallbackServlet extends HttpServlet
|
||||
|
||||
if (m.matches())
|
||||
{
|
||||
String repositoryId = m.group(1);
|
||||
String type = m.group(2);
|
||||
String repositoryId = getRepositoryName(request);
|
||||
String type = m.group(1);
|
||||
String challenge = request.getParameter(PARAM_CHALLENGE);
|
||||
|
||||
if (Util.isNotEmpty(challenge))
|
||||
@@ -316,6 +320,43 @@ public class HgHookCallbackServlet extends HttpServlet
|
||||
}
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getRepositoryName(HttpServletRequest request)
|
||||
{
|
||||
String name = null;
|
||||
String path = request.getParameter(PARAM_REPOSITORYPATH);
|
||||
|
||||
if (Util.isNotEmpty(path))
|
||||
{
|
||||
int directoryLength =
|
||||
handler.getConfig().getRepositoryDirectory().getAbsolutePath().length();
|
||||
|
||||
if (directoryLength < path.length())
|
||||
{
|
||||
name = IOUtil.trimSeperatorChars(path.substring(directoryLength));
|
||||
}
|
||||
else if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("path is shorter as the main hg repository path");
|
||||
}
|
||||
}
|
||||
else if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("no repository path parameter found");
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
|
||||
@@ -39,9 +39,8 @@ 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.repository.Repository;
|
||||
import sonia.scm.web.filter.ProviderPermissionFilter;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
@@ -53,7 +52,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Singleton
|
||||
public class HgPermissionFilter extends RegexPermissionFilter
|
||||
public class HgPermissionFilter extends ProviderPermissionFilter
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -61,30 +60,18 @@ public class HgPermissionFilter extends RegexPermissionFilter
|
||||
*
|
||||
*
|
||||
* @param securityContextProvider
|
||||
* @param repositoryManager
|
||||
* @param repositoryProvider
|
||||
*/
|
||||
@Inject
|
||||
public HgPermissionFilter(
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryManager repositoryManager)
|
||||
Provider<Repository> repositoryProvider)
|
||||
{
|
||||
super(securityContextProvider, repositoryManager);
|
||||
super(securityContextProvider, repositoryProvider);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected String getType()
|
||||
{
|
||||
return HgRepositoryHandler.TYPE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
@@ -48,9 +48,9 @@ def callback(ui, repo, hooktype, node=None, source=None, pending=None, **kwargs)
|
||||
failure = True
|
||||
if node != None:
|
||||
try:
|
||||
url = baseUrl + os.path.basename(repo.root) + "/" + hooktype
|
||||
url = baseUrl + hooktype
|
||||
ui.debug( "send scm-hook to " + url + " and " + node + "\n" )
|
||||
data = urllib.urlencode({'node': node, 'challenge': challenge, 'credentials': credentials})
|
||||
data = urllib.urlencode({'node': node, 'challenge': challenge, 'credentials': credentials, 'repositoryPath': repo.root})
|
||||
conn = urllib.urlopen(url, data);
|
||||
if conn.code >= 200 and conn.code < 300:
|
||||
ui.debug( "scm-hook " + hooktype + " success with status code " + str(conn.code) + "\n" )
|
||||
|
||||
@@ -102,7 +102,7 @@ public class SvnRepositoryHandler
|
||||
// register hook
|
||||
if (repositoryManager != null)
|
||||
{
|
||||
FSHooks.registerHook(new SvnRepositoryHook(repositoryManager));
|
||||
FSHooks.registerHook(new SvnRepositoryHook(repositoryManager, this));
|
||||
}
|
||||
else if (logger.isWarnEnabled())
|
||||
{
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.tmatesoft.svn.core.internal.io.fs.FSHook;
|
||||
import org.tmatesoft.svn.core.internal.io.fs.FSHookEvent;
|
||||
import org.tmatesoft.svn.core.internal.io.fs.FSHooks;
|
||||
|
||||
import sonia.scm.util.IOUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
@@ -70,10 +71,13 @@ public class SvnRepositoryHook implements FSHook
|
||||
*
|
||||
*
|
||||
* @param repositoryManager
|
||||
* @param handler
|
||||
*/
|
||||
public SvnRepositoryHook(RepositoryManager repositoryManager)
|
||||
public SvnRepositoryHook(RepositoryManager repositoryManager,
|
||||
SvnRepositoryHandler handler)
|
||||
{
|
||||
this.repositoryManager = repositoryManager;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
@@ -151,8 +155,14 @@ public class SvnRepositoryHook implements FSHook
|
||||
{
|
||||
try
|
||||
{
|
||||
repositoryManager.fireHookEvent(SvnRepositoryHandler.TYPE_NAME,
|
||||
directory.getName(), hookEvent);
|
||||
String name =
|
||||
directory.getAbsolutePath()
|
||||
.substring(handler.getConfig().getRepositoryDirectory()
|
||||
.getAbsolutePath().length());
|
||||
|
||||
name = IOUtil.trimSeperatorChars(name);
|
||||
repositoryManager.fireHookEvent(SvnRepositoryHandler.TYPE_NAME, name,
|
||||
hookEvent);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -168,6 +178,9 @@ public class SvnRepositoryHook implements FSHook
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private SvnRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private RepositoryManager repositoryManager;
|
||||
}
|
||||
|
||||
@@ -35,10 +35,17 @@ package sonia.scm.web;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import org.tmatesoft.svn.core.internal.server.dav.DAVConfig;
|
||||
import org.tmatesoft.svn.core.internal.server.dav.SVNPathBasedAccess;
|
||||
|
||||
import sonia.scm.repository.SvnConfig;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.SvnRepositoryHandler;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -52,12 +59,15 @@ public class SvnDAVConfig extends DAVConfig
|
||||
*
|
||||
*
|
||||
* @param davConfig
|
||||
* @param config
|
||||
* @param handler
|
||||
* @param repositoryProvider
|
||||
*/
|
||||
public SvnDAVConfig(DAVConfig davConfig, SvnConfig config)
|
||||
public SvnDAVConfig(DAVConfig davConfig, SvnRepositoryHandler handler,
|
||||
Provider<Repository> repositoryProvider)
|
||||
{
|
||||
this.davConfig = davConfig;
|
||||
this.config = config;
|
||||
this.handler = handler;
|
||||
this.repositoryProvider = repositoryProvider;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
@@ -71,7 +81,7 @@ public class SvnDAVConfig extends DAVConfig
|
||||
@Override
|
||||
public String getActivitiesDBPath()
|
||||
{
|
||||
return davConfig.getActivitiesDBPath();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,7 +105,19 @@ public class SvnDAVConfig extends DAVConfig
|
||||
@Override
|
||||
public String getRepositoryParentPath()
|
||||
{
|
||||
return config.getRepositoryDirectory().getAbsolutePath();
|
||||
String path = null;
|
||||
File directory = getRepositoryDirectory();
|
||||
|
||||
if (directory != null)
|
||||
{
|
||||
path = directory.getParent();
|
||||
}
|
||||
else
|
||||
{
|
||||
path = davConfig.getRepositoryPath();
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +129,19 @@ public class SvnDAVConfig extends DAVConfig
|
||||
@Override
|
||||
public String getRepositoryPath()
|
||||
{
|
||||
return davConfig.getRepositoryPath();
|
||||
String path = null;
|
||||
File directory = getRepositoryDirectory();
|
||||
|
||||
if (directory != null)
|
||||
{
|
||||
path = directory.getAbsolutePath();
|
||||
}
|
||||
else
|
||||
{
|
||||
path = davConfig.getRepositoryPath();
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -227,14 +261,36 @@ public class SvnDAVConfig extends DAVConfig
|
||||
@Override
|
||||
public boolean isUsingRepositoryPathDirective()
|
||||
{
|
||||
return davConfig.isUsingRepositoryPathDirective();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private File getRepositoryDirectory()
|
||||
{
|
||||
File directory = null;
|
||||
Repository repository = repositoryProvider.get();
|
||||
|
||||
if (repository != null)
|
||||
{
|
||||
directory = handler.getDirectory(repository);
|
||||
}
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private SvnConfig config;
|
||||
private DAVConfig davConfig;
|
||||
|
||||
/** Field description */
|
||||
private DAVConfig davConfig;
|
||||
private SvnRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private Provider<Repository> repositoryProvider;
|
||||
}
|
||||
|
||||
@@ -36,12 +36,26 @@ package sonia.scm.web;
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.tmatesoft.svn.core.internal.server.dav.DAVConfig;
|
||||
import org.tmatesoft.svn.core.internal.server.dav.DAVServlet;
|
||||
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.SvnRepositoryHandler;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -61,11 +75,34 @@ public class SvnDAVServlet extends DAVServlet
|
||||
*
|
||||
*
|
||||
* @param handler
|
||||
* @param repositoryProvider
|
||||
*/
|
||||
@Inject
|
||||
public SvnDAVServlet(SvnRepositoryHandler handler)
|
||||
public SvnDAVServlet(SvnRepositoryHandler handler,
|
||||
Provider<Repository> repositoryProvider)
|
||||
{
|
||||
this.handler = handler;
|
||||
this.repositoryProvider = repositoryProvider;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Override
|
||||
public void service(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
super.service(new SvnHttpServletRequestWrapper(request,
|
||||
repositoryProvider), response);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
@@ -79,11 +116,103 @@ public class SvnDAVServlet extends DAVServlet
|
||||
@Override
|
||||
protected DAVConfig getDAVConfig()
|
||||
{
|
||||
return new SvnDAVConfig(super.getDAVConfig(), handler.getConfig());
|
||||
return new SvnDAVConfig(super.getDAVConfig(), handler, repositoryProvider);
|
||||
}
|
||||
|
||||
//~--- inner classes --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class description
|
||||
*
|
||||
*
|
||||
* @version Enter version here..., 11/10/23
|
||||
* @author Enter your name here...
|
||||
*/
|
||||
private static class SvnHttpServletRequestWrapper
|
||||
extends HttpServletRequestWrapper
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
* @param repositoryProvider
|
||||
*/
|
||||
public SvnHttpServletRequestWrapper(HttpServletRequest request,
|
||||
Provider<Repository> repositoryProvider)
|
||||
{
|
||||
super(request);
|
||||
this.repositoryProvider = repositoryProvider;
|
||||
}
|
||||
|
||||
//~--- get methods --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getPathInfo()
|
||||
{
|
||||
String pathInfo = super.getPathInfo();
|
||||
|
||||
AssertUtil.assertIsNotEmpty(pathInfo);
|
||||
|
||||
Repository repository = repositoryProvider.get();
|
||||
|
||||
if (repository != null)
|
||||
{
|
||||
if (pathInfo.startsWith(HttpUtil.SEPARATOR_PATH))
|
||||
{
|
||||
pathInfo = pathInfo.substring(1);
|
||||
}
|
||||
|
||||
pathInfo = pathInfo.substring(repository.getName().length());
|
||||
}
|
||||
|
||||
return pathInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getServletPath()
|
||||
{
|
||||
String servletPath = super.getServletPath();
|
||||
Repository repository = repositoryProvider.get();
|
||||
|
||||
if (repository != null)
|
||||
{
|
||||
if (!servletPath.endsWith(HttpUtil.SEPARATOR_PATH))
|
||||
{
|
||||
servletPath = servletPath.concat(HttpUtil.SEPARATOR_PATH);
|
||||
}
|
||||
|
||||
servletPath = servletPath.concat(repository.getName());
|
||||
}
|
||||
|
||||
return servletPath;
|
||||
}
|
||||
|
||||
//~--- fields -------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Provider<Repository> repositoryProvider;
|
||||
}
|
||||
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private SvnRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private Provider<Repository> repositoryProvider;
|
||||
}
|
||||
|
||||
@@ -39,9 +39,8 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.SvnRepositoryHandler;
|
||||
import sonia.scm.web.filter.RegexPermissionFilter;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.web.filter.ProviderPermissionFilter;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
@@ -57,7 +56,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Singleton
|
||||
public class SvnPermissionFilter extends RegexPermissionFilter
|
||||
public class SvnPermissionFilter extends ProviderPermissionFilter
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
@@ -74,30 +73,18 @@ public class SvnPermissionFilter extends RegexPermissionFilter
|
||||
*
|
||||
*
|
||||
* @param securityContextProvider
|
||||
* @param repositoryManager
|
||||
* @param repository
|
||||
*/
|
||||
@Inject
|
||||
public SvnPermissionFilter(
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryManager repositoryManager)
|
||||
Provider<Repository> repository)
|
||||
{
|
||||
super(securityContextProvider, repositoryManager);
|
||||
super(securityContextProvider, repository);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected String getType()
|
||||
{
|
||||
return SvnRepositoryHandler.TYPE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
@@ -61,8 +61,10 @@ import sonia.scm.plugin.PluginLoader;
|
||||
import sonia.scm.plugin.PluginManager;
|
||||
import sonia.scm.plugin.ScriptResourceServlet;
|
||||
import sonia.scm.repository.ChangesetViewerUtil;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryBrowserUtil;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.RepositoryProvider;
|
||||
import sonia.scm.repository.xml.XmlRepositoryManager;
|
||||
import sonia.scm.security.CipherHandler;
|
||||
import sonia.scm.security.CipherUtil;
|
||||
@@ -203,6 +205,7 @@ public class ScmServletModule extends ServletModule
|
||||
ScmConfiguration config = getScmConfiguration(context);
|
||||
CipherUtil cu = CipherUtil.getInstance();
|
||||
|
||||
bind(Repository.class).toProvider(RepositoryProvider.class);
|
||||
bind(StoreFactory.class).to(JAXBStoreFactory.class);
|
||||
bind(ScmConfiguration.class).toInstance(config);
|
||||
bind(PluginLoader.class).toInstance(pluginLoader);
|
||||
|
||||
@@ -247,7 +247,8 @@ public class AuthenticationResource
|
||||
{
|
||||
return new ScmState(contextProvider, securityContext,
|
||||
repositoryManger.getConfiguredTypes(),
|
||||
new ScmClientConfig(configuration.getDateFormat()));
|
||||
new ScmClientConfig(configuration.getDateFormat(),
|
||||
configuration.isDisableGroupingGrid()));
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
@@ -416,11 +416,10 @@ public class RepositoryResource
|
||||
* @return the {@link Repository} with the specified type and name
|
||||
*/
|
||||
@GET
|
||||
@Path("{type}/{name}")
|
||||
@Path("{type: [a-z]+}/{name: .*}")
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
@TypeHint(Repository.class)
|
||||
public Response getByTypeAndName(@Context Request request,
|
||||
@PathParam("type") String type,
|
||||
public Response getByTypeAndName(@PathParam("type") String type,
|
||||
@PathParam("name") String name)
|
||||
{
|
||||
Response response = null;
|
||||
|
||||
@@ -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.repository;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.servlet.RequestScoped;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RequestScoped
|
||||
public class RepositoryProvider implements Provider<Repository>
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
public static final String ATTRIBUTE_NAME = "scm.request.repository";
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param requestProvider
|
||||
* @param manager
|
||||
*/
|
||||
@Inject
|
||||
public RepositoryProvider(Provider<HttpServletRequest> requestProvider,
|
||||
RepositoryManager manager)
|
||||
{
|
||||
this.requestProvider = requestProvider;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Repository get()
|
||||
{
|
||||
Repository repository = null;
|
||||
HttpServletRequest request = requestProvider.get();
|
||||
|
||||
if (request != null)
|
||||
{
|
||||
repository = (Repository) request.getAttribute(ATTRIBUTE_NAME);
|
||||
|
||||
if (repository == null)
|
||||
{
|
||||
repository = manager.getFromRequest(request);
|
||||
|
||||
if (repository != null)
|
||||
{
|
||||
request.setAttribute(ATTRIBUTE_NAME, repository);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return repository;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private RepositoryManager manager;
|
||||
|
||||
/** Field description */
|
||||
private Provider<HttpServletRequest> requestProvider;
|
||||
}
|
||||
@@ -67,6 +67,7 @@ import sonia.scm.store.Store;
|
||||
import sonia.scm.store.StoreFactory;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.util.CollectionAppender;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
import sonia.scm.util.IOUtil;
|
||||
import sonia.scm.util.SecurityUtil;
|
||||
import sonia.scm.util.Util;
|
||||
@@ -87,6 +88,8 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
@@ -625,6 +628,89 @@ public class XmlRepositoryManager extends AbstractRepositoryManager
|
||||
return viewer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Repository getFromRequest(HttpServletRequest request)
|
||||
{
|
||||
AssertUtil.assertIsNotNull(request);
|
||||
|
||||
return getFromUri(HttpUtil.getStrippedURI(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param type
|
||||
* @param uri
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Repository getFromTypeAndUri(String type, String uri)
|
||||
{
|
||||
AssertUtil.assertIsNotEmpty(type);
|
||||
AssertUtil.assertIsNotEmpty(uri);
|
||||
|
||||
Repository repository = null;
|
||||
|
||||
if (handlerMap.containsKey(type))
|
||||
{
|
||||
Collection<Repository> repositories = repositoryDB.values();
|
||||
|
||||
for (Repository r : repositories)
|
||||
{
|
||||
if (type.equals(r.getType()) && isNameMatching(r, uri))
|
||||
{
|
||||
if (isReader(r))
|
||||
{
|
||||
repository = r.clone();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param uri
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Repository getFromUri(String uri)
|
||||
{
|
||||
AssertUtil.assertIsNotEmpty(uri);
|
||||
|
||||
if (uri.startsWith(HttpUtil.SEPARATOR_PATH))
|
||||
{
|
||||
uri = uri.substring(1);
|
||||
}
|
||||
|
||||
int typeSeperator = uri.indexOf(HttpUtil.SEPARATOR_PATH);
|
||||
|
||||
AssertUtil.assertPositive(typeSeperator);
|
||||
|
||||
String type = uri.substring(0, typeSeperator);
|
||||
|
||||
uri = uri.substring(typeSeperator + 1);
|
||||
|
||||
return getFromTypeAndUri(type, uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -814,6 +900,30 @@ public class XmlRepositoryManager extends AbstractRepositoryManager
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
* @param path
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private boolean isNameMatching(Repository repository, String path)
|
||||
{
|
||||
boolean result = false;
|
||||
String name = repository.getName();
|
||||
|
||||
if (path.startsWith(name))
|
||||
{
|
||||
String sub = path.substring(name.length());
|
||||
|
||||
result = Util.isEmpty(sub) || sub.startsWith(HttpUtil.SEPARATOR_PATH);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
@@ -69,6 +69,8 @@ public class JAXBStore<T> implements Store<T>
|
||||
*/
|
||||
public JAXBStore(Class<T> type, File configFile)
|
||||
{
|
||||
this.type = type;
|
||||
|
||||
try
|
||||
{
|
||||
context = JAXBContext.newInstance(type);
|
||||
@@ -91,6 +93,11 @@ public class JAXBStore<T> implements Store<T>
|
||||
@Override
|
||||
public T get()
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("load {} from store {}", type, configFile);
|
||||
}
|
||||
|
||||
T result = null;
|
||||
|
||||
if (configFile.exists())
|
||||
@@ -108,6 +115,17 @@ public class JAXBStore<T> implements Store<T>
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Class<T> getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -145,4 +163,7 @@ public class JAXBStore<T> implements Store<T>
|
||||
|
||||
/** Field description */
|
||||
private JAXBContext context;
|
||||
|
||||
/** Field description */
|
||||
private Class<T> type;
|
||||
}
|
||||
|
||||
@@ -57,6 +57,9 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{
|
||||
baseUrlText: 'Base Url',
|
||||
forceBaseUrlText: 'Force Base Url',
|
||||
|
||||
// TODO i18n
|
||||
disableGroupingGridText: 'Disable repository Groups',
|
||||
|
||||
|
||||
// help
|
||||
servernameHelpText: 'The name of this server. This name will be part of the repository url.',
|
||||
@@ -79,6 +82,9 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{
|
||||
proxyPasswordHelpText: 'The password for the proxy server authentication.',
|
||||
baseUrlHelpText: 'The url of the application (with context path) i.e. http://localhost:8080/scm',
|
||||
forceBaseUrlHelpText: 'Redirects to the base url if the request comes from a other url',
|
||||
|
||||
// TODO i18n
|
||||
disableGroupingGridHelpText: 'Disable repository Groups. A complete page reload is required after a change of this value.',
|
||||
|
||||
|
||||
initComponent: function(){
|
||||
@@ -100,6 +106,12 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{
|
||||
name: 'force-base-url',
|
||||
inputValue: 'true',
|
||||
helpText: this.forceBaseUrlHelpText
|
||||
},{
|
||||
xtype: 'checkbox',
|
||||
fieldLabel: this.disableGroupingGridText,
|
||||
name: 'disableGroupingGrid',
|
||||
inputValue: 'true',
|
||||
helpText: this.disableGroupingGridHelpText
|
||||
},{
|
||||
xtype: 'textfield',
|
||||
fieldLabel: this.dateFormatText,
|
||||
|
||||
@@ -51,6 +51,13 @@ Ext.apply(Ext.form.VTypes, {
|
||||
|
||||
nameText: 'The name is invalid.',
|
||||
|
||||
// repository name validator
|
||||
repositoryName: function(val){
|
||||
return /^[A-z0-9\.\-_\/]+$/.test(val);
|
||||
},
|
||||
|
||||
repositoryNameText: 'The name of the repository is invalid.',
|
||||
|
||||
// username validator
|
||||
|
||||
username: function(val){
|
||||
|
||||
@@ -42,21 +42,55 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
searchValue: null,
|
||||
typeFilter: null,
|
||||
|
||||
// TODO find better text
|
||||
mainGroup: 'main',
|
||||
|
||||
// for history
|
||||
parentPanel: null,
|
||||
|
||||
initComponent: function(){
|
||||
|
||||
var repositoryStore = new Sonia.rest.JsonStore({
|
||||
var repositoryStore = new Ext.data.GroupingStore({
|
||||
proxy: new Ext.data.HttpProxy({
|
||||
url: restUrl + 'repositories.json',
|
||||
disableCaching: false
|
||||
}),
|
||||
idProperty: 'id',
|
||||
fields: [ 'id', 'name', 'type', 'contact', 'description', 'creationDate', 'url', 'public', 'permissions', 'properties' ],
|
||||
reader: new Ext.data.JsonReader({
|
||||
fields: [{
|
||||
name: 'id'
|
||||
},{
|
||||
name: 'group',
|
||||
convert: this.convertToGroup
|
||||
},{
|
||||
name: 'name'
|
||||
},{
|
||||
name: 'type'
|
||||
},{
|
||||
name: 'contact'
|
||||
},{
|
||||
name: 'description'
|
||||
},{
|
||||
name: 'creationDate'
|
||||
},{
|
||||
name:'url'
|
||||
},{
|
||||
name: 'public'
|
||||
},{
|
||||
name:'permissions'
|
||||
},{
|
||||
name: 'properties'
|
||||
}]
|
||||
}),
|
||||
sortInfo: {
|
||||
field: 'name'
|
||||
},
|
||||
autoDestroy: true,
|
||||
autoLoad: true,
|
||||
remoteGroup: false,
|
||||
groupOnSort: false,
|
||||
groupField: 'group',
|
||||
groupDir: 'AES',
|
||||
listeners: {
|
||||
load: {
|
||||
fn: this.storeLoad,
|
||||
@@ -71,16 +105,58 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
scope: this,
|
||||
width: 125
|
||||
},
|
||||
columns: [
|
||||
{id: 'name', header: this.colNameText, dataIndex: 'name'},
|
||||
{id: 'type', header: this.colTypeText, dataIndex: 'type', renderer: this.renderRepositoryType, width: 80},
|
||||
{id: 'contact', header: this.colContactText, dataIndex: 'contact', renderer: this.renderMailto},
|
||||
{id: 'description', header: this.colDescriptionText, dataIndex: 'description'},
|
||||
{id: 'creationDate', header: this.colCreationDateText, dataIndex: 'creationDate', renderer: Ext.util.Format.formatTimestamp},
|
||||
{id: 'Url', header: this.colUrlText, dataIndex: 'url', renderer: this.renderUrl, width: 250}
|
||||
]
|
||||
columns: [{
|
||||
id: 'name',
|
||||
header: this.colNameText,
|
||||
dataIndex: 'name',
|
||||
renderer: this.renderName,
|
||||
scope: this
|
||||
},{
|
||||
id: 'type',
|
||||
header: this.colTypeText,
|
||||
dataIndex: 'type',
|
||||
renderer: this.renderRepositoryType,
|
||||
width: 80
|
||||
},{
|
||||
id: 'contact',
|
||||
header: this.colContactText,
|
||||
dataIndex: 'contact',
|
||||
renderer: this.renderMailto
|
||||
},{
|
||||
id: 'description',
|
||||
header: this.colDescriptionText,
|
||||
dataIndex: 'description'
|
||||
},{
|
||||
id: 'creationDate',
|
||||
header: this.colCreationDateText,
|
||||
dataIndex: 'creationDate',
|
||||
renderer: Ext.util.Format.formatTimestamp
|
||||
},{
|
||||
id: 'Url',
|
||||
header: this.colUrlText,
|
||||
dataIndex: 'url',
|
||||
renderer: this.renderUrl,
|
||||
width: 250
|
||||
},{
|
||||
id: 'group',
|
||||
dataIndex: 'group',
|
||||
hidden: true,
|
||||
hideable: false,
|
||||
groupRenderer: this.renderGroupName,
|
||||
scope: this
|
||||
}]
|
||||
});
|
||||
|
||||
if (debug){
|
||||
var msg = "grouping is ";
|
||||
if ( state.clientConfig.disableGroupingGrid ){
|
||||
msg += "disabled";
|
||||
} else {
|
||||
msg += "enabled";
|
||||
}
|
||||
console.debug( msg );
|
||||
}
|
||||
|
||||
var config = {
|
||||
autoExpandColumn: 'description',
|
||||
store: repositoryStore,
|
||||
@@ -91,7 +167,15 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
fn: this.onFallBelowMinHeight,
|
||||
scope: this
|
||||
}
|
||||
}
|
||||
},
|
||||
view: new Ext.grid.GroupingView({
|
||||
enableGrouping: ! state.clientConfig.disableGroupingGrid,
|
||||
enableNoGroups: false,
|
||||
forceFit: true,
|
||||
groupMode: 'value',
|
||||
enableGroupingMenu: false,
|
||||
groupTextTpl: '{group} ({[values.rs.length]} {[values.rs.length > 1 ? "Repositories" : "Repository"]})'
|
||||
})
|
||||
};
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
@@ -102,6 +186,33 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
}
|
||||
},
|
||||
|
||||
convertToGroup: function(v, data){
|
||||
var name = data.name;
|
||||
var i = name.lastIndexOf('/');
|
||||
if ( i > 0 ){
|
||||
name = name.substring(0, i);
|
||||
} else {
|
||||
name = "zzz__";
|
||||
}
|
||||
return name;
|
||||
},
|
||||
|
||||
renderName: function(v, meta, record, rowIndex, colIndex, store){
|
||||
// TODO check if grouping is enabled
|
||||
var i = v.lastIndexOf('/');
|
||||
if ( i > 0 ){
|
||||
v = v.substring(i+1);
|
||||
}
|
||||
return v;
|
||||
},
|
||||
|
||||
renderGroupName: function(v){
|
||||
if (v == 'zzz__'){
|
||||
v = this.mainGroup;
|
||||
}
|
||||
return v;
|
||||
},
|
||||
|
||||
storeLoad: function(){
|
||||
if (this.searchValue){
|
||||
this.filterStore();
|
||||
|
||||
@@ -43,7 +43,7 @@ Sonia.repository.SettingsFormPanel = Ext.extend(Sonia.repository.FormPanel, {
|
||||
readOnly: update,
|
||||
allowBlank: false,
|
||||
helpText: this.nameHelpText,
|
||||
vtype: 'name'
|
||||
vtype: 'repositoryName'
|
||||
},{
|
||||
fieldLabel: this.typeText,
|
||||
name: 'type',
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
/**
|
||||
* 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.it;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryTestData;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import static sonia.scm.it.IntegrationTestUtil.*;
|
||||
import static sonia.scm.it.RepositoryITUtil.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import com.sun.jersey.api.client.ClientResponse;
|
||||
import com.sun.jersey.api.client.WebResource;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class CreateRepositoriesITCase extends AbstractAdminITCaseBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param repositoryType
|
||||
*/
|
||||
public CreateRepositoriesITCase(String repositoryType)
|
||||
{
|
||||
System.out.append("==> CreateRepositoriesITCase - ").println(
|
||||
repositoryType);
|
||||
this.repositoryType = repositoryType;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Parameters
|
||||
public static Collection<String[]> createParameters()
|
||||
{
|
||||
Collection<String[]> params = new ArrayList<String[]>();
|
||||
|
||||
params.add(new String[] { "git" });
|
||||
params.add(new String[] { "git" });
|
||||
|
||||
if (IOUtil.search("hg") != null)
|
||||
{
|
||||
params.add(new String[] { "git" });
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@After
|
||||
public void cleanup() throws IOException
|
||||
{
|
||||
deleteRepository(client, repository.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testCreate()
|
||||
{
|
||||
repository = RepositoryTestData.createHeartOfGold(repositoryType);
|
||||
repository = createRepository(client, repository);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testCreateAllreadyExists()
|
||||
{
|
||||
repository = RepositoryTestData.create42Puzzle(repositoryType);
|
||||
repository = createRepository(client, repository);
|
||||
|
||||
WebResource wr = createResource(client, "repositories");
|
||||
ClientResponse response =
|
||||
wr.post(ClientResponse.class,
|
||||
RepositoryTestData.create42Puzzle(repositoryType));
|
||||
|
||||
assertNotNull(response);
|
||||
assertEquals(500, response.getStatus());
|
||||
response.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testCreateAllreadyExistsWithStructure()
|
||||
{
|
||||
repository = RepositoryTestData.create42Puzzle(repositoryType);
|
||||
repository = createRepository(client, repository);
|
||||
|
||||
Repository r = RepositoryTestData.create42Puzzle(repositoryType);
|
||||
|
||||
r.setName(r.getName() + "/" + r.getName());
|
||||
|
||||
WebResource wr = createResource(client, "repositories");
|
||||
ClientResponse response = wr.post(ClientResponse.class, r);
|
||||
|
||||
assertNotNull(response);
|
||||
System.out.println( response.getStatus() );
|
||||
assertEquals(500, response.getStatus());
|
||||
response.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testCreateWithStructure()
|
||||
{
|
||||
repository = RepositoryTestData.createHeartOfGold(repositoryType);
|
||||
repository.setName("test/".concat(repository.getName()));
|
||||
repository = createRepository(client, repository);
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Repository repository;
|
||||
|
||||
/** Field description */
|
||||
private String repositoryType;
|
||||
}
|
||||
196
scm-webapp/src/test/java/sonia/scm/it/GetRepositoriesITCase.java
Normal file
196
scm-webapp/src/test/java/sonia/scm/it/GetRepositoriesITCase.java
Normal file
@@ -0,0 +1,196 @@
|
||||
/**
|
||||
* 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.it;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryTestData;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import static sonia.scm.it.IntegrationTestUtil.*;
|
||||
import static sonia.scm.it.RepositoryITUtil.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import com.sun.jersey.api.client.ClientResponse;
|
||||
import com.sun.jersey.api.client.WebResource;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class GetRepositoriesITCase extends AbstractAdminITCaseBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param repositoryType
|
||||
*/
|
||||
public GetRepositoriesITCase(String repositoryType)
|
||||
{
|
||||
this.repositoryType = repositoryType;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Parameters
|
||||
public static Collection<String[]> createParameters()
|
||||
{
|
||||
Collection<String[]> params = new ArrayList<String[]>();
|
||||
|
||||
params.add(new String[] { "git" });
|
||||
params.add(new String[] { "svn" });
|
||||
|
||||
if (IOUtil.search("hg") != null)
|
||||
{
|
||||
params.add(new String[] { "hg" });
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@After
|
||||
public void cleanup() throws IOException
|
||||
{
|
||||
deleteRepository(client, repository.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetById()
|
||||
{
|
||||
repository = RepositoryTestData.createHeartOfGold(repositoryType);
|
||||
repository = createRepository(client, repository);
|
||||
|
||||
String id = repository.getId();
|
||||
|
||||
assertNotNull(id);
|
||||
|
||||
Repository r = getRepositoryById(client, id);
|
||||
|
||||
assertEquals(id, r.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetByTypeAndName()
|
||||
{
|
||||
repository = RepositoryTestData.create42Puzzle(repositoryType);
|
||||
testGetByTypeAndName(repository);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetByTypeAndNameWithDirectoryStructure()
|
||||
{
|
||||
repository =
|
||||
RepositoryTestData.createRestaurantAtTheEndOfTheUniverse(repositoryType);
|
||||
repository.setName("test/".concat(repository.getName()));
|
||||
testGetByTypeAndName(repository);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
*/
|
||||
private void testGetByTypeAndName(Repository repo)
|
||||
{
|
||||
repository = createRepository(client, repo);
|
||||
|
||||
String name = repository.getName();
|
||||
WebResource wr = createResource(
|
||||
client,
|
||||
"repositories/".concat(repositoryType).concat(
|
||||
"/").concat(name));
|
||||
ClientResponse response = wr.get(ClientResponse.class);
|
||||
|
||||
assertNotNull(response);
|
||||
|
||||
Repository r = response.getEntity(Repository.class);
|
||||
|
||||
response.close();
|
||||
assertNotNull(r);
|
||||
assertEquals(repository.getId(), r.getId());
|
||||
assertEquals(repository.getName(), r.getName());
|
||||
assertEquals(repository.getType(), r.getType());
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Repository repository;
|
||||
|
||||
/** Field description */
|
||||
private String repositoryType;
|
||||
}
|
||||
@@ -50,6 +50,7 @@ import sonia.scm.repository.client.RepositoryClientFactory;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserTestData;
|
||||
import sonia.scm.util.IOUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@@ -220,36 +221,7 @@ public class RepositoryITCaseBase
|
||||
|
||||
for (Type t : state.getRepositoryTypes())
|
||||
{
|
||||
if (t.getName().equals("git"))
|
||||
{
|
||||
Repository gitRepository = createTestRepository("git", owner, write,
|
||||
read);
|
||||
|
||||
params.add(new Object[]
|
||||
{
|
||||
gitRepository, owner, write, read, noperm, "secret"
|
||||
});
|
||||
}
|
||||
else if (t.getName().equals("svn"))
|
||||
{
|
||||
Repository svnRepository = createTestRepository("svn", owner, write,
|
||||
read);
|
||||
|
||||
params.add(new Object[]
|
||||
{
|
||||
svnRepository, owner, write, read, noperm, "secret"
|
||||
});
|
||||
}
|
||||
else if (t.getName().equals("hg"))
|
||||
{
|
||||
Repository hgRepository = createTestRepository("hg", owner, write,
|
||||
read);
|
||||
|
||||
params.add(new Object[]
|
||||
{
|
||||
hgRepository, owner, write, read, noperm, "secret"
|
||||
});
|
||||
}
|
||||
appendTestParemeter(params, t.getName(), owner, write, read, noperm);
|
||||
}
|
||||
|
||||
return params;
|
||||
@@ -259,6 +231,40 @@ public class RepositoryITCaseBase
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param params
|
||||
* @param type
|
||||
* @param owner
|
||||
* @param write
|
||||
* @param read
|
||||
* @param noperm
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryClientException
|
||||
*/
|
||||
private static void appendTestParemeter(Collection<Object[]> params,
|
||||
String type, User owner, User write, User read, User noperm)
|
||||
throws RepositoryClientException, IOException
|
||||
{
|
||||
Repository repository = createTestRepository(null, type, owner, write,
|
||||
read);
|
||||
|
||||
params.add(new Object[]
|
||||
{
|
||||
repository, owner, write, read, noperm, "secret"
|
||||
});
|
||||
repository = createTestRepository("test", type, owner, write, read);
|
||||
params.add(new Object[]
|
||||
{
|
||||
repository, owner, write, read, noperm, "secret"
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param prefix
|
||||
* @param type
|
||||
* @param owner
|
||||
* @param write
|
||||
@@ -269,13 +275,18 @@ public class RepositoryITCaseBase
|
||||
* @throws IOException
|
||||
* @throws RepositoryClientException
|
||||
*/
|
||||
private static Repository createTestRepository(String type, User owner,
|
||||
User write, User read)
|
||||
private static Repository createTestRepository(String prefix, String type,
|
||||
User owner, User write, User read)
|
||||
throws RepositoryClientException, IOException
|
||||
{
|
||||
Client client = createAdminClient();
|
||||
Repository repository = RepositoryTestData.createHeartOfGold(type);
|
||||
|
||||
if (Util.isNotEmpty(prefix))
|
||||
{
|
||||
repository.setName(prefix.concat("/").concat(repository.getName()));
|
||||
}
|
||||
|
||||
//J-
|
||||
repository.setPermissions(Arrays.asList(
|
||||
new Permission(owner.getName(), PermissionType.OWNER),
|
||||
|
||||
@@ -37,16 +37,22 @@ package sonia.scm.repository;
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import sonia.scm.Manager;
|
||||
import org.junit.Test;
|
||||
|
||||
import sonia.scm.Type;
|
||||
import sonia.scm.repository.xml.XmlRepositoryManager;
|
||||
import sonia.scm.store.JAXBStoreFactory;
|
||||
import sonia.scm.store.StoreFactory;
|
||||
import sonia.scm.util.MockUtil;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -57,6 +63,36 @@ import java.util.Set;
|
||||
public class XmlRepositoryManagerTest extends RepositoryManagerTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Test
|
||||
public void getRepositoryFromRequestUriTest()
|
||||
throws RepositoryException, IOException
|
||||
{
|
||||
RepositoryManager m = createManager();
|
||||
|
||||
m.init(contextProvider);
|
||||
createRepository(m, new Repository("1", "hg", "scm"));
|
||||
createRepository(m, new Repository("2", "hg", "scm-test"));
|
||||
createRepository(m, new Repository("3", "git", "project1/test-1"));
|
||||
createRepository(m, new Repository("4", "git", "project1/test-2"));
|
||||
assertEquals("scm", m.getFromUri("hg/scm").getName());
|
||||
assertEquals("scm-test", m.getFromUri("hg/scm-test").getName());
|
||||
assertEquals("scm-test", m.getFromUri("/hg/scm-test").getName());
|
||||
assertEquals("project1/test-1",
|
||||
m.getFromUri("/git/project1/test-1").getName());
|
||||
assertEquals("project1/test-1",
|
||||
m.getFromUri("/git/project1/test-1/ka/some/path").getName());
|
||||
assertNull(m.getFromUri("/git/project1/test-3/ka/some/path"));
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -64,13 +100,29 @@ public class XmlRepositoryManagerTest extends RepositoryManagerTestBase
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected Manager<Repository, RepositoryException> createManager()
|
||||
protected XmlRepositoryManager createManager()
|
||||
{
|
||||
Set<RepositoryHandler> handlerSet = new HashSet<RepositoryHandler>();
|
||||
StoreFactory factory = new JAXBStoreFactory();
|
||||
|
||||
factory.init(contextProvider);
|
||||
handlerSet.add(new DummyRepositoryHandler(factory));
|
||||
handlerSet.add(new DummyRepositoryHandler(factory)
|
||||
{
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return new Type("hg", "Mercurial");
|
||||
}
|
||||
});
|
||||
handlerSet.add(new DummyRepositoryHandler(factory)
|
||||
{
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return new Type("git", "Git");
|
||||
}
|
||||
});
|
||||
|
||||
Provider<Set<RepositoryListener>> listenerProvider = mock(Provider.class);
|
||||
|
||||
@@ -85,4 +137,20 @@ public class XmlRepositoryManagerTest extends RepositoryManagerTestBase
|
||||
factory, handlerSet, listenerProvider,
|
||||
hookProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param m
|
||||
* @param repository
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
private void createRepository(RepositoryManager m, Repository repository)
|
||||
throws RepositoryException, IOException
|
||||
{
|
||||
m.create(repository);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user