Adjust to repository storage with id

This commit is contained in:
René Pfeuffer
2018-07-10 15:31:18 +02:00
parent 43ca72255e
commit dc8ecd5689
40 changed files with 619 additions and 1120 deletions

View File

@@ -36,19 +36,16 @@ package sonia.scm.repository;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Throwables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.ImportResult.Builder;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
import java.util.List;
//~--- JDK imports ------------------------------------------------------------
/**
* Abstract base class for directory based {@link ImportHandler} and
* {@link AdvancedImportHandler}.
@@ -164,23 +161,24 @@ public abstract class AbstactImportHandler implements AdvancedImportHandler
logger.trace("search for repositories to import");
try
{
List<String> repositoryNames =
RepositoryUtil.getRepositoryNames(getRepositoryHandler(),
getDirectoryNames());
for (String repositoryName : repositoryNames)
{
importRepository(manager, builder, throwExceptions, repositoryName);
}
}
catch (IOException ex)
{
handleException(ex, throwExceptions);
}
// TODO #8783
// try
// {
//
// List<String> repositoryNames =
// RepositoryUtil.getRepositoryNames(getRepositoryHandler(),
// getDirectoryNames());
//
// for (String repositoryName : repositoryNames)
// {
// importRepository(manager, builder, throwExceptions, repositoryName);
// }
//
// }
// catch (IOException ex)
// {
// handleException(ex, throwExceptions);
// }
return builder.build();
}
@@ -214,46 +212,48 @@ public abstract class AbstactImportHandler implements AdvancedImportHandler
* @param manager
* @param builder
* @param throwExceptions
* @param repositoryName
* @param directoryName
*
* @throws IOException
* @throws RepositoryException
*/
private void importRepository(RepositoryManager manager, Builder builder,
boolean throwExceptions, String repositoryName)
boolean throwExceptions, String directoryName)
throws IOException, RepositoryException
{
logger.trace("check repository {} for import", repositoryName);
logger.trace("check repository {} for import", directoryName);
Repository repository = manager.get(getTypeName(), repositoryName);
if (repository == null)
{
try
{
importRepository(manager, repositoryName);
builder.addImportedDirectory(repositoryName);
}
catch (IOException ex)
{
builder.addFailedDirectory(repositoryName);
handleException(ex, throwExceptions);
}
catch (IllegalStateException ex)
{
builder.addFailedDirectory(repositoryName);
handleException(ex, throwExceptions);
}
catch (RepositoryException ex)
{
builder.addFailedDirectory(repositoryName);
handleException(ex, throwExceptions);
}
}
else if (logger.isDebugEnabled())
{
logger.debug("repository {} is allready managed", repositoryName);
}
// TODO #8783
//
// Repository repository = manager.get(namespaceAndName);
//
// if (repository == null)
// {
// try
// {
// importRepository(manager, repositoryName);
// builder.addImportedDirectory(repositoryName);
// }
// catch (IOException ex)
// {
// builder.addFailedDirectory(repositoryName);
// handleException(ex, throwExceptions);
// }
// catch (IllegalStateException ex)
// {
// builder.addFailedDirectory(repositoryName);
// handleException(ex, throwExceptions);
// }
// catch (RepositoryException ex)
// {
// builder.addFailedDirectory(repositoryName);
// handleException(ex, throwExceptions);
// }
// }
// else if (logger.isDebugEnabled())
// {
// logger.debug("repository {} is already managed", repositoryName);
// }
}
/**

View File

@@ -0,0 +1,50 @@
package sonia.scm.repository;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import java.util.Objects;
public class NamespaceAndName {
private final String namespace;
private final String name;
public NamespaceAndName(String namespace, String name) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(namespace), "a non empty namespace is required");
Preconditions.checkArgument(!Strings.isNullOrEmpty(name), "a non empty name is required");
this.namespace = namespace;
this.name = name;
}
public String getNamespace() {
return namespace;
}
public String getName() {
return name;
}
@Override
public String toString() {
return getNamespace() + "/" + getName();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
NamespaceAndName that = (NamespaceAndName) o;
return Objects.equals(namespace, that.namespace) &&
Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(namespace, name);
}
}

View File

@@ -43,7 +43,12 @@ import sonia.scm.util.HttpUtil;
import sonia.scm.util.Util;
import sonia.scm.util.ValidationUtil;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -95,9 +100,10 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per
* @param type type of the {@link Repository}
* @param name name of the {@link Repository}
*/
public Repository(String id, String type, String name) {
public Repository(String id, String type, String namespace, String name) {
this.id = id;
this.type = type;
this.namespace = namespace;
this.name = name;
}
@@ -189,6 +195,11 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per
public String getNamespace() { return namespace; }
@XmlTransient
public NamespaceAndName getNamespaceAndName() {
return new NamespaceAndName(getNamespace(), getName());
}
public List<Permission> getPermissions() {
if (permissions == null) {
permissions = Lists.newArrayList();
@@ -347,7 +358,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per
public String createUrl(String baseUrl) {
String url = HttpUtil.append(baseUrl, type);
return HttpUtil.append(url, name);
return HttpUtil.concatenate(url, namespace, name);
}
/**

View File

@@ -49,27 +49,22 @@ public interface RepositoryDAO extends GenericDAO<Repository>
/**
* Returns true if a repository with specified
* type and name exists in the backend.
* namespace and name exists in the backend.
*
*
* @param type type of the repository
* @param name name of the repository
* @param namespaceAndName namespace and name of the repository
*
* @return true if the repository exists
*/
public boolean contains(String type, String name);
boolean contains(NamespaceAndName namespaceAndName);
//~--- get methods ----------------------------------------------------------
/**
* Returns the repository with the specified type and name or null
* Returns the repository with the specified namespace and name or null
* if no such repository exists in the backend.
*
*
* @param type
* @param name
*
* @return repository with the specified type and name or null
* @return repository with the specified namespace and name or null
*/
public Repository get(String type, String name);
Repository get(NamespaceAndName namespaceAndName);
}

View File

@@ -38,13 +38,11 @@ package sonia.scm.repository;
import sonia.scm.Type;
import sonia.scm.TypeManager;
//~--- JDK imports ------------------------------------------------------------
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Collection;
import javax.servlet.http.HttpServletRequest;
//~--- JDK imports ------------------------------------------------------------
/**
* The central class for managing {@link Repository} objects.
@@ -83,18 +81,17 @@ public interface RepositoryManager
//~--- get methods ----------------------------------------------------------
/**
* Returns a {@link Repository} by its type and name or
* Returns a {@link Repository} by its namespace and name or
* null if the {@link Repository} could not be found.
*
*
* @param type type of the {@link Repository}
* @param name name of the {@link Repository}
* @param namespaceAndName namespace and name of the {@link Repository}
*
*
* @return {@link Repository} by its type and name or null
* @return {@link Repository} by its namespace and name or null
* if the {@link Repository} could not be found
*/
public Repository get(String type, String name);
public Repository get(NamespaceAndName namespaceAndName);
/**
* Returns all configured repository types.
@@ -115,18 +112,6 @@ public interface RepositoryManager
*/
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.
*

View File

@@ -38,13 +38,11 @@ package sonia.scm.repository;
import sonia.scm.ManagerDecorator;
import sonia.scm.Type;
//~--- JDK imports ------------------------------------------------------------
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Collection;
import javax.servlet.http.HttpServletRequest;
//~--- JDK imports ------------------------------------------------------------
/**
* Decorator for {@link RepositoryManager}.
@@ -92,19 +90,10 @@ public class RepositoryManagerDecorator
//~--- get methods ----------------------------------------------------------
/**
* {@inheritDoc}
*
*
* @param type
* @param name
*
* @return
*/
@Override
public Repository get(String type, String name)
public Repository get(NamespaceAndName namespaceAndName)
{
return decorated.get(type, name);
return decorated.get(namespaceAndName);
}
/**
@@ -146,21 +135,6 @@ public class RepositoryManagerDecorator
return decorated.getFromRequest(request);
}
/**
* {@inheritDoc}
*
*
* @param type
* @param uri
*
* @return
*/
@Override
public Repository getFromTypeAndUri(String type, String uri)
{
return decorated.getFromTypeAndUri(type, uri);
}
/**
* {@inheritDoc}
*

View File

@@ -35,21 +35,20 @@ package sonia.scm.repository;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.io.DirectoryFileFilter;
import sonia.scm.util.IOUtil;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
//~--- JDK imports ------------------------------------------------------------
/**
*
@@ -82,204 +81,43 @@ public final class RepositoryUtil
*
* @return
*/
public static List<File> searchRepositoryDirectories(File directory,
String... names)
{
List<File> repositories = new ArrayList<File>();
public static List<File> searchRepositoryDirectories(File directory, String... names) {
List<File> repositories = new ArrayList<>();
searchRepositoryDirectories(repositories, directory, Arrays.asList(names));
return repositories;
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
*
* @param handler
* @param directoryPath
* @return
*
* @throws IOException
*/
public static String getRepositoryName(AbstractRepositoryHandler handler,
String directoryPath)
throws IOException
{
return getRepositoryName(handler.getConfig().getRepositoryDirectory(),
new File(directoryPath));
public static String getRepositoryId(AbstractRepositoryHandler handler, String directoryPath) throws IOException {
return getRepositoryId(handler.getConfig().getRepositoryDirectory(), new File(directoryPath));
}
/**
* Method description
*
*
*
* @param config
* @param directoryPath
* @return
*
* @throws IOException
*/
public static String getRepositoryName(SimpleRepositoryConfig config,
String directoryPath)
throws IOException
{
return getRepositoryName(config.getRepositoryDirectory(),
new File(directoryPath));
public static String getRepositoryId(AbstractRepositoryHandler handler, File directory) throws IOException {
return getRepositoryId(handler.getConfig(), directory);
}
/**
* Method description
*
*
*
* @param handler
* @param directory
* @return
*
* @throws IOException
*/
public static String getRepositoryName(AbstractRepositoryHandler handler,
File directory)
throws IOException
{
return getRepositoryName(handler.getConfig().getRepositoryDirectory(),
directory);
public static String getRepositoryId(SimpleRepositoryConfig config, File directory) throws IOException {
return getRepositoryId(config.getRepositoryDirectory(), directory);
}
/**
* Method description
*
*
*
* @param config
* @param directory
* @return
*
* @throws IOException
*/
public static String getRepositoryName(SimpleRepositoryConfig config,
File directory)
throws IOException
{
return getRepositoryName(config.getRepositoryDirectory(), directory);
}
/**
* Method description
*
*
*
* @param baseDirectory
* @param directory
* @return
*
* @throws IOException
*/
public static String getRepositoryName(File baseDirectory, File directory)
throws IOException
{
String name = null;
public static String getRepositoryId(File baseDirectory, File directory) throws IOException {
String path = directory.getCanonicalPath();
int directoryLength = baseDirectory.getCanonicalPath().length();
if (directoryLength < path.length())
{
name = IOUtil.trimSeperatorChars(path.substring(directoryLength));
// replace windows path seperator
name = name.replaceAll("\\\\", "/");
String id = IOUtil.trimSeperatorChars(path.substring(directoryLength));
Preconditions.checkState(!id.contains("\\") && !id.contains("/"),
"got illegal repository directory with separators in id: " + path);
return id;
}
else if (logger.isWarnEnabled())
else
{
logger.warn("path is shorter as the main repository path");
throw new IllegalStateException("path is shorter as the main repository path");
}
return name;
}
/**
* Method description
*
*
* @param handler
* @param directoryNames
*
* @return
*
* @throws IOException
*/
public static List<String> getRepositoryNames(
AbstractRepositoryHandler handler, String... directoryNames)
throws IOException
{
return getRepositoryNames(handler.getConfig(), directoryNames);
}
/**
* Method description
*
*
* @param config
* @param directoryNames
*
* @return
*
* @throws IOException
*/
public static List<String> getRepositoryNames(SimpleRepositoryConfig config,
String... directoryNames)
throws IOException
{
return getRepositoryNames(config.getRepositoryDirectory(), directoryNames);
}
/**
* Method description
*
*
* @param baseDirectory
* @param directoryNames
*
* @return
*
* @throws IOException
*/
public static List<String> getRepositoryNames(File baseDirectory,
String... directoryNames)
throws IOException
{
List<String> repositories = new ArrayList<String>();
List<File> repositoryFiles = searchRepositoryDirectories(baseDirectory,
directoryNames);
for (File file : repositoryFiles)
{
String name = getRepositoryName(baseDirectory, file);
if (name != null)
{
repositories.add(name);
}
}
return repositories;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param repositories
* @param directory
* @param names
*/
private static void searchRepositoryDirectories(List<File> repositories,
File directory, List<String> names)
{

View File

@@ -37,20 +37,20 @@ package sonia.scm.repository.api;
import com.github.legman.ReferenceType;
import com.github.legman.Subscribe;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.HandlerEventType;
import sonia.scm.cache.Cache;
import sonia.scm.cache.CacheManager;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.event.ScmEventBus;
import sonia.scm.repository.ClearRepositoryCacheEvent;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.PostReceiveRepositoryHookEvent;
import sonia.scm.repository.PreProcessorUtil;
import sonia.scm.repository.Repository;
@@ -63,11 +63,9 @@ import sonia.scm.repository.spi.RepositoryServiceProvider;
import sonia.scm.repository.spi.RepositoryServiceResolver;
import sonia.scm.security.ScmSecurityException;
//~--- JDK imports ------------------------------------------------------------
import java.util.Set;
import sonia.scm.event.ScmEventBus;
import sonia.scm.repository.ClearRepositoryCacheEvent;
//~--- JDK imports ------------------------------------------------------------
/**
* The {@link RepositoryServiceFactory} is the entrypoint of the repository api.
@@ -190,8 +188,7 @@ public final class RepositoryServiceFactory
* Creates a new RepositoryService for the given repository.
*
*
* @param type type of the repository
* @param name name of the repository
* @param namespaceAndName namespace and name of the repository
*
* @return a implementation of RepositoryService
* for the given type of repository
@@ -204,24 +201,19 @@ public final class RepositoryServiceFactory
* @throws ScmSecurityException if current user has not read permissions
* for that repository
*/
public RepositoryService create(String type, String name)
public RepositoryService create(NamespaceAndName namespaceAndName)
throws RepositoryNotFoundException
{
Preconditions.checkArgument(!Strings.isNullOrEmpty(type),
"a non empty type is required");
Preconditions.checkArgument(!Strings.isNullOrEmpty(name),
"a non empty name is required");
Preconditions.checkArgument(namespaceAndName != null,
"a non empty namespace and name is required");
Repository repository = repositoryManager.get(type, name);
Repository repository = repositoryManager.get(namespaceAndName);
if (repository == null)
{
StringBuilder msg =
new StringBuilder("could not find a repository with type ");
String msg = "could not find a repository with namespace/name " + namespaceAndName;
msg.append(type).append(" and name ").append(name);
throw new RepositoryNotFoundException(msg.toString());
throw new RepositoryNotFoundException(msg);
}
return create(repository);

View File

@@ -35,7 +35,7 @@ package sonia.scm.repository.spi;
import com.google.inject.Inject;
import com.google.inject.Provider;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.RepositoryHookEvent;
@@ -72,50 +72,15 @@ public final class HookEventFacade
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param id
*
* @return
*
* @throws RepositoryException
*/
public HookEventHandler handle(String id) throws RepositoryException
{
public HookEventHandler handle(String id) throws RepositoryException {
return handle(repositoryManagerProvider.get().get(id));
}
/**
* Method description
*
*
* @param type
* @param repositoryName
*
* @return
*
* @throws RepositoryException
*/
public HookEventHandler handle(String type, String repositoryName)
throws RepositoryException
{
return handle(repositoryManagerProvider.get().get(type, repositoryName));
public HookEventHandler handle(NamespaceAndName namespaceAndName) throws RepositoryException {
return handle(repositoryManagerProvider.get().get(namespaceAndName));
}
/**
* Method description
*
*
* @param repository
*
* @return
*
* @throws RepositoryException
*/
public HookEventHandler handle(Repository repository)
throws RepositoryException
public HookEventHandler handle(Repository repository) throws RepositoryException
{
if (repository == null)
{

View File

@@ -39,27 +39,23 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CharMatcher;
import com.google.common.base.Objects;
import com.google.common.base.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.config.ScmConfiguration;
//~--- JDK imports ------------------------------------------------------------
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//~--- JDK imports ------------------------------------------------------------
/**
* Util method for the http protocol.
@@ -252,13 +248,15 @@ public final class HttpUtil
//~--- methods --------------------------------------------------------------
public static String concatenate(String... pathElements) {
return Arrays.stream(pathElements).reduce(HttpUtil::append).orElse("");
}
/**
* Appends the suffix to given uri.
*
*
* @param uri uri
* @param uri uri
* @param suffix suffix
*
* @return
* @since 1.9
*/

View File

@@ -1,133 +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.web.filter;
//~--- non-JDK imports --------------------------------------------------------
import sonia.scm.config.ScmConfiguration;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryManager;
//~--- JDK imports ------------------------------------------------------------
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
/**
*
* @author Sebastian Sdorra
*/
public abstract class RegexPermissionFilter extends PermissionFilter
{
/** Field description */
public static final Pattern PATTERN_REPOSITORYNAME =
Pattern.compile("/[^/]+/([^/]+)(?:/.*)?");
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
*
* @param configuration
* @param repositoryManager
*/
public RegexPermissionFilter(ScmConfiguration configuration,
RepositoryManager repositoryManager)
{
super(configuration);
this.repositoryManager = repositoryManager;
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
protected abstract String getType();
/**
* Method description
*
*
* @param request
*
* @return
*/
@Override
protected 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 name
*
* @return
*/
protected Repository getRepository(String name)
{
return repositoryManager.get(getType(), name);
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private RepositoryManager repositoryManager;
}