From d3a2fc8219e8a6217a39e1b52c80fc005ae0ad84 Mon Sep 17 00:00:00 2001 From: Philipp Czora Date: Wed, 4 Jul 2018 15:46:08 +0200 Subject: [PATCH 01/21] Implemented namespace feature --- .../sonia/scm/config/ScmConfiguration.java | 600 ++++++------------ .../repository/NamespaceStrategyProvider.java | 32 + .../java/sonia/scm/repository/Repository.java | 31 +- .../main/java/sonia/scm/ScmServletModule.java | 45 +- .../repository/DefaultNamespaceStrategy.java | 11 +- .../repository/DefaultRepositoryManager.java | 209 +----- .../DefaultRepositoryManagerPerfTest.java | 22 +- .../DefaultRepositoryManagerTest.java | 42 +- 8 files changed, 262 insertions(+), 730 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/repository/NamespaceStrategyProvider.java diff --git a/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java b/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java index ac22c1403e..c7c3517099 100644 --- a/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java +++ b/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java @@ -1,19 +1,19 @@ /** * 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. + * 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. + * 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. - * + * 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 @@ -24,39 +24,32 @@ * 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.config; -//~--- non-JDK imports -------------------------------------------------------- import com.google.common.collect.Sets; import com.google.inject.Singleton; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import sonia.scm.event.ScmEventBus; import sonia.scm.util.HttpUtil; import sonia.scm.xml.XmlSetStringAdapter; -//~--- JDK imports ------------------------------------------------------------ - -import java.io.File; - -import java.util.Set; -import java.util.concurrent.TimeUnit; - import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import java.io.File; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +//~--- JDK imports ------------------------------------------------------------ /** * The main configuration object for SCM-Manager. @@ -67,38 +60,137 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @Singleton @XmlRootElement(name = "scm-config") @XmlAccessorType(XmlAccessType.FIELD) -public class ScmConfiguration -{ +public class ScmConfiguration { - /** Default JavaScript date format */ + /** + * Default JavaScript date format + */ public static final String DEFAULT_DATEFORMAT = "YYYY-MM-DD HH:mm:ss"; - /** Default plugin url */ + /** + * Default plugin url + */ public static final String DEFAULT_PLUGINURL = "http://plugins.scm-manager.org/scm-plugin-backend/api/{version}/plugins?os={os}&arch={arch}&snapshot=false"; - /** Default plugin url from version 1.0 */ + /** + * Default plugin url from version 1.0 + */ public static final String OLD_PLUGINURL = "http://plugins.scm-manager.org/plugins.xml.gz"; - /** Path to the configuration file */ + /** + * Path to the configuration file + */ public static final String PATH = "config".concat(File.separator).concat("config.xml"); - /** the logger for ScmConfiguration */ + /** + * the logger for ScmConfiguration + */ private static final Logger logger = LoggerFactory.getLogger(ScmConfiguration.class); - //~--- methods -------------------------------------------------------------- + + @XmlElement(name = "admin-groups") + @XmlJavaTypeAdapter(XmlSetStringAdapter.class) + private Set adminGroups; + + + @XmlElement(name = "admin-users") + @XmlJavaTypeAdapter(XmlSetStringAdapter.class) + private Set adminUsers; + + + @XmlElement(name = "base-url") + private String baseUrl; + + + @XmlElement(name = "force-base-url") + private boolean forceBaseUrl; + + /** + * Maximum allowed login attempts. + * + * @since 1.34 + */ + @XmlElement(name = "login-attempt-limit") + private int loginAttemptLimit = -1; + + /** + * glob patterns for urls which are excluded from proxy + */ + @XmlElement(name = "proxy-excludes") + @XmlJavaTypeAdapter(XmlSetStringAdapter.class) + private Set proxyExcludes; + + + private String proxyPassword; + + + private int proxyPort = 8080; + + + private String proxyServer = "proxy.mydomain.com"; + + + private String proxyUser; + + /** + * Skip failed authenticators. + * + * @since 1.36 + */ + @XmlElement(name = "skip-failed-authenticators") + private boolean skipFailedAuthenticators = false; + + + @XmlElement(name = "plugin-url") + private String pluginUrl = DEFAULT_PLUGINURL; + + /** + * Login attempt timeout. + * + * @since 1.34 + */ + @XmlElement(name = "login-attempt-limit-timeout") + private long loginAttemptLimitTimeout = TimeUnit.MINUTES.toSeconds(5l); + + + private boolean enableProxy = false; + + /** + * Authentication realm for basic authentication. + */ + private String realmDescription = HttpUtil.AUTHENTICATION_REALM; + private boolean enableRepositoryArchive = false; + private boolean disableGroupingGrid = false; + /** + * JavaScript date format from moment.js + * + * @see http://momentjs.com/docs/#/parsing/ + */ + private String dateFormat = DEFAULT_DATEFORMAT; + private boolean anonymousAccessEnabled = false; + + /** + * Enables xsrf cookie protection. + * + * @since 1.47 + */ + @XmlElement(name = "xsrf-protection") + private boolean enabledXsrfProtection = true; + + @XmlElement(name = "default-namespace-strategy") + private String defaultNamespaceStrategy = "sonia.scm.repository.DefaultNamespaceStrategy"; + /** * Calls the {@link sonia.scm.ConfigChangedListener#configChanged(Object)} * method of all registered listeners. */ - public void fireChangeEvent() - { - if (logger.isDebugEnabled()) - { + public void fireChangeEvent() { + if (logger.isDebugEnabled()) { logger.debug("fire config changed event"); } @@ -109,12 +201,9 @@ public class ScmConfiguration /** * Load all properties from another {@link ScmConfiguration} object. * - * - * * @param other */ - public void load(ScmConfiguration other) - { + public void load(ScmConfiguration other) { this.realmDescription = other.realmDescription; this.dateFormat = other.dateFormat; this.pluginUrl = other.pluginUrl; @@ -135,29 +224,14 @@ public class ScmConfiguration this.loginAttemptLimit = other.loginAttemptLimit; this.loginAttemptLimitTimeout = other.loginAttemptLimitTimeout; this.enabledXsrfProtection = other.enabledXsrfProtection; + this.defaultNamespaceStrategy = other.defaultNamespaceStrategy; } - //~--- get methods ---------------------------------------------------------- - - /** - * Returns a set of admin group names. - * - * - * @return set of admin group names - */ - public Set getAdminGroups() - { + public Set getAdminGroups() { return adminGroups; } - /** - * Returns a set of admin user names. - * - * - * @return set of admin user names - */ - public Set getAdminUsers() - { + public Set getAdminUsers() { return adminUsers; } @@ -165,11 +239,10 @@ public class ScmConfiguration * Returns the complete base url of the scm-manager including the context path. * For example http://localhost:8080/scm * - * @since 1.5 * @return complete base url of the scm-manager + * @since 1.5 */ - public String getBaseUrl() - { + public String getBaseUrl() { return baseUrl; } @@ -177,23 +250,14 @@ public class ScmConfiguration * Returns the date format for the user interface. This format is a * JavaScript date format, from the library moment.js. * - * @see http://momentjs.com/docs/#/parsing/ * @return moment.js date format + * @see http://momentjs.com/docs/#/parsing/ */ - public String getDateFormat() - { + public String getDateFormat() { return dateFormat; } - /** - * Returns maximum allowed login attempts. - * - * @return maximum allowed login attempts - * - * @since 1.34 - */ - public int getLoginAttemptLimit() - { + public int getLoginAttemptLimit() { return loginAttemptLimit; } @@ -202,11 +266,9 @@ public class ScmConfiguration * because of too many failed login attempts. * * @return login attempt timeout in seconds - * * @since 1.34 */ - public long getLoginAttemptLimitTimeout() - { + public long getLoginAttemptLimitTimeout() { return loginAttemptLimitTimeout; } @@ -222,8 +284,7 @@ public class ScmConfiguration * * @return the complete plugin url. */ - public String getPluginUrl() - { + public String getPluginUrl() { return pluginUrl; } @@ -231,289 +292,141 @@ public class ScmConfiguration * Returns a set of glob patterns for urls which should excluded from * proxy settings. * - * * @return set of glob patterns * @since 1.23 */ - public Set getProxyExcludes() - { - if (proxyExcludes == null) - { + public Set getProxyExcludes() { + if (proxyExcludes == null) { proxyExcludes = Sets.newHashSet(); } return proxyExcludes; } - /** - * Method description - * - * - * @return - * @since 1.7 - */ - public String getProxyPassword() - { + public String getProxyPassword() { return proxyPassword; } - /** - * Returns the proxy port. - * - * - * @return proxy port - */ - public int getProxyPort() - { + public int getProxyPort() { return proxyPort; } /** * Returns the servername or ip of the proxyserver. * - * * @return servername or ip of the proxyserver */ - public String getProxyServer() - { + public String getProxyServer() { return proxyServer; } - /** - * Method description - * - * - * @return - * @since 1.7 - */ - public String getProxyUser() - { + public String getProxyUser() { return proxyUser; } - /** - * Returns the realm description. - * - * - * @return realm description - * @since 1.36 - */ - public String getRealmDescription() - { + public String getRealmDescription() { return realmDescription; } - - /** - * Returns true if the anonymous access to the SCM-Manager is enabled. - * - * - * @return true if the anonymous access to the SCM-Manager is enabled - */ - public boolean isAnonymousAccessEnabled() - { + public boolean isAnonymousAccessEnabled() { return anonymousAccessEnabled; } - /** - * Method description - * - * @since 1.9 - * @return - */ - public boolean isDisableGroupingGrid() - { + public boolean isDisableGroupingGrid() { return disableGroupingGrid; } /** * Returns {@code true} if the cookie xsrf protection is enabled. - * - * @see Issue 793 + * * @return {@code true} if the cookie xsrf protection is enabled - * + * @see Issue 793 * @since 1.47 */ - public boolean isEnabledXsrfProtection() - { + public boolean isEnabledXsrfProtection() { return enabledXsrfProtection; } - /** - * Returns true if proxy is enabled. - * - * - * @return true if proxy is enabled - */ - public boolean isEnableProxy() - { + public boolean isEnableProxy() { return enableProxy; } - /** - * Returns true if the repository archive is enabled. - * - * - * @return true if the repository archive is enabled - * @since 1.14 - */ - public boolean isEnableRepositoryArchive() - { + public boolean isEnableRepositoryArchive() { return enableRepositoryArchive; } - /** - * Returns true if force base url is enabled. - * - * @since 1.5 - * @return true if force base url is enabled - */ - public boolean isForceBaseUrl() - { + public boolean isForceBaseUrl() { return forceBaseUrl; } - /** - * Returns true if the login attempt limit is enabled. - * - * - * @return true if login attempt limit is enabled - * - * @since 1.37 - */ - public boolean isLoginAttemptLimitEnabled() - { + public boolean isLoginAttemptLimitEnabled() { return loginAttemptLimit > 0; } + public String getDefaultNamespaceStrategy() { + return defaultNamespaceStrategy; + } + + /** * Returns true if failed authenticators are skipped. * - * * @return true if failed authenticators are skipped - * * @since 1.36 */ - public boolean isSkipFailedAuthenticators() - { + public boolean isSkipFailedAuthenticators() { return skipFailedAuthenticators; } - //~--- set methods ---------------------------------------------------------- - - /** - * Method description - * - * - * @param adminGroups - */ - public void setAdminGroups(Set adminGroups) - { + public void setAdminGroups(Set adminGroups) { this.adminGroups = adminGroups; } - /** - * Method description - * - * - * @param adminUsers - */ - public void setAdminUsers(Set adminUsers) - { + public void setAdminUsers(Set adminUsers) { this.adminUsers = adminUsers; } - /** - * Method description - * - * - * @param anonymousAccessEnabled - */ - public void setAnonymousAccessEnabled(boolean anonymousAccessEnabled) - { + public void setAnonymousAccessEnabled(boolean anonymousAccessEnabled) { this.anonymousAccessEnabled = anonymousAccessEnabled; } - /** - * Method description - * - * - * @param baseUrl - * @since 1.5 - */ - public void setBaseUrl(String baseUrl) - { + public void setBaseUrl(String baseUrl) { this.baseUrl = baseUrl; } - /** - * Sets the date format for the ui. - * - * - * @param dateFormat date format for ui - */ - public void setDateFormat(String dateFormat) - { + public void setDateFormat(String dateFormat) { this.dateFormat = dateFormat; } - /** - * Method description - * - * @since 1.9 - * - * @param disableGroupingGrid - */ - public void setDisableGroupingGrid(boolean disableGroupingGrid) - { + public void setDisableGroupingGrid(boolean disableGroupingGrid) { this.disableGroupingGrid = disableGroupingGrid; } - /** - * Method description - * - * - * @param enableProxy - */ - public void setEnableProxy(boolean enableProxy) - { + public void setEnableProxy(boolean enableProxy) { this.enableProxy = enableProxy; } /** * Enable or disable the repository archive. Default is disabled. * - * * @param enableRepositoryArchive true to disable the repository archive * @since 1.14 */ - public void setEnableRepositoryArchive(boolean enableRepositoryArchive) - { + public void setEnableRepositoryArchive(boolean enableRepositoryArchive) { this.enableRepositoryArchive = enableRepositoryArchive; } - /** - * Method description - * - * - * @param forceBaseUrl - * @since 1.5 - */ - public void setForceBaseUrl(boolean forceBaseUrl) - { + public void setForceBaseUrl(boolean forceBaseUrl) { this.forceBaseUrl = forceBaseUrl; } /** * Set maximum allowed login attempts. * - * * @param loginAttemptLimit login attempt limit - * * @since 1.34 */ - public void setLoginAttemptLimit(int loginAttemptLimit) - { + public void setLoginAttemptLimit(int loginAttemptLimit) { this.loginAttemptLimit = loginAttemptLimit; } @@ -522,22 +435,13 @@ public class ScmConfiguration * because of too many failed login attempts. * * @param loginAttemptLimitTimeout login attempt timeout in seconds - * * @since 1.34 */ - public void setLoginAttemptLimitTimeout(long loginAttemptLimitTimeout) - { + public void setLoginAttemptLimitTimeout(long loginAttemptLimitTimeout) { this.loginAttemptLimitTimeout = loginAttemptLimitTimeout; } - /** - * Method description - * - * - * @param pluginUrl - */ - public void setPluginUrl(String pluginUrl) - { + public void setPluginUrl(String pluginUrl) { this.pluginUrl = pluginUrl; } @@ -545,194 +449,56 @@ public class ScmConfiguration * Set glob patterns for urls which are should be excluded from proxy * settings. * - * * @param proxyExcludes glob patterns * @since 1.23 */ - public void setProxyExcludes(Set proxyExcludes) - { + public void setProxyExcludes(Set proxyExcludes) { this.proxyExcludes = proxyExcludes; } - /** - * Method description - * - * - * @param proxyPassword - * @since 1.7 - */ - public void setProxyPassword(String proxyPassword) - { + public void setProxyPassword(String proxyPassword) { this.proxyPassword = proxyPassword; } - /** - * Method description - * - * - * @param proxyPort - */ - public void setProxyPort(int proxyPort) - { + public void setProxyPort(int proxyPort) { this.proxyPort = proxyPort; } - /** - * Method description - * - * - * @param proxyServer - */ - public void setProxyServer(String proxyServer) - { + public void setProxyServer(String proxyServer) { this.proxyServer = proxyServer; } - /** - * Method description - * - * - * @param proxyUser - * @since 1.7 - */ - public void setProxyUser(String proxyUser) - { + public void setProxyUser(String proxyUser) { this.proxyUser = proxyUser; } - /** - * Sets the realm description. - * - * - * @param realmDescription - * @since 1.36 - */ - public void setRealmDescription(String realmDescription) - { + public void setRealmDescription(String realmDescription) { this.realmDescription = realmDescription; } /** - * If set to true the authentication chain is not stopped, if an + * If set to true the authentication chain is not stopped, if an * authenticator finds the user but fails to authenticate the user. * * @param skipFailedAuthenticators true to skip failed authenticators - * * @since 1.36 */ - public void setSkipFailedAuthenticators(boolean skipFailedAuthenticators) - { + public void setSkipFailedAuthenticators(boolean skipFailedAuthenticators) { this.skipFailedAuthenticators = skipFailedAuthenticators; } /** * Set {@code true} to enable xsrf cookie protection. - * + * * @param enabledXsrfProtection {@code true} to enable xsrf protection * @see Issue 793 - * * @since 1.47 */ - public void setEnabledXsrfProtection(boolean enabledXsrfProtection) - { + public void setEnabledXsrfProtection(boolean enabledXsrfProtection) { this.enabledXsrfProtection = enabledXsrfProtection; } - //~--- fields --------------------------------------------------------------- - - /** Field description */ - @XmlElement(name = "admin-groups") - @XmlJavaTypeAdapter(XmlSetStringAdapter.class) - private Set adminGroups; - - /** Field description */ - @XmlElement(name = "admin-users") - @XmlJavaTypeAdapter(XmlSetStringAdapter.class) - private Set adminUsers; - - /** Field description */ - @XmlElement(name = "base-url") - private String baseUrl; - - /** Field description */ - @XmlElement(name = "force-base-url") - private boolean forceBaseUrl; - - /** - * Maximum allowed login attempts. - * - * @since 1.34 - */ - @XmlElement(name = "login-attempt-limit") - private int loginAttemptLimit = -1; - - /** glob patterns for urls which are excluded from proxy */ - @XmlElement(name = "proxy-excludes") - @XmlJavaTypeAdapter(XmlSetStringAdapter.class) - private Set proxyExcludes; - - /** Field description */ - private String proxyPassword; - - /** Field description */ - private int proxyPort = 8080; - - /** Field description */ - private String proxyServer = "proxy.mydomain.com"; - - /** Field description */ - private String proxyUser; - - /** - * Skip failed authenticators. - * - * @since 1.36 - */ - @XmlElement(name = "skip-failed-authenticators") - private boolean skipFailedAuthenticators = false; - - /** Field description */ - @XmlElement(name = "plugin-url") - private String pluginUrl = DEFAULT_PLUGINURL; - - /** - * Login attempt timeout. - * - * @since 1.34 - */ - @XmlElement(name = "login-attempt-limit-timeout") - private long loginAttemptLimitTimeout = TimeUnit.MINUTES.toSeconds(5l); - - /** Field description */ - private boolean enableProxy = false; - - /** - * - * Authentication realm for basic authentication. - * - */ - private String realmDescription = HttpUtil.AUTHENTICATION_REALM; - - /** Field description */ - private boolean enableRepositoryArchive = false; - - /** Field description */ - private boolean disableGroupingGrid = false; - - /** - * JavaScript date format from moment.js - * @see http://momentjs.com/docs/#/parsing/ - */ - private String dateFormat = DEFAULT_DATEFORMAT; - - /** Field description */ - private boolean anonymousAccessEnabled = false; - - /** - * Enables xsrf cookie protection. - * - * @since 1.47 - */ - @XmlElement(name = "xsrf-protection") - private boolean enabledXsrfProtection = true; + public void setDefaultNamespaceStrategy(String defaultNamespaceStrategy) { + this.defaultNamespaceStrategy = defaultNamespaceStrategy; + } } diff --git a/scm-core/src/main/java/sonia/scm/repository/NamespaceStrategyProvider.java b/scm-core/src/main/java/sonia/scm/repository/NamespaceStrategyProvider.java new file mode 100644 index 0000000000..49aefe71ac --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/NamespaceStrategyProvider.java @@ -0,0 +1,32 @@ +package sonia.scm.repository; + +import sonia.scm.config.ScmConfiguration; + +import javax.inject.Inject; +import javax.inject.Provider; +import java.util.Set; + +public class NamespaceStrategyProvider implements Provider { + + private final Set strategies; + private final ScmConfiguration scmConfiguration; + + @Inject + public NamespaceStrategyProvider(Set strategies, ScmConfiguration scmConfiguration) { + this.strategies = strategies; + this.scmConfiguration = scmConfiguration; + } + + @Override + public NamespaceStrategy get() { + String namespaceStrategy = scmConfiguration.getDefaultNamespaceStrategy(); + + for (NamespaceStrategy s : this.strategies) { + if (s.getClass().getCanonicalName().equals(namespaceStrategy)) { + return s; + } + } + return null; + } + +} diff --git a/scm-core/src/main/java/sonia/scm/repository/Repository.java b/scm-core/src/main/java/sonia/scm/repository/Repository.java index 63bef4ea6c..df340564f6 100644 --- a/scm-core/src/main/java/sonia/scm/repository/Repository.java +++ b/scm-core/src/main/java/sonia/scm/repository/Repository.java @@ -37,23 +37,17 @@ import com.github.sdorra.ssp.PermissionObject; import com.github.sdorra.ssp.StaticPermissions; import com.google.common.base.Objects; import com.google.common.collect.Lists; - import sonia.scm.BasicPropertiesAware; import sonia.scm.ModelObject; import sonia.scm.util.HttpUtil; import sonia.scm.util.Util; import sonia.scm.util.ValidationUtil; +import javax.xml.bind.annotation.*; import java.util.Arrays; import java.util.Collections; import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElementWrapper; -import javax.xml.bind.annotation.XmlRootElement; - /** * Source code repository. * @@ -178,40 +172,23 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per return healthCheckFailures; } - /** - * Returns the unique id of the {@link Repository}. - * - * @return unique id - */ @Override public String getId() { return id; } - /** - * Returns the timestamp of the last modified date of the {@link Repository}. - * - * @return timestamp of the last modified date - */ @Override public Long getLastModified() { return lastModified; } - /** - * Returns the name of the {@link Repository}. - * - * @return name of the {@link Repository} - */ + public String getName() { return name; } - /** - * Returns the access permissions of the {@link Repository}. - * - * @return access permissions - */ + public String getNamespace() { return namespace; } + public List getPermissions() { if (permissions == null) { permissions = Lists.newArrayList(); diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java index 0938b8a02a..dc62c54d59 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java @@ -57,16 +57,8 @@ import sonia.scm.group.xml.XmlGroupDAO; import sonia.scm.io.DefaultFileSystem; import sonia.scm.io.FileSystem; import sonia.scm.net.SSLContextProvider; -import sonia.scm.net.ahc.AdvancedHttpClient; -import sonia.scm.net.ahc.ContentTransformer; -import sonia.scm.net.ahc.DefaultAdvancedHttpClient; -import sonia.scm.net.ahc.JsonContentTransformer; -import sonia.scm.net.ahc.XmlContentTransformer; -import sonia.scm.plugin.DefaultPluginLoader; -import sonia.scm.plugin.DefaultPluginManager; -import sonia.scm.plugin.ExtensionProcessor; -import sonia.scm.plugin.PluginLoader; -import sonia.scm.plugin.PluginManager; +import sonia.scm.net.ahc.*; +import sonia.scm.plugin.*; import sonia.scm.repository.*; import sonia.scm.repository.api.HookContextFactory; import sonia.scm.repository.api.RepositoryServiceFactory; @@ -78,32 +70,13 @@ import sonia.scm.resources.ResourceManager; import sonia.scm.resources.ScriptResourceServlet; import sonia.scm.schedule.QuartzScheduler; import sonia.scm.schedule.Scheduler; -import sonia.scm.security.AuthorizationChangedEventProducer; -import sonia.scm.security.CipherHandler; -import sonia.scm.security.CipherUtil; -import sonia.scm.security.ConfigurableLoginAttemptHandler; -import sonia.scm.security.DefaultKeyGenerator; -import sonia.scm.security.DefaultSecuritySystem; -import sonia.scm.security.KeyGenerator; -import sonia.scm.security.LoginAttemptHandler; -import sonia.scm.security.SecuritySystem; -import sonia.scm.store.BlobStoreFactory; -import sonia.scm.store.ConfigurationEntryStoreFactory; -import sonia.scm.store.ConfigurationStoreFactory; -import sonia.scm.store.DataStoreFactory; -import sonia.scm.store.FileBlobStoreFactory; -import sonia.scm.store.JAXBConfigurationEntryStoreFactory; -import sonia.scm.store.JAXBConfigurationStoreFactory; -import sonia.scm.store.JAXBDataStoreFactory; +import sonia.scm.security.*; +import sonia.scm.store.*; import sonia.scm.template.MustacheTemplateEngine; import sonia.scm.template.TemplateEngine; import sonia.scm.template.TemplateEngineFactory; import sonia.scm.template.TemplateServlet; -import sonia.scm.url.RestJsonUrlProvider; -import sonia.scm.url.RestXmlUrlProvider; -import sonia.scm.url.UrlProvider; -import sonia.scm.url.UrlProviderFactory; -import sonia.scm.url.WebUIUrlProvider; +import sonia.scm.url.*; import sonia.scm.user.DefaultUserManager; import sonia.scm.user.UserDAO; import sonia.scm.user.UserManager; @@ -223,7 +196,9 @@ public class ScmServletModule extends ServletModule ScmConfiguration config = getScmConfiguration(); CipherUtil cu = CipherUtil.getInstance(); - + + bind(NamespaceStrategy.class).toProvider(NamespaceStrategyProvider.class); + // bind repository provider ThrowingProviderBinder.create(binder()).bind( RepositoryProvider.class, Repository.class).to( @@ -351,10 +326,10 @@ public class ScmServletModule extends ServletModule // bind events // bind(LastModifiedUpdateListener.class); - Class namespaceStrategy = extensionProcessor.byExtensionPoint(NamespaceStrategy.class).iterator().next(); - bind(NamespaceStrategy.class, namespaceStrategy); + } + /** * Method description * diff --git a/scm-webapp/src/main/java/sonia/scm/repository/DefaultNamespaceStrategy.java b/scm-webapp/src/main/java/sonia/scm/repository/DefaultNamespaceStrategy.java index ce6362ee9c..e68d03909b 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/DefaultNamespaceStrategy.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/DefaultNamespaceStrategy.java @@ -1,11 +1,18 @@ package sonia.scm.repository; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.subject.Subject; import sonia.scm.plugin.Extension; +import sonia.scm.user.User; + @Extension -public class DefaultNamespaceStrategy implements NamespaceStrategy{ +public class DefaultNamespaceStrategy implements NamespaceStrategy { + @Override public String getNamespace() { - return "42"; + Subject subject = SecurityUtils.getSubject(); + String displayName = subject.getPrincipals().oneByType(User.class).getName(); + return displayName; } } diff --git a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java index 00271a75cb..363cc4c0bb 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java @@ -42,29 +42,14 @@ import com.google.inject.Singleton; import org.apache.shiro.concurrent.SubjectAwareExecutorService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import sonia.scm.ArgumentIsInvalidException; -import sonia.scm.ConfigurationException; -import sonia.scm.HandlerEventType; -import sonia.scm.SCMContextProvider; -import sonia.scm.Type; +import sonia.scm.*; import sonia.scm.config.ScmConfiguration; import sonia.scm.security.KeyGenerator; -import sonia.scm.util.AssertUtil; -import sonia.scm.util.CollectionAppender; -import sonia.scm.util.HttpUtil; -import sonia.scm.util.IOUtil; -import sonia.scm.util.Util; +import sonia.scm.util.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; @@ -128,16 +113,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { } } - /** - * Method description - * - * - * @param repository - * @param initRepository - * - * @throws IOException - * @throws RepositoryException - */ public void create(Repository repository, boolean initRepository) throws RepositoryException, IOException { logger.info("create repository {} of type {}", repository.getName(), @@ -163,30 +138,12 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { fireEvent(HandlerEventType.CREATE, repository); } - /** - * Method description - * - * - * @param repository - * - * @throws IOException - * @throws RepositoryException - */ @Override public void create(Repository repository) throws RepositoryException, IOException { create(repository, true); } - /** - * Method description - * - * - * @param repository - * - * @throws IOException - * @throws RepositoryException - */ @Override public void delete(Repository repository) throws RepositoryException, IOException { @@ -213,40 +170,16 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { } } - /** - * Method description - * - * - * @param repository - * - * @throws IOException - * @throws RepositoryException - */ @Override public void importRepository(Repository repository) throws RepositoryException, IOException { create(repository, false); } - /** - * Method description - * - * - * @param context - */ @Override public void init(SCMContextProvider context) { } - /** - * Method description - * - * - * @param repository - * - * @throws IOException - * @throws RepositoryException - */ @Override public void modify(Repository repository) throws RepositoryException, IOException { @@ -273,15 +206,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { } } - /** - * Method description - * - * - * @param repository - * - * @throws IOException - * @throws RepositoryException - */ @Override public void refresh(Repository repository) throws RepositoryException, IOException { @@ -299,16 +223,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { } } - //~--- get methods ---------------------------------------------------------- - /** - * Method description - * - * - * @param id - * - * @return - */ @Override public Repository get(String id) { AssertUtil.assertIsNotEmpty(id); @@ -324,15 +239,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { return repository; } - /** - * Method description - * - * - * @param type - * @param name - * - * @return - */ @Override public Repository get(String type, String name) { AssertUtil.assertIsNotEmpty(type); @@ -348,14 +254,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { return repository; } - /** - * Method description - * - * - * - * @param comparator - * @return - */ @Override public Collection getAll(Comparator comparator) { List repositories = Lists.newArrayList(); @@ -378,28 +276,12 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { return repositories; } - /** - * Method description - * - * - * @return - */ @Override public Collection getAll() { return getAll(null); } - /** - * Method description - * - * - * - * @param comparator - * @param start - * @param limit - * - * @return - */ + @Override public Collection getAll(Comparator comparator, int start, int limit) { @@ -417,26 +299,11 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { }, start, limit); } - /** - * Method description - * - * - * @param start - * @param limit - * - * @return - */ @Override public Collection getAll(int start, int limit) { return getAll(null, start, limit); } - /** - * Method description - * - * - * @return - */ @Override public Collection getConfiguredTypes() { List validTypes = Lists.newArrayList(); @@ -450,14 +317,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { return validTypes; } - /** - * Method description - * - * - * @param request - * - * @return - */ @Override public Repository getFromRequest(HttpServletRequest request) { AssertUtil.assertIsNotNull(request); @@ -465,15 +324,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { return getFromUri(HttpUtil.getStrippedURI(request)); } - /** - * Method description - * - * - * @param type - * @param uri - * - * @return - */ @Override public Repository getFromTypeAndUri(String type, String uri) { if (Strings.isNullOrEmpty(type)) { @@ -512,14 +362,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { return repository; } - /** - * Method description - * - * - * @param uri - * - * @return - */ @Override public Repository getFromUri(String uri) { AssertUtil.assertIsNotEmpty(uri); @@ -541,51 +383,21 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { return repository; } - /** - * Method description - * - * - * @param type - * - * @return - */ @Override public RepositoryHandler getHandler(String type) { return handlerMap.get(type); } - /** - * Method description - * - * - * @return - */ @Override public Long getLastModified() { return repositoryDAO.getLastModified(); } - /** - * Method description - * - * - * @return - */ @Override public Collection getTypes() { return types; } - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - * - * - * @param contextProvider - * @param handler - */ private void addHandler(SCMContextProvider contextProvider, RepositoryHandler handler) { AssertUtil.assertIsNotNull(handler); @@ -609,19 +421,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { types.add(type); } - //~--- get methods ---------------------------------------------------------- - - /** - * Method description - * - * - * @param repository - * - * @return - * - * - * @throws RepositoryException - */ private RepositoryHandler getHandler(Repository repository) throws RepositoryException { String type = repository.getType(); diff --git a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerPerfTest.java b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerPerfTest.java index 95cbd44340..81059c1247 100644 --- a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerPerfTest.java +++ b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerPerfTest.java @@ -34,11 +34,7 @@ import com.google.common.base.Stopwatch; import com.google.common.collect.ImmutableSet; import com.google.inject.Provider; import org.apache.shiro.SecurityUtils; -import org.apache.shiro.authc.AuthenticationException; -import org.apache.shiro.authc.AuthenticationInfo; -import org.apache.shiro.authc.AuthenticationToken; -import org.apache.shiro.authc.SimpleAuthenticationInfo; -import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.authc.*; import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.mgt.DefaultSecurityManager; @@ -61,12 +57,7 @@ import sonia.scm.security.DefaultKeyGenerator; import sonia.scm.security.KeyGenerator; import sonia.scm.user.UserTestData; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.TimeUnit; import static org.mockito.Mockito.mock; @@ -96,8 +87,6 @@ public class DefaultRepositoryManagerPerfTest { private final KeyGenerator keyGenerator = new DefaultKeyGenerator(); - private final NamespaceStrategy namespaceStrategy = new DefaultNamespaceStrategy(); - @Mock private RepositoryHandler repositoryHandler; @@ -114,7 +103,7 @@ public class DefaultRepositoryManagerPerfTest { when(repositoryHandler.getType()).thenReturn(new Type(REPOSITORY_TYPE, REPOSITORY_TYPE)); Set handlerSet = ImmutableSet.of(repositoryHandler); RepositoryMatcher repositoryMatcher = new RepositoryMatcher(Collections.emptySet()); - + NamespaceStrategy namespaceStrategy = mock(NamespaceStrategy.class); repositoryManager = new DefaultRepositoryManager( configuration, contextProvider, @@ -132,10 +121,7 @@ public class DefaultRepositoryManagerPerfTest { ThreadContext.bind(securityManager); } - - /** - * Tear down test objects. - */ + @After public void tearDown(){ ThreadContext.unbindSecurityManager(); diff --git a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java index a66bf222cb..7bbdd657ee 100644 --- a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java +++ b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java @@ -58,25 +58,11 @@ import sonia.scm.store.ConfigurationStoreFactory; import sonia.scm.store.JAXBConfigurationStoreFactory; import java.io.IOException; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.Stack; +import java.util.*; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.hasProperty; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; //~--- JDK imports ------------------------------------------------------------ @@ -492,12 +478,15 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase Date: Fri, 6 Jul 2018 11:57:43 +0200 Subject: [PATCH 02/21] Implemented persisting repositories according to namespace changes Repository directories are now named after the repo's id instead of it's name --- .../AbstractSimpleRepositoryHandler.java | 335 ++++-------------- .../RepositoryDirectoryHandler.java | 8 - .../repository/GitRepositoryHandlerTest.java | 86 ++--- .../repository/HgRepositoryHandlerTest.java | 89 ++--- .../repository/SvnRepositoryHandlerTest.java | 99 ++++-- .../repository/DummyRepositoryHandler.java | 98 ++--- .../scm/repository/RepositoryTestData.java | 2 +- .../SimpleRepositoryHandlerTestBase.java | 132 ++----- 8 files changed, 283 insertions(+), 566 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java b/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java index 670cab93e1..b61a4dce19 100644 --- a/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java +++ b/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java @@ -1,19 +1,19 @@ /** * 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. + * 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. + * 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. - * + * 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 @@ -24,13 +24,11 @@ * 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 -------------------------------------------------------- @@ -38,181 +36,118 @@ package sonia.scm.repository; import com.google.common.base.Charsets; import com.google.common.base.Throwables; import com.google.common.io.Resources; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import sonia.scm.ConfigurationException; import sonia.scm.io.CommandResult; import sonia.scm.io.ExtendedCommand; import sonia.scm.io.FileSystem; +import sonia.scm.store.ConfigurationStoreFactory; import sonia.scm.util.IOUtil; -//~--- JDK imports ------------------------------------------------------------ - import java.io.File; import java.io.IOException; - import java.net.URL; -import sonia.scm.store.ConfigurationStoreFactory; + +//~--- JDK imports ------------------------------------------------------------ /** - * - * @author Sebastian Sdorra - * - * * @param + * @author Sebastian Sdorra */ public abstract class AbstractSimpleRepositoryHandler - extends AbstractRepositoryHandler implements RepositoryDirectoryHandler -{ + extends AbstractRepositoryHandler implements RepositoryDirectoryHandler { - /** Field description */ public static final String DEFAULT_VERSION_INFORMATION = "unknown"; - /** Field description */ public static final String DIRECTORY_REPOSITORY = "repositories"; - /** Field description */ public static final String DOT = "."; - /** the logger for AbstractSimpleRepositoryHandler */ + /** + * the logger for AbstractSimpleRepositoryHandler + */ private static final Logger logger = LoggerFactory.getLogger(AbstractSimpleRepositoryHandler.class); - //~--- constructors --------------------------------------------------------- + private FileSystem fileSystem; + - /** - * Constructs ... - * - * - * @param storeFactory - * @param fileSystem - */ public AbstractSimpleRepositoryHandler(ConfigurationStoreFactory storeFactory, - FileSystem fileSystem) - { + FileSystem fileSystem) { super(storeFactory); this.fileSystem = fileSystem; } - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - * - * @param repository - * - * @throws IOException - * @throws RepositoryException - */ @Override public void create(Repository repository) - throws RepositoryException, IOException - { + throws RepositoryException, IOException { File directory = getDirectory(repository); - if (directory.exists()) - { + if (directory.exists()) { throw RepositoryAlreadyExistsException.create(repository); } checkPath(directory); - try - { + try { fileSystem.create(directory); create(repository, directory); postCreate(repository, directory); - } - catch (Exception ex) - { - if (directory.exists()) - { - if (logger.isDebugEnabled()) - { + } catch (Exception ex) { + if (directory.exists()) { + if (logger.isDebugEnabled()) { logger.debug( - "delete repository directory {}, because of failed repository creation", - directory); + "delete repository directory {}, because of failed repository creation", + directory); } fileSystem.destroy(directory); } Throwables.propagateIfPossible(ex, RepositoryException.class, - IOException.class); + IOException.class); } } - /** - * Method description - * - * - * - * @param repository - * @return - */ @Override - public String createResourcePath(Repository repository) - { + public String createResourcePath(Repository repository) { StringBuilder path = new StringBuilder("/"); - path.append(getType().getName()).append("/").append(repository.getName()); + path.append(getType().getName()).append("/").append(repository.getId()); return path.toString(); } - /** - * Method description - * - * - * @param repository - * - * @throws IOException - * @throws RepositoryException - */ @Override public void delete(Repository repository) - throws RepositoryException, IOException - { + throws RepositoryException, IOException { File directory = getDirectory(repository); - if (directory.exists()) - { + if (directory.exists()) { fileSystem.destroy(directory); cleanupEmptyDirectories(config.getRepositoryDirectory(), - directory.getParentFile()); - } - else if (logger.isWarnEnabled()) - { + directory.getParentFile()); + } else if (logger.isWarnEnabled()) { logger.warn("repository {} not found", repository); } } - /** - * Method description - * - */ @Override - public void loadConfig() - { + public void loadConfig() { super.loadConfig(); - if (config == null) - { + if (config == null) { config = createInitialConfig(); - if (config != null) - { + if (config != null) { File repositoryDirectory = config.getRepositoryDirectory(); - if (repositoryDirectory == null) - { + if (repositoryDirectory == null) { repositoryDirectory = new File( - baseDirectory, - DIRECTORY_REPOSITORY.concat(File.separator).concat( - getType().getName())); + baseDirectory, + DIRECTORY_REPOSITORY.concat(File.separator).concat( + getType().getName())); config.setRepositoryDirectory(repositoryDirectory); } @@ -222,108 +157,52 @@ public abstract class AbstractSimpleRepositoryHandler * 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. + * 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. + * 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. - * + * 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 @@ -24,50 +24,45 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + *

* http://bitbucket.org/sdorra/scm-manager - * */ - package sonia.scm.repository; //~--- non-JDK imports -------------------------------------------------------- -import sonia.scm.io.DefaultFileSystem; - -import static org.junit.Assert.*; - -//~--- JDK imports ------------------------------------------------------------ - -import java.io.File; -import sonia.scm.store.ConfigurationStoreFactory; +import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import sonia.scm.io.DefaultFileSystem; import sonia.scm.schedule.Scheduler; +import sonia.scm.store.ConfigurationStoreFactory; + +import java.io.File; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +//~--- JDK imports ------------------------------------------------------------ /** * * @author Sebastian Sdorra */ @RunWith(MockitoJUnitRunner.class) -public class GitRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase -{ +public class GitRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase { @Mock private Scheduler scheduler; - - /** - * Method description - * - * - * @param directory - */ + + @Mock + private ConfigurationStoreFactory factory; + @Override - protected void checkDirectory(File directory) - { + protected void checkDirectory(File directory) { File head = new File(directory, "HEAD"); assertTrue(head.exists()); @@ -84,21 +79,12 @@ public class GitRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase assertTrue(refs.isDirectory()); } - /** - * Method description - * - * - * @param factory - * @param directory - * - * @return - */ + @Override protected RepositoryHandler createRepositoryHandler(ConfigurationStoreFactory factory, - File directory) - { + File directory) { GitRepositoryHandler repositoryHandler = new GitRepositoryHandler(factory, - new DefaultFileSystem(), scheduler); + new DefaultFileSystem(), scheduler); repositoryHandler.init(contextProvider); @@ -110,4 +96,20 @@ public class GitRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase return repositoryHandler; } + + @Test + public void getDirectory() { + GitRepositoryHandler repositoryHandler = new GitRepositoryHandler(factory, + new DefaultFileSystem(), scheduler); + + GitConfig gitConfig = new GitConfig(); + gitConfig.setRepositoryDirectory(new File("/path")); + repositoryHandler.setConfig(gitConfig); + + Repository repository = new Repository("id", "git", "Name"); + + File path = repositoryHandler.getDirectory(repository); + assertEquals("/path/id", path.getAbsolutePath()); + assertTrue(path.getAbsolutePath().endsWith("id")); + } } diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java index c14e5f1b61..2fdc039c53 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java @@ -1,19 +1,19 @@ /** * 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. + * 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. + * 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. - * + * 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 @@ -24,43 +24,45 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + *

* http://bitbucket.org/sdorra/scm-manager - * */ - package sonia.scm.repository; //~--- non-JDK imports -------------------------------------------------------- +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; import sonia.scm.io.DefaultFileSystem; - -import static org.junit.Assert.*; - -//~--- JDK imports ------------------------------------------------------------ +import sonia.scm.store.ConfigurationStoreFactory; import java.io.File; -import sonia.scm.store.ConfigurationStoreFactory; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +//~--- JDK imports ------------------------------------------------------------ /** * * @author Sebastian Sdorra */ -public class HgRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase -{ +@RunWith(MockitoJUnitRunner.class) +public class HgRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase { + + @Mock + private ConfigurationStoreFactory factory; + + @Mock + private com.google.inject.Provider provider; - /** - * Method description - * - * - * @param directory - */ @Override - protected void checkDirectory(File directory) - { + protected void checkDirectory(File directory) { File hgDirectory = new File(directory, ".hg"); assertTrue(hgDirectory.exists()); @@ -73,22 +75,12 @@ public class HgRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase assertTrue(hgrc.length() > 0); } - /** - * Method description - * - * - * @param factory - * @param directory - * - * @return - */ @Override protected RepositoryHandler createRepositoryHandler(ConfigurationStoreFactory factory, - File directory) - { + File directory) { HgRepositoryHandler handler = new HgRepositoryHandler(factory, - new DefaultFileSystem(), - new HgContextProvider()); + new DefaultFileSystem(), + new HgContextProvider()); handler.init(contextProvider); handler.getConfig().setRepositoryDirectory(directory); @@ -97,5 +89,22 @@ public class HgRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase return handler; } + + @Test + public void getDirectory() { + HgRepositoryHandler repositoryHandler = new HgRepositoryHandler(factory, + new DefaultFileSystem(), provider); + + HgConfig hgConfig = new HgConfig(); + hgConfig.setRepositoryDirectory(new File("/path")); + hgConfig.setHgBinary("hg"); + hgConfig.setPythonBinary("python"); + repositoryHandler.setConfig(hgConfig); + + Repository repository = new Repository("id", "git", "Name"); + + File path = repositoryHandler.getDirectory(repository); + assertEquals("/path/id", path.getAbsolutePath()); + assertTrue(path.getAbsolutePath().endsWith("id")); + } } -//~--- non-JDK imports -------------------------------------------------------- diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/SvnRepositoryHandlerTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/SvnRepositoryHandlerTest.java index af80e27bcf..a0774c9596 100644 --- a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/SvnRepositoryHandlerTest.java +++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/SvnRepositoryHandlerTest.java @@ -1,19 +1,19 @@ /** * 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. + * 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. + * 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. - * + * 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 @@ -24,42 +24,56 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + *

* http://bitbucket.org/sdorra/scm-manager - * */ - package sonia.scm.repository; -//~--- non-JDK imports -------------------------------------------------------- +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; import sonia.scm.io.DefaultFileSystem; - -import static org.junit.Assert.*; - -//~--- JDK imports ------------------------------------------------------------ +import sonia.scm.repository.api.HookContextFactory; +import sonia.scm.repository.spi.HookEventFacade; +import sonia.scm.store.ConfigurationStore; +import sonia.scm.store.ConfigurationStoreFactory; import java.io.File; -import sonia.scm.store.ConfigurationStoreFactory; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +//~--- JDK imports ------------------------------------------------------------ /** * * @author Sebastian Sdorra */ -public class SvnRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase -{ +@RunWith(MockitoJUnitRunner.class) +public class SvnRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase { + + @Mock + private ConfigurationStoreFactory factory; + + @Mock + private ConfigurationStore store; + + @Mock + private com.google.inject.Provider repositoryManagerProvider; + + private HookContextFactory hookContextFactory = new HookContextFactory(mock(PreProcessorUtil.class)); + + private HookEventFacade facade = new HookEventFacade(repositoryManagerProvider, hookContextFactory); - /** - * Method description - * - * - * @param directory - */ @Override - protected void checkDirectory(File directory) - { + protected void checkDirectory(File directory) { File format = new File(directory, "format"); assertTrue(format.exists()); @@ -71,21 +85,11 @@ public class SvnRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase assertTrue(db.isDirectory()); } - /** - * Method description - * - * - * @param factory - * @param directory - * - * @return - */ @Override protected RepositoryHandler createRepositoryHandler(ConfigurationStoreFactory factory, - File directory) - { + File directory) { SvnRepositoryHandler handler = new SvnRepositoryHandler(factory, - new DefaultFileSystem(), null); + new DefaultFileSystem(), null); handler.init(contextProvider); @@ -98,4 +102,21 @@ public class SvnRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase return handler; } + + @Test + public void getDirectory() { + when(factory.getStore(any(), any())).thenReturn(store); + SvnRepositoryHandler repositoryHandler = new SvnRepositoryHandler(factory, + new DefaultFileSystem(), facade); + + SvnConfig svnConfig = new SvnConfig(); + svnConfig.setRepositoryDirectory(new File("/path")); + repositoryHandler.setConfig(svnConfig); + + Repository repository = new Repository("id", "svn", "Name"); + + File path = repositoryHandler.getDirectory(repository); + assertEquals("/path/id", path.getAbsolutePath()); + assertTrue(path.getAbsolutePath().endsWith("id")); + } } diff --git a/scm-test/src/main/java/sonia/scm/repository/DummyRepositoryHandler.java b/scm-test/src/main/java/sonia/scm/repository/DummyRepositoryHandler.java index 0a85231da0..fa2cc1b0fd 100644 --- a/scm-test/src/main/java/sonia/scm/repository/DummyRepositoryHandler.java +++ b/scm-test/src/main/java/sonia/scm/repository/DummyRepositoryHandler.java @@ -1,19 +1,19 @@ /** * 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. + * 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. + * 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. - * + * 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 @@ -24,113 +24,67 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + *

* http://bitbucket.org/sdorra/scm-manager - * */ - package sonia.scm.repository; //~--- non-JDK imports -------------------------------------------------------- import sonia.scm.Type; import sonia.scm.io.DefaultFileSystem; - -//~--- JDK imports ------------------------------------------------------------ +import sonia.scm.store.ConfigurationStoreFactory; import java.io.File; -import java.io.IOException; -import sonia.scm.store.ConfigurationStoreFactory; +import java.util.HashSet; +import java.util.Set; + +//~--- JDK imports ------------------------------------------------------------ /** * * @author Sebastian Sdorra */ public class DummyRepositoryHandler - extends AbstractSimpleRepositoryHandler -{ + extends AbstractSimpleRepositoryHandler { - /** Field description */ public static final String TYPE_DISPLAYNAME = "Dummy"; - /** Field description */ public static final String TYPE_NAME = "dummy"; - /** Field description */ public static final Type TYPE = new Type(TYPE_NAME, TYPE_DISPLAYNAME); - //~--- constructors --------------------------------------------------------- + private Set existingRepoNames = new HashSet<>(); - /** - * Constructs ... - * - * - * @param storeFactory - */ - public DummyRepositoryHandler(ConfigurationStoreFactory storeFactory) - { + public DummyRepositoryHandler(ConfigurationStoreFactory storeFactory) { super(storeFactory, new DefaultFileSystem()); } - //~--- get methods ---------------------------------------------------------- - - /** - * Method description - * - * - * @return - */ @Override - public Type getType() - { + public Type getType() { return TYPE; } - //~--- methods -------------------------------------------------------------- - /** - * Method description - * - * - * @param repository - * @param directory - * - * @throws IOException - * @throws RepositoryException - */ @Override protected void create(Repository repository, File directory) - throws RepositoryException, IOException - { - - // do nothing + throws RepositoryException { + if (existingRepoNames.contains(repository.getNamespace() + repository.getName())) { + throw new RepositoryAlreadyExistsException("Repo exists"); + } else { + existingRepoNames.add(repository.getNamespace() + repository.getName()); + } } - /** - * Method description - * - * - * @return - */ @Override - protected SimpleRepositoryConfig createInitialConfig() - { + protected SimpleRepositoryConfig createInitialConfig() { return new SimpleRepositoryConfig(); } - //~--- get methods ---------------------------------------------------------- - - /** - * Method description - * - * - * @return - */ @Override - protected Class getConfigClass() - { + protected Class getConfigClass() { return SimpleRepositoryConfig.class; } } diff --git a/scm-test/src/main/java/sonia/scm/repository/RepositoryTestData.java b/scm-test/src/main/java/sonia/scm/repository/RepositoryTestData.java index d5d443fe31..c9ea3c7886 100644 --- a/scm-test/src/main/java/sonia/scm/repository/RepositoryTestData.java +++ b/scm-test/src/main/java/sonia/scm/repository/RepositoryTestData.java @@ -141,7 +141,7 @@ public final class RepositoryTestData heartOfGold.setName("HeartOfGold"); heartOfGold.setDescription( "Heart of Gold is the first prototype ship to successfully utilise the revolutionary Infinite Improbability Drive"); - + heartOfGold.setId("hogId"); return heartOfGold; } diff --git a/scm-test/src/main/java/sonia/scm/repository/SimpleRepositoryHandlerTestBase.java b/scm-test/src/main/java/sonia/scm/repository/SimpleRepositoryHandlerTestBase.java index 19af367a1d..07a9495588 100644 --- a/scm-test/src/main/java/sonia/scm/repository/SimpleRepositoryHandlerTestBase.java +++ b/scm-test/src/main/java/sonia/scm/repository/SimpleRepositoryHandlerTestBase.java @@ -1,19 +1,19 @@ /** * 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. + * 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. + * 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. - * + * 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 @@ -24,169 +24,94 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + *

* http://bitbucket.org/sdorra/scm-manager - * */ - package sonia.scm.repository; //~--- non-JDK imports -------------------------------------------------------- import org.junit.Test; - import sonia.scm.AbstractTestBase; +import sonia.scm.store.ConfigurationStoreFactory; import sonia.scm.store.InMemoryConfigurationStoreFactory; import sonia.scm.util.IOUtil; +import java.io.File; +import java.io.IOException; + import static org.junit.Assert.*; //~--- JDK imports ------------------------------------------------------------ -import java.io.File; -import java.io.IOException; -import sonia.scm.store.ConfigurationStoreFactory; - /** * * @author Sebastian Sdorra */ -public abstract class SimpleRepositoryHandlerTestBase extends AbstractTestBase -{ +public abstract class SimpleRepositoryHandlerTestBase extends AbstractTestBase { + - /** - * Method description - * - * - * @param directory - */ protected abstract void checkDirectory(File directory); - /** - * Method description - * - * - * @param factory - * @param directory - * - * @return - */ protected abstract RepositoryHandler createRepositoryHandler( - ConfigurationStoreFactory factory, File directory); + ConfigurationStoreFactory factory, File directory); - /** - * Method description - * - * - * @throws IOException - * @throws RepositoryException - */ @Test - public void testCreate() throws RepositoryException, IOException - { + public void testCreate() throws RepositoryException, IOException { createRepository(); } - /** - * Method description - * - * - * @throws IOException - * @throws RepositoryException - */ @Test(expected = RepositoryAlreadyExistsException.class) public void testCreateExisitingRepository() - throws RepositoryException, IOException - { + throws RepositoryException, IOException { createRepository(); createRepository(); } - /** - * Method description - * - * - * @throws IOException - * @throws RepositoryException - */ @Test - public void testCreateResourcePath() throws RepositoryException, IOException - { + public void testCreateResourcePath() throws RepositoryException, IOException { Repository repository = createRepository(); String path = handler.createResourcePath(repository); assertNotNull(path); assertTrue(path.trim().length() > 0); - assertTrue(path.contains(repository.getName())); + assertTrue(path.contains(repository.getId())); } - /** - * Method description - * - * - * @throws IOException - * @throws RepositoryException - */ @Test - public void testDelete() throws RepositoryException, IOException - { + public void testDelete() throws RepositoryException, IOException { Repository repository = createRepository(); handler.delete(repository); - File directory = new File(baseDirectory, repository.getName()); + File directory = new File(baseDirectory, repository.getId()); assertFalse(directory.exists()); } - /** - * Method description - * - * - * @throws Exception - */ @Override - protected void postSetUp() throws Exception - { + protected void postSetUp() throws Exception { InMemoryConfigurationStoreFactory storeFactory = new InMemoryConfigurationStoreFactory(); baseDirectory = new File(contextProvider.getBaseDirectory(), "repositories"); IOUtil.mkdirs(baseDirectory); handler = createRepositoryHandler(storeFactory, baseDirectory); } - /** - * Method description - * - * - * @throws Exception - */ @Override - protected void preTearDown() throws Exception - { - if (handler != null) - { + protected void preTearDown() throws Exception { + if (handler != null) { handler.close(); } } - /** - * Method description - * - * - * @return - * - * @throws IOException - * @throws RepositoryException - */ - private Repository createRepository() throws RepositoryException, IOException - { + private Repository createRepository() throws RepositoryException, IOException { Repository repository = RepositoryTestData.createHeartOfGold(); handler.create(repository); - File directory = new File(baseDirectory, repository.getName()); + File directory = new File(baseDirectory, repository.getId()); assertTrue(directory.exists()); assertTrue(directory.isDirectory()); @@ -195,11 +120,8 @@ public abstract class SimpleRepositoryHandlerTestBase extends AbstractTestBase return repository; } - //~--- fields --------------------------------------------------------------- - /** Field description */ protected File baseDirectory; - /** Field description */ private RepositoryHandler handler; } From 091af43daa0e5f34b3134c34405fe9b3dd6119a0 Mon Sep 17 00:00:00 2001 From: Philipp Czora Date: Fri, 6 Jul 2018 12:16:51 +0200 Subject: [PATCH 03/21] Fixed merge errors --- .../AbstractSimpleRepositoryHandler.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java b/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java index 0e0e05f74b..90015f0f31 100644 --- a/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java +++ b/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java @@ -81,8 +81,7 @@ public abstract class AbstractSimpleRepositoryHandler Date: Fri, 6 Jul 2018 15:03:13 +0200 Subject: [PATCH 04/21] Create id for all test repositories --- .../scm/repository/RepositoryTestData.java | 152 +++++++----------- 1 file changed, 54 insertions(+), 98 deletions(-) diff --git a/scm-test/src/main/java/sonia/scm/repository/RepositoryTestData.java b/scm-test/src/main/java/sonia/scm/repository/RepositoryTestData.java index c9ea3c7886..65fad6f80d 100644 --- a/scm-test/src/main/java/sonia/scm/repository/RepositoryTestData.java +++ b/scm-test/src/main/java/sonia/scm/repository/RepositoryTestData.java @@ -33,147 +33,103 @@ package sonia.scm.repository; -/** - * - * @author Sebastian Sdorra - */ public final class RepositoryTestData { - /** - * Constructs ... - * - */ private RepositoryTestData() {} - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - * - * @return - */ public static Repository create42Puzzle() { return create42Puzzle(DummyRepositoryHandler.TYPE_NAME); } - /** - * Method description - * - * - * @param type - * - * @return - */ public static Repository create42Puzzle(String type) { - Repository repository = new Repository(); - - repository.setType(type); - repository.setContact("douglas.adams@hitchhiker.com"); - repository.setName("42Puzzle"); - repository.setDescription("The 42 Puzzle"); - - return repository; + return new Builder() + .type(type) + .contact("douglas.adams@hitchhiker.com") + .name("42Puzzle") + .description("The 42 Puzzle") + .build(); } - /** - * Method description - * - * - * @return - */ public static Repository createHappyVerticalPeopleTransporter() { return createHappyVerticalPeopleTransporter( DummyRepositoryHandler.TYPE_NAME); } - /** - * Method description - * - * - * - * @param type - * @return - */ public static Repository createHappyVerticalPeopleTransporter(String type) { - Repository happyVerticalPeopleTransporter = new Repository(); - - happyVerticalPeopleTransporter.setType(type); - happyVerticalPeopleTransporter.setContact( - "zaphod.beeblebrox@hitchhiker.com"); - happyVerticalPeopleTransporter.setName("happyVerticalPeopleTransporter"); - happyVerticalPeopleTransporter.setDescription( - "Happy Vertical People Transporter"); - - return happyVerticalPeopleTransporter; + return new Builder() + .type(type) + .contact("zaphod.beeblebrox@hitchhiker.com") + .name("happyVerticalPeopleTransporter") + .description("Happy Vertical People Transporter") + .build(); } - /** - * Method description - * - * - * @return - */ public static Repository createHeartOfGold() { return createHeartOfGold(DummyRepositoryHandler.TYPE_NAME); } - /** - * Method description - * - * - * - * @param type - * @return - */ public static Repository createHeartOfGold(String type) { - Repository heartOfGold = new Repository(); - - heartOfGold.setType(type); - heartOfGold.setContact("zaphod.beeblebrox@hitchhiker.com"); - heartOfGold.setName("HeartOfGold"); - heartOfGold.setDescription( - "Heart of Gold is the first prototype ship to successfully utilise the revolutionary Infinite Improbability Drive"); - heartOfGold.setId("hogId"); - return heartOfGold; + return new Builder() + .type(type) + .contact("zaphod.beeblebrox@hitchhiker.com") + .name("HeartOfGold") + .description( + "Heart of Gold is the first prototype ship to successfully utilise the revolutionary Infinite Improbability Drive") + .build(); } - /** - * Method description - * - * - * @return - */ public static Repository createRestaurantAtTheEndOfTheUniverse() { return createRestaurantAtTheEndOfTheUniverse( DummyRepositoryHandler.TYPE_NAME); } - /** - * Method description - * - * - * @param type - * - * @return - */ public static Repository createRestaurantAtTheEndOfTheUniverse(String type) { + return new Builder() + .type(type) + .contact("douglas.adams@hitchhiker.com") + .name("RestaurantAtTheEndOfTheUniverse") + .description("The Restaurant at the End of the Universe") + .build(); + } + + private static class Builder { + private static int nextID = 0; Repository repository = new Repository(); + { + repository.setId("ID-" + ++nextID); + } - repository.setType(type); - repository.setContact("douglas.adams@hitchhiker.com"); - repository.setName("RestaurantAtTheEndOfTheUniverse"); - repository.setDescription("The Restaurant at the End of the Universe"); + Builder type(String type) { + repository.setType(type); + return this; + } - return repository; + Builder contact(String contact) { + repository.setContact(contact); + return this; + } + + Builder name(String name) { + repository.setName(name); + return this; + } + + Builder description(String description) { + repository.setDescription(description); + return this; + } + + public Repository build() { + return repository; + } } } From 43ca72255e071f3e7d5e59d5cdf182fc1c0f6171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 9 Jul 2018 10:47:28 +0200 Subject: [PATCH 05/21] Remove redundant checks --- .../test/java/sonia/scm/repository/GitRepositoryHandlerTest.java | 1 - .../test/java/sonia/scm/repository/HgRepositoryHandlerTest.java | 1 - .../test/java/sonia/scm/repository/SvnRepositoryHandlerTest.java | 1 - 3 files changed, 3 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryHandlerTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryHandlerTest.java index 741892a0b1..d5201dca83 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryHandlerTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryHandlerTest.java @@ -110,6 +110,5 @@ public class GitRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase { File path = repositoryHandler.getDirectory(repository); assertEquals("/path/id", path.getAbsolutePath()); - assertTrue(path.getAbsolutePath().endsWith("id")); } } diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java index 2fdc039c53..c5d62dc054 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java @@ -105,6 +105,5 @@ public class HgRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase { File path = repositoryHandler.getDirectory(repository); assertEquals("/path/id", path.getAbsolutePath()); - assertTrue(path.getAbsolutePath().endsWith("id")); } } diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/SvnRepositoryHandlerTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/SvnRepositoryHandlerTest.java index a0774c9596..c7cd78dc75 100644 --- a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/SvnRepositoryHandlerTest.java +++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/SvnRepositoryHandlerTest.java @@ -117,6 +117,5 @@ public class SvnRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase { File path = repositoryHandler.getDirectory(repository); assertEquals("/path/id", path.getAbsolutePath()); - assertTrue(path.getAbsolutePath().endsWith("id")); } } From dc8ecd5689ded5278ae850217b3021bf2b140c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 10 Jul 2018 15:31:18 +0200 Subject: [PATCH 06/21] Adjust to repository storage with id --- .../scm/repository/AbstactImportHandler.java | 108 ++++---- .../scm/repository/NamespaceAndName.java | 50 ++++ .../java/sonia/scm/repository/Repository.java | 17 +- .../sonia/scm/repository/RepositoryDAO.java | 17 +- .../scm/repository/RepositoryManager.java | 27 +- .../RepositoryManagerDecorator.java | 34 +-- .../sonia/scm/repository/RepositoryUtil.java | 198 ++------------- .../api/RepositoryServiceFactory.java | 32 +-- .../scm/repository/spi/HookEventFacade.java | 45 +--- .../main/java/sonia/scm/util/HttpUtil.java | 20 +- .../scm/web/filter/RegexPermissionFilter.java | 133 ---------- .../sonia/scm/repository/RepositoryTest.java | 4 +- .../scm/repository/xml/XmlRepositoryDAO.java | 30 +-- .../repository/xml/XmlRepositoryDatabase.java | 129 ++-------- .../xml/XmlRepositoryMapAdapter.java | 7 +- .../java/sonia/scm/web/GitReceiveHook.java | 18 +- .../repository/GitRepositoryHandlerTest.java | 2 +- .../GitRepositoryPathMatcherTest.java | 22 +- .../spi/AbstractRemoteCommandTestBase.java | 19 +- .../scm/web/lfs/LfsBlobStoreFactoryTest.java | 9 +- .../lfs/servlet/LfsServletFactoryTest.java | 10 +- .../spi/HgHookChangesetProvider.java | 24 +- .../repository/spi/HgHookContextProvider.java | 15 +- .../sonia/scm/web/HgHookCallbackServlet.java | 85 ++----- .../repository/HgRepositoryHandlerTest.java | 2 +- .../spi/IncomingOutgoingTestBase.java | 21 +- .../scm/web/HgHookCallbackServletTest.java | 41 +++ .../scm/repository/SvnRepositoryHook.java | 17 +- .../repository/SvnRepositoryHandlerTest.java | 2 +- .../repository/DummyRepositoryHandler.java | 10 +- .../scm/repository/RepositoryBuilder.java | 49 ++++ .../scm/repository/RepositoryTestData.java | 82 ++---- .../SimpleRepositoryHandlerTestBase.java | 23 +- .../resources/RepositoryImportResource.java | 6 +- .../rest/resources/RepositoryResource.java | 36 --- .../repository/DefaultRepositoryManager.java | 86 ++++--- .../scm/repository/RepositoryMatcher.java | 36 ++- .../DefaultRepositoryManagerPerfTest.java | 17 +- .../DefaultRepositoryManagerTest.java | 237 +++++++----------- .../scm/repository/RepositoryMatcherTest.java | 19 +- 40 files changed, 619 insertions(+), 1120 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/repository/NamespaceAndName.java delete mode 100644 scm-core/src/main/java/sonia/scm/web/filter/RegexPermissionFilter.java create mode 100644 scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/web/HgHookCallbackServletTest.java create mode 100644 scm-test/src/main/java/sonia/scm/repository/RepositoryBuilder.java diff --git a/scm-core/src/main/java/sonia/scm/repository/AbstactImportHandler.java b/scm-core/src/main/java/sonia/scm/repository/AbstactImportHandler.java index 2da506674d..6e0827af4a 100644 --- a/scm-core/src/main/java/sonia/scm/repository/AbstactImportHandler.java +++ b/scm-core/src/main/java/sonia/scm/repository/AbstactImportHandler.java @@ -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 repositoryNames = - RepositoryUtil.getRepositoryNames(getRepositoryHandler(), - getDirectoryNames()); - - for (String repositoryName : repositoryNames) - { - importRepository(manager, builder, throwExceptions, repositoryName); - } - - } - catch (IOException ex) - { - handleException(ex, throwExceptions); - } + // TODO #8783 +// try +// { +// +// List 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); +// } } /** diff --git a/scm-core/src/main/java/sonia/scm/repository/NamespaceAndName.java b/scm-core/src/main/java/sonia/scm/repository/NamespaceAndName.java new file mode 100644 index 0000000000..1aa6f474f0 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/NamespaceAndName.java @@ -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); + } +} diff --git a/scm-core/src/main/java/sonia/scm/repository/Repository.java b/scm-core/src/main/java/sonia/scm/repository/Repository.java index df340564f6..b2d99c85e1 100644 --- a/scm-core/src/main/java/sonia/scm/repository/Repository.java +++ b/scm-core/src/main/java/sonia/scm/repository/Repository.java @@ -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 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); } /** diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryDAO.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryDAO.java index 9a2d4b5662..ce309ecee6 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryDAO.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryDAO.java @@ -49,27 +49,22 @@ public interface RepositoryDAO extends GenericDAO /** * 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); } diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryManager.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryManager.java index 7cbac2b52e..172108aa1b 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryManager.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryManager.java @@ -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. * diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryManagerDecorator.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryManagerDecorator.java index 632b54b741..6990baf7c5 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryManagerDecorator.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryManagerDecorator.java @@ -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} * diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryUtil.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryUtil.java index e271992248..4bf10387d4 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryUtil.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryUtil.java @@ -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 searchRepositoryDirectories(File directory, - String... names) - { - List repositories = new ArrayList(); + public static List searchRepositoryDirectories(File directory, String... names) { + List 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 getRepositoryNames( - AbstractRepositoryHandler handler, String... directoryNames) - throws IOException - { - return getRepositoryNames(handler.getConfig(), directoryNames); - } - - /** - * Method description - * - * - * @param config - * @param directoryNames - * - * @return - * - * @throws IOException - */ - public static List getRepositoryNames(SimpleRepositoryConfig config, - String... directoryNames) - throws IOException - { - return getRepositoryNames(config.getRepositoryDirectory(), directoryNames); - } - - /** - * Method description - * - * - * @param baseDirectory - * @param directoryNames - * - * @return - * - * @throws IOException - */ - public static List getRepositoryNames(File baseDirectory, - String... directoryNames) - throws IOException - { - List repositories = new ArrayList(); - List 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 repositories, File directory, List names) { diff --git a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java index 5bd737a85a..90084b876e 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java @@ -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); diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/HookEventFacade.java b/scm-core/src/main/java/sonia/scm/repository/spi/HookEventFacade.java index 899892a5b7..93ed5f1111 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/HookEventFacade.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/HookEventFacade.java @@ -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) { diff --git a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java index 27abcaffbe..99de58023e 100644 --- a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java +++ b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java @@ -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 */ diff --git a/scm-core/src/main/java/sonia/scm/web/filter/RegexPermissionFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/RegexPermissionFilter.java deleted file mode 100644 index 40c41a5954..0000000000 --- a/scm-core/src/main/java/sonia/scm/web/filter/RegexPermissionFilter.java +++ /dev/null @@ -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; -} diff --git a/scm-core/src/test/java/sonia/scm/repository/RepositoryTest.java b/scm-core/src/test/java/sonia/scm/repository/RepositoryTest.java index 11bb602611..f13f4cbc67 100644 --- a/scm-core/src/test/java/sonia/scm/repository/RepositoryTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/RepositoryTest.java @@ -34,7 +34,7 @@ package sonia.scm.repository; import org.junit.Test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; /** * @@ -50,7 +50,7 @@ public class RepositoryTest @Test public void testCreateUrl() { - Repository repository = new Repository("123", "hg", "test/repo"); + Repository repository = new Repository("123", "hg", "test", "repo"); assertEquals("http://localhost:8080/scm/hg/test/repo", repository.createUrl("http://localhost:8080/scm")); diff --git a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDAO.java b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDAO.java index 7c17c365aa..4510706721 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDAO.java +++ b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDAO.java @@ -36,11 +36,11 @@ package sonia.scm.repository.xml; import com.google.inject.Inject; import com.google.inject.Singleton; - +import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryDAO; -import sonia.scm.xml.AbstractXmlDAO; import sonia.scm.store.ConfigurationStoreFactory; +import sonia.scm.xml.AbstractXmlDAO; /** * @@ -71,36 +71,18 @@ public class XmlRepositoryDAO //~--- methods -------------------------------------------------------------- - /** - * Method description - * - * - * @param type - * @param name - * - * @return - */ @Override - public boolean contains(String type, String name) + public boolean contains(NamespaceAndName namespaceAndName) { - return db.contains(type, name); + return db.contains(namespaceAndName); } //~--- get methods ---------------------------------------------------------- - /** - * Method description - * - * - * @param type - * @param name - * - * @return - */ @Override - public Repository get(String type, String name) + public Repository get(NamespaceAndName namespaceAndName) { - return db.get(type, name); + return db.get(namespaceAndName); } //~--- methods -------------------------------------------------------------- diff --git a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDatabase.java b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDatabase.java index a5c599c291..1c82b07f50 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDatabase.java +++ b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDatabase.java @@ -35,34 +35,26 @@ package sonia.scm.repository.xml; //~--- non-JDK imports -------------------------------------------------------- +import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.Repository; import sonia.scm.xml.XmlDatabase; -//~--- JDK imports ------------------------------------------------------------ - -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.Map; - import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +//~--- JDK imports ------------------------------------------------------------ -/** - * - * @author Sebastian Sdorra - */ @XmlRootElement(name = "repository-db") @XmlAccessorType(XmlAccessType.FIELD) public class XmlRepositoryDatabase implements XmlDatabase { - /** - * Constructs ... - * - */ public XmlRepositoryDatabase() { long c = System.currentTimeMillis(); @@ -71,124 +63,53 @@ public class XmlRepositoryDatabase implements XmlDatabase lastModified = c; } - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - * - * @param type - * @param name - * - * @return - */ - static String createKey(String type, String name) + static String createKeyX(NamespaceAndName namespaceAndName) { - return type.concat(":").concat(name); + return namespaceAndName.getNamespace() + ":" + namespaceAndName.getName(); } - /** - * Method description - * - * - * @param repository - * - * @return - */ - static String createKey(Repository repository) + static String createKeyX(Repository repository) { - return createKey(repository.getType(), repository.getName()); + return createKeyX(repository.getNamespaceAndName()); } - /** - * Method description - * - * - * @param repository - */ @Override public void add(Repository repository) { - repositoryMap.put(createKey(repository), repository); + repositoryMap.put(createKeyX(repository), repository); } - /** - * Method description - * - * - * - * @param type - * @param name - * - * @return - */ - public boolean contains(String type, String name) + public boolean contains(NamespaceAndName namespaceAndName) { - return repositoryMap.containsKey(createKey(type, name)); + return repositoryMap.containsKey(createKeyX(namespaceAndName)); } - /** - * Method description - * - * - * @param id - * - * @return - */ @Override public boolean contains(String id) { return get(id) != null; } - /** - * Method description - * - * - * @param repository - * - * @return - */ public boolean contains(Repository repository) { - return repositoryMap.containsKey(createKey(repository)); + return repositoryMap.containsKey(createKeyX(repository)); } - /** - * Method description - * - * - * @param repository - */ - public void remove(Repository repository) + public void removeX(Repository repository) { - repositoryMap.remove(createKey(repository)); + repositoryMap.remove(createKeyX(repository)); } - /** - * Method description - * - * - * @param id - * - * @return - */ @Override public Repository remove(String id) { Repository r = get(id); - remove(r); + removeX(r); return r; } - /** - * Method description - * - * - * @return - */ @Override public Collection values() { @@ -197,18 +118,9 @@ public class XmlRepositoryDatabase implements XmlDatabase //~--- get methods ---------------------------------------------------------- - /** - * Method description - * - * - * @param type - * @param name - * - * @return - */ - public Repository get(String type, String name) + public Repository get(NamespaceAndName namespaceAndName) { - return repositoryMap.get(createKey(type, name)); + return repositoryMap.get(createKeyX(namespaceAndName)); } /** @@ -298,6 +210,5 @@ public class XmlRepositoryDatabase implements XmlDatabase /** Field description */ @XmlJavaTypeAdapter(XmlRepositoryMapAdapter.class) @XmlElement(name = "repositories") - private Map repositoryMap = new LinkedHashMap(); + private Map repositoryMap = new LinkedHashMap<>(); } diff --git a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryMapAdapter.java b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryMapAdapter.java index a90a2d4fa9..4706c64f62 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryMapAdapter.java +++ b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryMapAdapter.java @@ -37,12 +37,11 @@ package sonia.scm.repository.xml; import sonia.scm.repository.Repository; -//~--- JDK imports ------------------------------------------------------------ - +import javax.xml.bind.annotation.adapters.XmlAdapter; import java.util.LinkedHashMap; import java.util.Map; -import javax.xml.bind.annotation.adapters.XmlAdapter; +//~--- JDK imports ------------------------------------------------------------ /** * @@ -88,7 +87,7 @@ public class XmlRepositoryMapAdapter for (Repository repository : repositories) { - repositoryMap.put(XmlRepositoryDatabase.createKey(repository), + repositoryMap.put(XmlRepositoryDatabase.createKeyX(repository), repository); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitReceiveHook.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitReceiveHook.java index 3ecd6047e9..eeda60ed02 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitReceiveHook.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitReceiveHook.java @@ -40,24 +40,21 @@ import org.eclipse.jgit.transport.PostReceiveHook; import org.eclipse.jgit.transport.PreReceiveHook; import org.eclipse.jgit.transport.ReceiveCommand; import org.eclipse.jgit.transport.ReceivePack; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.RepositoryHookType; import sonia.scm.repository.RepositoryUtil; import sonia.scm.repository.spi.GitHookContextProvider; import sonia.scm.repository.spi.HookEventFacade; -//~--- JDK imports ------------------------------------------------------------ - import java.io.File; import java.io.IOException; - import java.util.Collection; import java.util.List; +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra @@ -131,15 +128,14 @@ public class GitReceiveHook implements PreReceiveHook, PostReceiveHook try { Repository repository = rpack.getRepository(); - String repositoryName = resolveRepositoryName(repository); + String id = resolveRepositoryId(repository); - logger.trace("resolved repository name to {}", repositoryName); + logger.trace("resolved repository to id {}", id); GitHookContextProvider context = new GitHookContextProvider(rpack, receiveCommands); - hookEventFacade.handle(GitRepositoryHandler.TYPE_NAME, - repositoryName).fireHookEvent(type, context); + hookEventFacade.handle(id).fireHookEvent(type, context); } catch (Exception ex) @@ -191,7 +187,7 @@ public class GitReceiveHook implements PreReceiveHook, PostReceiveHook * * @throws IOException */ - private String resolveRepositoryName(Repository repository) throws IOException + private String resolveRepositoryId(Repository repository) throws IOException { File directory; @@ -204,7 +200,7 @@ public class GitReceiveHook implements PreReceiveHook, PostReceiveHook directory = repository.getWorkTree(); } - return RepositoryUtil.getRepositoryName(handler, directory); + return RepositoryUtil.getRepositoryId(handler, directory); } //~--- fields --------------------------------------------------------------- diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryHandlerTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryHandlerTest.java index d5201dca83..47ca08b597 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryHandlerTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryHandlerTest.java @@ -106,7 +106,7 @@ public class GitRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase { gitConfig.setRepositoryDirectory(new File("/path")); repositoryHandler.setConfig(gitConfig); - Repository repository = new Repository("id", "git", "Name"); + Repository repository = new Repository("id", "git", "Space", "Name"); File path = repositoryHandler.getDirectory(repository); assertEquals("/path/id", path.getAbsolutePath()); diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryPathMatcherTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryPathMatcherTest.java index 7adc4a6913..598d3b6400 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryPathMatcherTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryPathMatcherTest.java @@ -31,7 +31,9 @@ package sonia.scm.repository; import org.junit.Test; -import static org.junit.Assert.*; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; /** * Unit tests for {@link GitRepositoryPathMatcher}. @@ -45,18 +47,18 @@ public class GitRepositoryPathMatcherTest { @Test public void testIsPathMatching() { - assertFalse(pathMatcher.isPathMatching(repository("my-repo"), "my-repoo")); - assertFalse(pathMatcher.isPathMatching(repository("my"), "my-repo")); - assertFalse(pathMatcher.isPathMatching(repository("my"), "my-repo/with/path")); + assertFalse(pathMatcher.isPathMatching(repository("space", "my-repo"), "my-repoo")); + assertFalse(pathMatcher.isPathMatching(repository("space", "my"), "my-repo")); + assertFalse(pathMatcher.isPathMatching(repository("space", "my"), "my-repo/with/path")); - assertTrue(pathMatcher.isPathMatching(repository("my-repo"), "my-repo")); - assertTrue(pathMatcher.isPathMatching(repository("my-repo"), "my-repo.git")); - assertTrue(pathMatcher.isPathMatching(repository("my-repo"), "my-repo/with/path")); - assertTrue(pathMatcher.isPathMatching(repository("my-repo"), "my-repo.git/with/path")); + assertTrue(pathMatcher.isPathMatching(repository("space", "my-repo"), "my-repo")); + assertTrue(pathMatcher.isPathMatching(repository("space", "my-repo"), "my-repo.git")); + assertTrue(pathMatcher.isPathMatching(repository("space", "my-repo"), "my-repo/with/path")); + assertTrue(pathMatcher.isPathMatching(repository("space", "my-repo"), "my-repo.git/with/path")); } - private Repository repository(String name) { - return new Repository(name, GitRepositoryHandler.TYPE_NAME, name); + private Repository repository(String namespace, String name) { + return new Repository(name, GitRepositoryHandler.TYPE_NAME, namespace, name); } } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/AbstractRemoteCommandTestBase.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/AbstractRemoteCommandTestBase.java index a76d110561..e2a401bf7d 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/AbstractRemoteCommandTestBase.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/AbstractRemoteCommandTestBase.java @@ -38,34 +38,31 @@ package sonia.scm.repository.spi; import com.google.common.base.Charsets; import com.google.common.io.Files; import com.google.inject.Provider; - import org.eclipse.jgit.api.CommitCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.transport.ScmTransportProtocol; import org.eclipse.jgit.transport.Transport; - import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.rules.TemporaryFolder; - import sonia.scm.repository.Changeset; import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.Repository; import sonia.scm.user.User; import sonia.scm.user.UserTestData; -import static org.junit.Assert.*; - -import static org.mockito.Mockito.*; - -//~--- JDK imports ------------------------------------------------------------ - import java.io.File; import java.io.IOException; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra @@ -88,8 +85,8 @@ public class AbstractRemoteCommandTestBase outgoingDirectory = tempFolder.newFile("outgoing"); outgoingDirectory.delete(); - incomgingRepository = new Repository("1", "git", "incoming"); - outgoingRepository = new Repository("2", "git", "outgoing"); + incomgingRepository = new Repository("1", "git", "space", "incoming"); + outgoingRepository = new Repository("2", "git", "space", "outgoing"); incoming = Git.init().setDirectory(incomingDirectory).setBare(false).call(); outgoing = Git.init().setDirectory(outgoingDirectory).setBare(false).call(); diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/LfsBlobStoreFactoryTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/LfsBlobStoreFactoryTest.java index 2eb8968405..fe48e403c5 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/LfsBlobStoreFactoryTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/LfsBlobStoreFactoryTest.java @@ -35,14 +35,15 @@ package sonia.scm.web.lfs; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; -import static org.mockito.Matchers.matches; import org.mockito.Mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; import org.mockito.runners.MockitoJUnitRunner; import sonia.scm.repository.Repository; import sonia.scm.store.BlobStoreFactory; +import static org.mockito.Matchers.matches; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + /** * Unit tests for {@link LfsBlobStoreFactory}. * @@ -59,7 +60,7 @@ public class LfsBlobStoreFactoryTest { @Test public void getBlobStore() throws Exception { - lfsBlobStoreFactory.getLfsBlobStore(new Repository("the-id", "GIT", "the-name")); + lfsBlobStoreFactory.getLfsBlobStore(new Repository("the-id", "GIT", "space", "the-name")); // just make sure the right parameter is passed, as properly validating the return value is nearly impossible with // the return value (and should not be part of this test) diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/servlet/LfsServletFactoryTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/servlet/LfsServletFactoryTest.java index c670032089..74674cc9db 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/servlet/LfsServletFactoryTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/servlet/LfsServletFactoryTest.java @@ -7,8 +7,9 @@ import javax.servlet.http.HttpServletRequest; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * Created by omilke on 18.05.2017. @@ -18,14 +19,15 @@ public class LfsServletFactoryTest { @Test public void buildBaseUri() throws Exception { + String repositoryNamespace = "space"; String repositoryName = "git-lfs-demo"; - String result = LfsServletFactory.buildBaseUri(new Repository("", "GIT", repositoryName), RequestWithUri(repositoryName, true)); + String result = LfsServletFactory.buildBaseUri(new Repository("", "GIT", repositoryNamespace, repositoryName), RequestWithUri(repositoryName, true)); assertThat(result, is(equalTo("http://localhost:8081/scm/git/git-lfs-demo.git/info/lfs/objects/"))); //result will be with dot-gix suffix, ide - result = LfsServletFactory.buildBaseUri(new Repository("", "GIT", repositoryName), RequestWithUri(repositoryName, false)); + result = LfsServletFactory.buildBaseUri(new Repository("", "GIT", repositoryNamespace, repositoryName), RequestWithUri(repositoryName, false)); assertThat(result, is(equalTo("http://localhost:8081/scm/git/git-lfs-demo.git/info/lfs/objects/"))); } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgHookChangesetProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgHookChangesetProvider.java index 17c0816686..59ad0c3345 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgHookChangesetProvider.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgHookChangesetProvider.java @@ -34,20 +34,18 @@ package sonia.scm.repository.spi; //~--- non-JDK imports -------------------------------------------------------- import com.aragost.javahg.Repository; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import sonia.scm.repository.HgHookManager; import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.RepositoryHookType; import sonia.scm.repository.spi.javahg.HgLogChangesetCommand; import sonia.scm.web.HgUtil; -//~--- JDK imports ------------------------------------------------------------ - import java.io.File; +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra @@ -63,22 +61,12 @@ public class HgHookChangesetProvider implements HookChangesetProvider //~--- constructors --------------------------------------------------------- - /** - * Constructs ... - * - * - * @param handler - * @param repositoryName - * @param hookManager - * @param startRev - * @param type - */ public HgHookChangesetProvider(HgRepositoryHandler handler, - String repositoryName, HgHookManager hookManager, String startRev, + String id, HgHookManager hookManager, String startRev, RepositoryHookType type) { this.handler = handler; - this.repositoryName = repositoryName; + this.id = id; this.hookManager = hookManager; this.startRev = startRev; this.type = type; @@ -136,7 +124,7 @@ public class HgHookChangesetProvider implements HookChangesetProvider private Repository open() { File directory = handler.getConfig().getRepositoryDirectory(); - File repositoryDirectory = new File(directory, repositoryName); + File repositoryDirectory = new File(directory, id); // use HG_PENDING only for pre receive hooks boolean pending = type == RepositoryHookType.PRE_RECEIVE; @@ -155,7 +143,7 @@ public class HgHookChangesetProvider implements HookChangesetProvider private HgHookManager hookManager; /** Field description */ - private String repositoryName; + private String id; /** Field description */ private HookChangesetResponse response; diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgHookContextProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgHookContextProvider.java index dede59796c..5b354ecec4 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgHookContextProvider.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgHookContextProvider.java @@ -38,16 +38,16 @@ import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.RepositoryHookType; import sonia.scm.repository.api.HgHookBranchProvider; import sonia.scm.repository.api.HgHookMessageProvider; +import sonia.scm.repository.api.HgHookTagProvider; import sonia.scm.repository.api.HookBranchProvider; import sonia.scm.repository.api.HookFeature; import sonia.scm.repository.api.HookMessageProvider; - -//~--- JDK imports ------------------------------------------------------------ +import sonia.scm.repository.api.HookTagProvider; import java.util.EnumSet; import java.util.Set; -import sonia.scm.repository.api.HgHookTagProvider; -import sonia.scm.repository.api.HookTagProvider; + +//~--- JDK imports ------------------------------------------------------------ /** * Mercurial implementation of {@link HookContextProvider}. @@ -67,17 +67,16 @@ public class HgHookContextProvider extends HookContextProvider * Constructs a new instance. * * @param handler mercurial repository handler - * @param repositoryName name of changed repository + * @param namespaceAndName namespace and name of changed repository * @param hookManager mercurial hook manager * @param startRev start revision * @param type type of hook */ public HgHookContextProvider(HgRepositoryHandler handler, - String repositoryName, HgHookManager hookManager, String startRev, + String id, HgHookManager hookManager, String startRev, RepositoryHookType type) { - this.hookChangesetProvider = new HgHookChangesetProvider(handler, - repositoryName, hookManager, startRev, type); + this.hookChangesetProvider = new HgHookChangesetProvider(handler, id, hookManager, startRev, type); } //~--- get methods ---------------------------------------------------------- diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java index abbf09380a..4283519011 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java @@ -40,13 +40,10 @@ import com.google.common.io.Closeables; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; - import org.apache.shiro.SecurityUtils; import org.apache.shiro.subject.Subject; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import sonia.scm.repository.HgContext; import sonia.scm.repository.HgHookManager; import sonia.scm.repository.HgRepositoryHandler; @@ -62,19 +59,17 @@ import sonia.scm.security.Tokens; import sonia.scm.util.HttpUtil; import sonia.scm.util.Util; -//~--- JDK imports ------------------------------------------------------------ - -import java.io.IOException; -import java.io.PrintWriter; - -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +//~--- JDK imports ------------------------------------------------------------ /** * @@ -187,7 +182,7 @@ public class HgHookCallbackServlet extends HttpServlet if (m.matches()) { - String repositoryId = getRepositoryName(request); + String id = getRepositoryId(request); String type = m.group(1); String challenge = request.getParameter(PARAM_CHALLENGE); @@ -204,7 +199,7 @@ public class HgHookCallbackServlet extends HttpServlet authenticate(request, credentials); } - hookCallback(response, repositoryId, type, challenge, node); + hookCallback(response, id, type, challenge, node); } else if (logger.isDebugEnabled()) { @@ -227,13 +222,6 @@ public class HgHookCallbackServlet extends HttpServlet } } - /** - * Method description - * - * - * @param request - * @param credentials - */ private void authenticate(HttpServletRequest request, String credentials) { try @@ -270,18 +258,7 @@ public class HgHookCallbackServlet extends HttpServlet } } - /** - * Method description - * - * - * @param response - * @param repositoryName - * @param node - * @param type - * - * @throws IOException - */ - private void fireHook(HttpServletResponse response, String repositoryName, + private void fireHook(HttpServletResponse response, String id, String node, RepositoryHookType type) throws IOException { @@ -294,11 +271,10 @@ public class HgHookCallbackServlet extends HttpServlet contextProvider.get().setPending(true); } - context = new HgHookContextProvider(handler, repositoryName, hookManager, + context = new HgHookContextProvider(handler, id, hookManager, node, type); - hookEventFacade.handle(HgRepositoryHandler.TYPE_NAME, - repositoryName).fireHookEvent(type, context); + hookEventFacade.handle(id).fireHookEvent(type, context); printMessages(response, context); } @@ -306,7 +282,7 @@ public class HgHookCallbackServlet extends HttpServlet { if (logger.isErrorEnabled()) { - logger.error("could not find repository {}", repositoryName); + logger.error("could not find repository with id {}", id); if (logger.isTraceEnabled()) { @@ -322,22 +298,7 @@ public class HgHookCallbackServlet extends HttpServlet } } - /** - * Method description - * - * - * @param response - * @param repositoryName - * @param typeName - * @param challenge - * @param node - * - * @throws IOException - */ - private void hookCallback(HttpServletResponse response, - String repositoryName, String typeName, String challenge, String node) - throws IOException - { + private void hookCallback(HttpServletResponse response, String id, String typeName, String challenge, String node) throws IOException { if (hookManager.isAcceptAble(challenge)) { RepositoryHookType type = null; @@ -353,7 +314,7 @@ public class HgHookCallbackServlet extends HttpServlet if (type != null) { - fireHook(response, repositoryName, node, type); + fireHook(response, id, node, type); } else { @@ -403,12 +364,12 @@ public class HgHookCallbackServlet extends HttpServlet * Method description * * - * @param resonse + * @param response * @param context * * @throws IOException */ - private void printMessages(HttpServletResponse resonse, + private void printMessages(HttpServletResponse response, HgHookContextProvider context) throws IOException { @@ -420,7 +381,7 @@ public class HgHookCallbackServlet extends HttpServlet try { - writer = resonse.getWriter(); + writer = response.getWriter(); printMessages(writer, msgs); } @@ -506,9 +467,9 @@ public class HgHookCallbackServlet extends HttpServlet * * @return */ - private String getRepositoryName(HttpServletRequest request) + private String getRepositoryId(HttpServletRequest request) { - String name = null; + String id = null; String path = request.getParameter(PARAM_REPOSITORYPATH); if (Util.isNotEmpty(path)) @@ -520,11 +481,11 @@ public class HgHookCallbackServlet extends HttpServlet */ try { - name = RepositoryUtil.getRepositoryName(handler, path); + id = RepositoryUtil.getRepositoryId(handler, path); } catch (IOException ex) { - logger.error("could not find name of repository", ex); + logger.error("could not find namespace and name of repository", ex); } } else if (logger.isWarnEnabled()) @@ -532,7 +493,7 @@ public class HgHookCallbackServlet extends HttpServlet logger.warn("no repository path parameter found"); } - return name; + return id; } //~--- fields --------------------------------------------------------------- diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java index c5d62dc054..bd14a63b56 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java @@ -101,7 +101,7 @@ public class HgRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase { hgConfig.setPythonBinary("python"); repositoryHandler.setConfig(hgConfig); - Repository repository = new Repository("id", "git", "Name"); + Repository repository = new Repository("id", "git", "Space", "Name"); File path = repositoryHandler.getDirectory(repository); assertEquals("/path/id", path.getAbsolutePath()); diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/IncomingOutgoingTestBase.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/IncomingOutgoingTestBase.java index c45d0af2da..8dca8fdfe6 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/IncomingOutgoingTestBase.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/IncomingOutgoingTestBase.java @@ -41,14 +41,11 @@ import com.aragost.javahg.Repository; import com.aragost.javahg.RepositoryConfiguration; import com.aragost.javahg.commands.AddCommand; import com.aragost.javahg.commands.CommitCommand; - import com.google.common.base.Charsets; import com.google.common.io.Files; - import org.junit.Before; import org.junit.Rule; import org.junit.rules.TemporaryFolder; - import sonia.scm.AbstractTestBase; import sonia.scm.repository.HgConfig; import sonia.scm.repository.HgContext; @@ -58,15 +55,15 @@ import sonia.scm.user.User; import sonia.scm.user.UserTestData; import sonia.scm.util.MockUtil; -import static org.junit.Assert.*; - -import static org.mockito.Mockito.*; - -//~--- JDK imports ------------------------------------------------------------ - import java.io.File; import java.io.IOException; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra @@ -90,10 +87,8 @@ public abstract class IncomingOutgoingTestBase extends AbstractTestBase incomingDirectory = tempFolder.newFolder("incoming"); outgoingDirectory = tempFolder.newFolder("outgoing"); - incomingRepository = new sonia.scm.repository.Repository("1", "hg", - "incoming"); - outgoingRepository = new sonia.scm.repository.Repository("2", "hg", - "outgoing"); + incomingRepository = new sonia.scm.repository.Repository("1", "hg", "space", "incoming"); + outgoingRepository = new sonia.scm.repository.Repository("2", "hg", "space", "outgoing"); incoming = Repository.create(createConfig(temp), incomingDirectory); outgoing = Repository.create(createConfig(temp), outgoingDirectory); diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/web/HgHookCallbackServletTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/web/HgHookCallbackServletTest.java new file mode 100644 index 0000000000..a586962bb8 --- /dev/null +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/web/HgHookCallbackServletTest.java @@ -0,0 +1,41 @@ +package sonia.scm.web; + +import org.junit.Test; +import sonia.scm.repository.HgConfig; +import sonia.scm.repository.HgRepositoryHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; + +import static org.mockito.Matchers.anyInt; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static sonia.scm.web.HgHookCallbackServlet.PARAM_REPOSITORYPATH; + +public class HgHookCallbackServletTest { + + @Test + public void shouldExtractCorrectRepositoryId() throws ServletException, IOException { + HgRepositoryHandler handler = mock(HgRepositoryHandler.class); + HgHookCallbackServlet servlet = new HgHookCallbackServlet(null, handler, null, null); + HttpServletRequest request = mock(HttpServletRequest.class); + HttpServletResponse response = mock(HttpServletResponse.class); + HgConfig config = mock(HgConfig.class); + + when(request.getContextPath()).thenReturn("http://example.com/scm"); + when(request.getRequestURI()).thenReturn("http://example.com/scm/hook/hg/pretxnchangegroup"); + when(request.getParameter(PARAM_REPOSITORYPATH)).thenReturn("/tmp/hg/12345"); + + when(handler.getConfig()).thenReturn(config); + when(config.getRepositoryDirectory()).thenReturn(new File("/tmp/hg")); + + servlet.doPost(request, response); + + verify(response, never()).sendError(anyInt()); + } +} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnRepositoryHook.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnRepositoryHook.java index 1de3b2aecb..00958174a4 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnRepositoryHook.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnRepositoryHook.java @@ -37,7 +37,6 @@ package sonia.scm.repository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.tmatesoft.svn.core.SVNCancelException; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNErrorMessage; @@ -45,21 +44,19 @@ import org.tmatesoft.svn.core.SVNException; 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.repository.spi.AbstractSvnHookChangesetProvider; import sonia.scm.repository.spi.HookEventFacade; import sonia.scm.repository.spi.SvnHookContextProvider; import sonia.scm.repository.spi.SvnPostReceiveHookChangesetProvier; import sonia.scm.repository.spi.SvnPreReceiveHookChangesetProvier; import sonia.scm.util.AssertUtil; -import sonia.scm.util.IOUtil; import sonia.scm.util.Util; -//~--- JDK imports ------------------------------------------------------------ - import java.io.File; import java.io.IOException; +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra @@ -166,12 +163,10 @@ public class SvnRepositoryHook implements FSHook { try { - String name = getRepositoryName(directory); - - name = IOUtil.trimSeperatorChars(name); + String id = getRepositoryId(directory); //J- - hookEventFacade.handle(SvnRepositoryHandler.TYPE_NAME, name) + hookEventFacade.handle(id) .fireHookEvent( changesetProvider.getType(), new SvnHookContextProvider(changesetProvider) @@ -202,11 +197,11 @@ public class SvnRepositoryHook implements FSHook * * @throws IOException */ - private String getRepositoryName(File directory) throws IOException + private String getRepositoryId(File directory) throws IOException { AssertUtil.assertIsNotNull(directory); - return RepositoryUtil.getRepositoryName(handler, directory); + return RepositoryUtil.getRepositoryId(handler, directory); } //~--- fields --------------------------------------------------------------- diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/SvnRepositoryHandlerTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/SvnRepositoryHandlerTest.java index c7cd78dc75..f2c53e413c 100644 --- a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/SvnRepositoryHandlerTest.java +++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/SvnRepositoryHandlerTest.java @@ -113,7 +113,7 @@ public class SvnRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase { svnConfig.setRepositoryDirectory(new File("/path")); repositoryHandler.setConfig(svnConfig); - Repository repository = new Repository("id", "svn", "Name"); + Repository repository = new Repository("id", "svn", "Space", "Name"); File path = repositoryHandler.getDirectory(repository); assertEquals("/path/id", path.getAbsolutePath()); diff --git a/scm-test/src/main/java/sonia/scm/repository/DummyRepositoryHandler.java b/scm-test/src/main/java/sonia/scm/repository/DummyRepositoryHandler.java index fa2cc1b0fd..870127b14e 100644 --- a/scm-test/src/main/java/sonia/scm/repository/DummyRepositoryHandler.java +++ b/scm-test/src/main/java/sonia/scm/repository/DummyRepositoryHandler.java @@ -56,7 +56,7 @@ public class DummyRepositoryHandler public static final Type TYPE = new Type(TYPE_NAME, TYPE_DISPLAYNAME); - private Set existingRepoNames = new HashSet<>(); + private final Set existingRepoNames = new HashSet<>(); public DummyRepositoryHandler(ConfigurationStoreFactory storeFactory) { super(storeFactory, new DefaultFileSystem()); @@ -69,12 +69,12 @@ public class DummyRepositoryHandler @Override - protected void create(Repository repository, File directory) - throws RepositoryException { - if (existingRepoNames.contains(repository.getNamespace() + repository.getName())) { + protected void create(Repository repository, File directory) throws RepositoryException { + String key = repository.getNamespace() + "/" + repository.getName(); + if (existingRepoNames.contains(key)) { throw new RepositoryAlreadyExistsException("Repo exists"); } else { - existingRepoNames.add(repository.getNamespace() + repository.getName()); + existingRepoNames.add(key); } } diff --git a/scm-test/src/main/java/sonia/scm/repository/RepositoryBuilder.java b/scm-test/src/main/java/sonia/scm/repository/RepositoryBuilder.java new file mode 100644 index 0000000000..9c8ceb4762 --- /dev/null +++ b/scm-test/src/main/java/sonia/scm/repository/RepositoryBuilder.java @@ -0,0 +1,49 @@ +package sonia.scm.repository; + +public class RepositoryBuilder { + + private String id = "id-" + ++nextID; + private String contact = "test@example.com"; + private String description = ""; + private String namespace = "test"; + private String name = "name"; + private String type = "git"; + + private static int nextID = 0; + + public RepositoryBuilder type(String type) { + this.type = type; + return this; + } + + public RepositoryBuilder contact(String contact) { + this.contact = contact; + return this; + } + + public RepositoryBuilder namespace(String namespace) { + this.namespace = namespace; + return this; + } + + public RepositoryBuilder name(String name) { + this.name = name; + return this; + } + + public RepositoryBuilder description(String description) { + this.description = description; + return this; + } + + public Repository build() { + Repository repository = new Repository(); + repository.setId(id); + repository.setType(type); + repository.setContact(contact); + repository.setNamespace(namespace); + repository.setName(name); + repository.setDescription(description); + return repository; + } +} diff --git a/scm-test/src/main/java/sonia/scm/repository/RepositoryTestData.java b/scm-test/src/main/java/sonia/scm/repository/RepositoryTestData.java index 65fad6f80d..b81c39ca00 100644 --- a/scm-test/src/main/java/sonia/scm/repository/RepositoryTestData.java +++ b/scm-test/src/main/java/sonia/scm/repository/RepositoryTestData.java @@ -6,13 +6,13 @@ * 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. + * 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. + * 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. + * 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 @@ -26,26 +26,22 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * http://bitbucket.org/sdorra/scm-manager - * */ - package sonia.scm.repository; -public final class RepositoryTestData -{ +public final class RepositoryTestData { - private RepositoryTestData() {} + private RepositoryTestData() { + } - public static Repository create42Puzzle() - { + public static Repository create42Puzzle() { return create42Puzzle(DummyRepositoryHandler.TYPE_NAME); } - public static Repository create42Puzzle(String type) - { - return new Builder() + public static Repository create42Puzzle(String type) { + return new RepositoryBuilder() .type(type) .contact("douglas.adams@hitchhiker.com") .name("42Puzzle") @@ -53,15 +49,13 @@ public final class RepositoryTestData .build(); } - public static Repository createHappyVerticalPeopleTransporter() - { + public static Repository createHappyVerticalPeopleTransporter() { return createHappyVerticalPeopleTransporter( DummyRepositoryHandler.TYPE_NAME); } - public static Repository createHappyVerticalPeopleTransporter(String type) - { - return new Builder() + public static Repository createHappyVerticalPeopleTransporter(String type) { + return new RepositoryBuilder() .type(type) .contact("zaphod.beeblebrox@hitchhiker.com") .name("happyVerticalPeopleTransporter") @@ -69,14 +63,12 @@ public final class RepositoryTestData .build(); } - public static Repository createHeartOfGold() - { + public static Repository createHeartOfGold() { return createHeartOfGold(DummyRepositoryHandler.TYPE_NAME); } - public static Repository createHeartOfGold(String type) - { - return new Builder() + public static Repository createHeartOfGold(String type) { + return new RepositoryBuilder() .type(type) .contact("zaphod.beeblebrox@hitchhiker.com") .name("HeartOfGold") @@ -85,51 +77,17 @@ public final class RepositoryTestData .build(); } - public static Repository createRestaurantAtTheEndOfTheUniverse() - { + public static Repository createRestaurantAtTheEndOfTheUniverse() { return createRestaurantAtTheEndOfTheUniverse( DummyRepositoryHandler.TYPE_NAME); } - public static Repository createRestaurantAtTheEndOfTheUniverse(String type) - { - return new Builder() + public static Repository createRestaurantAtTheEndOfTheUniverse(String type) { + return new RepositoryBuilder() .type(type) .contact("douglas.adams@hitchhiker.com") .name("RestaurantAtTheEndOfTheUniverse") .description("The Restaurant at the End of the Universe") .build(); } - - private static class Builder { - private static int nextID = 0; - Repository repository = new Repository(); - { - repository.setId("ID-" + ++nextID); - } - - Builder type(String type) { - repository.setType(type); - return this; - } - - Builder contact(String contact) { - repository.setContact(contact); - return this; - } - - Builder name(String name) { - repository.setName(name); - return this; - } - - Builder description(String description) { - repository.setDescription(description); - return this; - } - - public Repository build() { - return repository; - } - } } diff --git a/scm-test/src/main/java/sonia/scm/repository/SimpleRepositoryHandlerTestBase.java b/scm-test/src/main/java/sonia/scm/repository/SimpleRepositoryHandlerTestBase.java index 07a9495588..680ac83dd9 100644 --- a/scm-test/src/main/java/sonia/scm/repository/SimpleRepositoryHandlerTestBase.java +++ b/scm-test/src/main/java/sonia/scm/repository/SimpleRepositoryHandlerTestBase.java @@ -40,9 +40,10 @@ import sonia.scm.store.InMemoryConfigurationStoreFactory; import sonia.scm.util.IOUtil; import java.io.File; -import java.io.IOException; -import static org.junit.Assert.*; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; //~--- JDK imports ------------------------------------------------------------ @@ -59,19 +60,12 @@ public abstract class SimpleRepositoryHandlerTestBase extends AbstractTestBase { ConfigurationStoreFactory factory, File directory); @Test - public void testCreate() throws RepositoryException, IOException { - createRepository(); - } - - @Test(expected = RepositoryAlreadyExistsException.class) - public void testCreateExisitingRepository() - throws RepositoryException, IOException { - createRepository(); + public void testCreate() throws RepositoryException { createRepository(); } @Test - public void testCreateResourcePath() throws RepositoryException, IOException { + public void testCreateResourcePath() throws RepositoryException { Repository repository = createRepository(); String path = handler.createResourcePath(repository); @@ -81,7 +75,7 @@ public abstract class SimpleRepositoryHandlerTestBase extends AbstractTestBase { } @Test - public void testDelete() throws RepositoryException, IOException { + public void testDelete() throws RepositoryException { Repository repository = createRepository(); handler.delete(repository); @@ -92,7 +86,7 @@ public abstract class SimpleRepositoryHandlerTestBase extends AbstractTestBase { } @Override - protected void postSetUp() throws Exception { + protected void postSetUp() { InMemoryConfigurationStoreFactory storeFactory = new InMemoryConfigurationStoreFactory(); baseDirectory = new File(contextProvider.getBaseDirectory(), "repositories"); IOUtil.mkdirs(baseDirectory); @@ -106,7 +100,7 @@ public abstract class SimpleRepositoryHandlerTestBase extends AbstractTestBase { } } - private Repository createRepository() throws RepositoryException, IOException { + private Repository createRepository() throws RepositoryException { Repository repository = RepositoryTestData.createHeartOfGold(); handler.create(repository); @@ -120,7 +114,6 @@ public abstract class SimpleRepositoryHandlerTestBase extends AbstractTestBase { return repository; } - protected File baseDirectory; private RepositoryHandler handler; diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryImportResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryImportResource.java index f336bbb6e7..4d8fba1c26 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryImportResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryImportResource.java @@ -543,7 +543,8 @@ public class RepositoryImportResource try { - repository = new Repository(null, type, name); + // TODO #8783 +// repository = new Repository(null, type, name); manager.create(repository); } catch (RepositoryAlreadyExistsException ex) @@ -738,7 +739,8 @@ public class RepositoryImportResource { for (String repositoryName : repositoryNames) { - Repository repository = manager.get(type, repositoryName); + // TODO #8783 + Repository repository = null; //manager.get(type, repositoryName); if (repository != null) { diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java index bf974b2fa4..5c9618860b 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java @@ -561,42 +561,6 @@ public class RepositoryResource extends AbstractManagerResource 0) { + String type = uri.substring(0, typeSeparator); + + uri = uri.substring(typeSeparator + 1); + repository = getFromTypeAndUri(type, uri); + } + + return repository; + } + + private Repository getFromTypeAndUri(String type, String uri) { if (Strings.isNullOrEmpty(type)) { throw new ArgumentIsInvalidException("argument type is required"); } @@ -362,27 +395,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { return repository; } - @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); - Repository repository = null; - - if (typeSeperator > 0) { - String type = uri.substring(0, typeSeperator); - - uri = uri.substring(typeSeperator + 1); - repository = getFromTypeAndUri(type, uri); - } - - return repository; - } - @Override public RepositoryHandler getHandler(String type) { return handlerMap.get(type); diff --git a/scm-webapp/src/main/java/sonia/scm/repository/RepositoryMatcher.java b/scm-webapp/src/main/java/sonia/scm/repository/RepositoryMatcher.java index d0ad30e84f..8cb3871047 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/RepositoryMatcher.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/RepositoryMatcher.java @@ -32,14 +32,15 @@ package sonia.scm.repository; -import com.google.common.collect.Maps; -import java.util.Map; -import java.util.Set; -import javax.inject.Inject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import sonia.scm.util.HttpUtil; -import sonia.scm.util.Util; + import com.google.common.collect.Maps; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import sonia.scm.util.HttpUtil; + import sonia.scm.util.Util; + + import javax.inject.Inject; + import java.util.Map; + import java.util.Set; /** * RepositoryMatcher is able to check if a repository matches the requested path. @@ -83,9 +84,24 @@ public final class RepositoryMatcher { } private boolean isPathMatching(Repository repository, String path) { - return getPathMatcherForType(repository.getType()).isPathMatching(repository, path); + + String namespace = extractNamespace(path); + String remainingPath = path.substring(namespace.length() + 1); + + return getPathMatcherForType(repository.getType()).isPathMatching(repository, remainingPath); } - + + private String extractNamespace(String path) { + if (path.startsWith(HttpUtil.SEPARATOR_PATH)) { + path = path.substring(1); + } + int namespaceSeparator = path.indexOf(HttpUtil.SEPARATOR_PATH); + if (namespaceSeparator > 0) { + return path.substring(0, namespaceSeparator); + } + throw new IllegalArgumentException("no namespace in path " + path); + } + private RepositoryPathMatcher getPathMatcherForType(String type) { RepositoryPathMatcher pathMatcher = pathMatchers.get(type); if (pathMatcher == null) { diff --git a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerPerfTest.java b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerPerfTest.java index 81059c1247..665c54c9e1 100644 --- a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerPerfTest.java +++ b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerPerfTest.java @@ -34,7 +34,11 @@ import com.google.common.base.Stopwatch; import com.google.common.collect.ImmutableSet; import com.google.inject.Provider; import org.apache.shiro.SecurityUtils; -import org.apache.shiro.authc.*; +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.SimpleAuthenticationInfo; +import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.mgt.DefaultSecurityManager; @@ -57,7 +61,12 @@ import sonia.scm.security.DefaultKeyGenerator; import sonia.scm.security.KeyGenerator; import sonia.scm.user.UserTestData; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; import static org.mockito.Mockito.mock; @@ -174,8 +183,8 @@ private long calculateAverage(List times) { when(repositoryDAO.getAll()).thenReturn(repositories.values()); } - private Repository createTestRepository(int number){ - Repository repository = new Repository(keyGenerator.createKey(), REPOSITORY_TYPE, "repo-" + number); + private Repository createTestRepository(int number) { + Repository repository = new Repository(keyGenerator.createKey(), REPOSITORY_TYPE, "namespace", "repo-" + number); repository.getPermissions().add(new Permission("trillian", PermissionType.READ)); return repository; } diff --git a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java index 7bbdd657ee..ae652dddf6 100644 --- a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java +++ b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java @@ -58,11 +58,26 @@ import sonia.scm.store.ConfigurationStoreFactory; import sonia.scm.store.JAXBConfigurationStoreFactory; import java.io.IOException; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.Stack; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; //~--- JDK imports ------------------------------------------------------------ @@ -84,12 +99,8 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase keys = new Stack<>(); @@ -320,12 +264,6 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase mockedNamespace); return new DefaultRepositoryManager(configuration, contextProvider, keyGenerator, repositoryDAO, handlerSet, createRepositoryMatcher(), namespaceStrategy); diff --git a/scm-webapp/src/test/java/sonia/scm/repository/RepositoryMatcherTest.java b/scm-webapp/src/test/java/sonia/scm/repository/RepositoryMatcherTest.java index c832bb8691..1d6371074c 100644 --- a/scm-webapp/src/test/java/sonia/scm/repository/RepositoryMatcherTest.java +++ b/scm-webapp/src/test/java/sonia/scm/repository/RepositoryMatcherTest.java @@ -31,10 +31,13 @@ package sonia.scm.repository; import com.google.common.collect.Sets; -import java.util.Set; -import org.junit.Test; -import static org.junit.Assert.*; import org.junit.Before; +import org.junit.Test; + +import java.util.Set; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; /** * Unit tests for {@link RepositoryMatcher}. @@ -54,11 +57,11 @@ public class RepositoryMatcherTest { @Test public void testMatches() { - assertFalse(matcher.matches(repository("hg", "scm"), "hg", "scm-test/ka")); - assertFalse(matcher.matches(repository("git", "scm-test"), "hg", "scm-test")); + assertFalse(matcher.matches(repository("hg", "scm"), "hg", "namespace/scm-test/ka")); + assertFalse(matcher.matches(repository("git", "scm-test"), "hg", "namespace/scm-test")); - assertTrue(matcher.matches(repository("hg", "scm-test"), "hg", "scm-test/ka")); - assertTrue(matcher.matches(repository("hg", "scm-test"), "hg", "scm-test")); + assertTrue(matcher.matches(repository("hg", "scm-test"), "hg", "namespace/scm-test/ka")); + assertTrue(matcher.matches(repository("hg", "scm-test"), "hg", "namespace/scm-test")); } @Test @@ -68,7 +71,7 @@ public class RepositoryMatcherTest { } private Repository repository(String type, String name) { - return new Repository(type + "-" + name, type, name); + return new Repository(type + "-" + name, type, "namespace", name); } private static class AbcRepositoryPathMatcher implements RepositoryPathMatcher { From 5db74e08cbf3fdc64df56d25ae65eb07dad8d362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Wed, 11 Jul 2018 08:08:46 +0200 Subject: [PATCH 07/21] Fix git directory name --- .../sonia/scm/web/GitRepositoryResolver.java | 45 ++++++++----------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitRepositoryResolver.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitRepositoryResolver.java index 2ddf4b3de9..76e742a71a 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitRepositoryResolver.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitRepositoryResolver.java @@ -36,8 +36,8 @@ package sonia.scm.web; //~--- non-JDK imports -------------------------------------------------------- import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; import com.google.inject.Inject; - import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryCache; @@ -46,19 +46,17 @@ import org.eclipse.jgit.transport.resolver.RepositoryResolver; import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; import org.eclipse.jgit.util.FS; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import sonia.scm.repository.GitConfig; import sonia.scm.repository.GitRepositoryHandler; +import sonia.scm.repository.RepositoryProvider; -//~--- JDK imports ------------------------------------------------------------ - +import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; -import javax.servlet.http.HttpServletRequest; +//~--- JDK imports ------------------------------------------------------------ /** * @@ -72,17 +70,11 @@ public class GitRepositoryResolver implements RepositoryResolver Date: Wed, 11 Jul 2018 08:25:06 +0200 Subject: [PATCH 08/21] Correct sequence of setting and reading namespace for new repository --- .../repository/DefaultRepositoryManager.java | 7 +- .../DefaultRepositoryManagerTest.java | 73 ++++++++++--------- 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java index 07bff4e999..c644034df9 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java @@ -130,9 +130,13 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { public void create(Repository repository, boolean initRepository) throws RepositoryException { - logger.info("create repository {} of type {}", repository.getNamespaceAndName(), repository.getType()); + logger.info("create repository {} of type {}", repository.getName(), repository.getType()); RepositoryPermissions.create().check(); + + repository.setNamespace(namespaceStrategy.getNamespace()); + logger.info("setting namespace of new repository {} to {}", repository.getName(), repository.getNamespace()); + AssertUtil.assertIsValid(repository); if (repositoryDAO.contains(repository.getNamespaceAndName())) { @@ -141,7 +145,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager { repository.setId(keyGenerator.createKey()); repository.setCreationDate(System.currentTimeMillis()); - repository.setNamespace(namespaceStrategy.getNamespace()); if (initRepository) { getHandler(repository).create(repository); diff --git a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java index ae652dddf6..e76d2af7b3 100644 --- a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java +++ b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java @@ -57,7 +57,6 @@ import sonia.scm.security.KeyGenerator; import sonia.scm.store.ConfigurationStoreFactory; import sonia.scm.store.JAXBConfigurationStoreFactory; -import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -102,7 +101,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase keys = new Stack<>(); @@ -265,7 +264,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBaseemptySet()); } - private Repository createRepository(Repository repository) throws RepositoryException, IOException { + private Repository createRepository(Repository repository) throws RepositoryException { manager.create(repository); assertNotNull(repository.getId()); assertNotNull(manager.get(repository.getId())); @@ -538,17 +545,17 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase manager, Repository repository) - throws RepositoryException, IOException { + throws RepositoryException { String id = repository.getId(); From 8391e75a159b0452718f70d28fc9f0f83afe58e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Wed, 11 Jul 2018 10:14:00 +0200 Subject: [PATCH 09/21] Correct servlet paths for svn requests --- .../src/main/java/sonia/scm/web/SvnDAVServlet.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java index db22857595..c811179255 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVServlet.java @@ -37,13 +37,10 @@ package sonia.scm.web; import com.google.inject.Inject; import com.google.inject.Singleton; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - 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.RepositoryProvider; import sonia.scm.repository.RepositoryRequestListenerUtil; @@ -51,14 +48,13 @@ import sonia.scm.repository.SvnRepositoryHandler; import sonia.scm.util.AssertUtil; import sonia.scm.util.HttpUtil; -//~--- 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; +import java.io.IOException; + +//~--- JDK imports ------------------------------------------------------------ /** * @@ -224,7 +220,7 @@ public class SvnDAVServlet extends DAVServlet pathInfo = pathInfo.substring(1); } - pathInfo = pathInfo.substring(repository.getName().length()); + pathInfo = pathInfo.substring(repository.getNamespace().length() + 1 + repository.getName().length()); } return pathInfo; @@ -249,7 +245,7 @@ public class SvnDAVServlet extends DAVServlet servletPath = servletPath.concat(HttpUtil.SEPARATOR_PATH); } - servletPath = servletPath.concat(repository.getName()); + servletPath = servletPath + repository.getNamespace() + "/" + repository.getName(); } return servletPath; From 53f3264f6e77afc71402dfe3cce77e287f90c9ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Wed, 11 Jul 2018 12:53:48 +0200 Subject: [PATCH 10/21] Correct repository name for hg --- .../main/java/sonia/scm/web/HgCGIServlet.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java index e00304c977..6cb4d523f0 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java @@ -39,10 +39,8 @@ import com.google.common.base.Stopwatch; import com.google.common.base.Strings; import com.google.inject.Inject; import com.google.inject.Singleton; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import sonia.scm.SCMContext; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.HgConfig; @@ -60,19 +58,17 @@ import sonia.scm.web.cgi.CGIExecutor; import sonia.scm.web.cgi.CGIExecutorFactory; import sonia.scm.web.cgi.EnvList; -//~--- JDK imports ------------------------------------------------------------ - -import java.io.File; -import java.io.IOException; -import java.util.Base64; - -import java.util.Enumeration; - import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import java.io.File; +import java.io.IOException; +import java.util.Base64; +import java.util.Enumeration; + +//~--- JDK imports ------------------------------------------------------------ /** * @@ -305,7 +301,7 @@ public class HgCGIServlet extends HttpServlet executor.setExceptionHandler(exceptionHandler); executor.setStatusCodeHandler(exceptionHandler); executor.setContentLengthWorkaround(true); - executor.getEnvironment().set(ENV_REPOSITORY_NAME, name); + executor.getEnvironment().set(ENV_REPOSITORY_NAME, repository.getNamespace() + "/" + repository.getName()); executor.getEnvironment().set(ENV_REPOSITORY_PATH, directory.getAbsolutePath()); From 450f0cd6624733084a4eb01c13cd67cce7f1ba22 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Fri, 13 Jul 2018 11:30:37 +0200 Subject: [PATCH 11/21] improve logging --- .../AbstractSimpleRepositoryHandler.java | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java b/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java index 2809069913..aa28403116 100644 --- a/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java +++ b/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java @@ -97,11 +97,7 @@ public abstract class AbstractSimpleRepositoryHandler Date: Fri, 13 Jul 2018 11:43:41 +0200 Subject: [PATCH 12/21] added javadoc and unit test --- .../java/sonia/scm/repository/Repository.java | 6 ++---- .../main/java/sonia/scm/util/HttpUtil.java | 14 ++++++++++--- .../java/sonia/scm/util/HttpUtilTest.java | 20 +++++++++++++++---- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/Repository.java b/scm-core/src/main/java/sonia/scm/repository/Repository.java index b2d99c85e1..44841893e7 100644 --- a/scm-core/src/main/java/sonia/scm/repository/Repository.java +++ b/scm-core/src/main/java/sonia/scm/repository/Repository.java @@ -59,7 +59,7 @@ import java.util.List; * @author Sebastian Sdorra */ @StaticPermissions( - value = "repository", + value = "repository", permissions = {"read", "write", "modify", "delete", "healthCheck"} ) @XmlAccessorType(XmlAccessType.FIELD) @@ -356,9 +356,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per * @since 1.17 */ public String createUrl(String baseUrl) { - String url = HttpUtil.append(baseUrl, type); - - return HttpUtil.concatenate(url, namespace, name); + return HttpUtil.concatenate(baseUrl, type, namespace, name); } /** diff --git a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java index 99de58023e..30995a0b3c 100644 --- a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java +++ b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java @@ -82,9 +82,9 @@ public final class HttpUtil /** * Name of bearer authentication cookie. - * + * * TODO find a better place - * + * * @since 2.0.0 */ public static final String COOKIE_BEARER_AUTHENTICATION = "X-Bearer-Token"; @@ -97,7 +97,7 @@ public final class HttpUtil * @since 2.0.0 */ public static final String HEADER_AUTHORIZATION = "Authorization"; - + /** * content-length header * @since 1.46 @@ -248,6 +248,14 @@ public final class HttpUtil //~--- methods -------------------------------------------------------------- + /** + * Joins all path elements together separated by {@code {@link #SEPARATOR_PATH}}. + * + * @param pathElements path elements + * + * @return concatenated path + * @since 2.0.0 + */ public static String concatenate(String... pathElements) { return Arrays.stream(pathElements).reduce(HttpUtil::append).orElse(""); } diff --git a/scm-core/src/test/java/sonia/scm/util/HttpUtilTest.java b/scm-core/src/test/java/sonia/scm/util/HttpUtilTest.java index b85221f8c8..5e6fa3e10e 100644 --- a/scm-core/src/test/java/sonia/scm/util/HttpUtilTest.java +++ b/scm-core/src/test/java/sonia/scm/util/HttpUtilTest.java @@ -54,6 +54,18 @@ import javax.servlet.http.HttpServletRequest; public class HttpUtilTest { + @Test + public void concatenateTest() { + assertEquals( + "/scm/git/hitchhiker/tricia", + HttpUtil.concatenate("/scm", "git", "hitchhiker", "tricia") + ); + assertEquals( + "scm/git/hitchhiker/tricia", + HttpUtil.concatenate("scm", "git", "hitchhiker", "tricia") + ); + } + /** * Method description * @@ -63,19 +75,19 @@ public class HttpUtilTest { //J- assertEquals( - "http://www.scm-manager/scm/test", + "http://www.scm-manager/scm/test", HttpUtil.append("http://www.scm-manager/scm/", "test") ); assertEquals( - "http://www.scm-manager/scm/test", + "http://www.scm-manager/scm/test", HttpUtil.append("http://www.scm-manager/scm", "test") ); assertEquals( - "http://www.scm-manager/scm/test", + "http://www.scm-manager/scm/test", HttpUtil.append("http://www.scm-manager/scm", "/test") ); assertEquals( - "http://www.scm-manager/scm/test", + "http://www.scm-manager/scm/test", HttpUtil.append("http://www.scm-manager/scm/", "/test") ); //J+ From 31ca22fe47cfd914b7a277011da5ad054760c8d6 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Fri, 13 Jul 2018 11:49:37 +0200 Subject: [PATCH 13/21] removed X suffix --- .../repository/xml/XmlRepositoryDatabase.java | 20 +++++----- .../xml/XmlRepositoryMapAdapter.java | 40 +++---------------- 2 files changed, 16 insertions(+), 44 deletions(-) diff --git a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDatabase.java b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDatabase.java index 1c82b07f50..93be611213 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDatabase.java +++ b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDatabase.java @@ -63,25 +63,25 @@ public class XmlRepositoryDatabase implements XmlDatabase lastModified = c; } - static String createKeyX(NamespaceAndName namespaceAndName) + static String createKey(NamespaceAndName namespaceAndName) { return namespaceAndName.getNamespace() + ":" + namespaceAndName.getName(); } - static String createKeyX(Repository repository) + static String createKey(Repository repository) { - return createKeyX(repository.getNamespaceAndName()); + return createKey(repository.getNamespaceAndName()); } @Override public void add(Repository repository) { - repositoryMap.put(createKeyX(repository), repository); + repositoryMap.put(createKey(repository), repository); } public boolean contains(NamespaceAndName namespaceAndName) { - return repositoryMap.containsKey(createKeyX(namespaceAndName)); + return repositoryMap.containsKey(createKey(namespaceAndName)); } @Override @@ -92,12 +92,12 @@ public class XmlRepositoryDatabase implements XmlDatabase public boolean contains(Repository repository) { - return repositoryMap.containsKey(createKeyX(repository)); + return repositoryMap.containsKey(createKey(repository)); } - public void removeX(Repository repository) + public void remove(Repository repository) { - repositoryMap.remove(createKeyX(repository)); + repositoryMap.remove(createKey(repository)); } @Override @@ -105,7 +105,7 @@ public class XmlRepositoryDatabase implements XmlDatabase { Repository r = get(id); - removeX(r); + remove(r); return r; } @@ -120,7 +120,7 @@ public class XmlRepositoryDatabase implements XmlDatabase public Repository get(NamespaceAndName namespaceAndName) { - return repositoryMap.get(createKeyX(namespaceAndName)); + return repositoryMap.get(createKey(namespaceAndName)); } /** diff --git a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryMapAdapter.java b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryMapAdapter.java index 4706c64f62..4d6686dfb2 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryMapAdapter.java +++ b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryMapAdapter.java @@ -47,47 +47,19 @@ import java.util.Map; * * @author Sebastian Sdorra */ -public class XmlRepositoryMapAdapter - extends XmlAdapter> -{ +public class XmlRepositoryMapAdapter extends XmlAdapter> { - /** - * Method description - * - * - * @param repositoryMap - * - * @return - * - * @throws Exception - */ @Override - public XmlRepositoryList marshal(Map repositoryMap) - throws Exception - { + public XmlRepositoryList marshal(Map repositoryMap) { return new XmlRepositoryList(repositoryMap); } - /** - * Method description - * - * - * @param repositories - * - * @return - * - * @throws Exception - */ @Override - public Map unmarshal(XmlRepositoryList repositories) - throws Exception - { - Map repositoryMap = new LinkedHashMap(); + public Map unmarshal(XmlRepositoryList repositories) { + Map repositoryMap = new LinkedHashMap<>(); - for (Repository repository : repositories) - { - repositoryMap.put(XmlRepositoryDatabase.createKeyX(repository), + for (Repository repository : repositories) { + repositoryMap.put(XmlRepositoryDatabase.createKey(repository), repository); } From 82da801280a8a4bf36fadacd7f289dd216c48ca1 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Fri, 13 Jul 2018 12:10:19 +0200 Subject: [PATCH 14/21] improve DefaultNamespaceStrategy, added tests and javadoc --- .../repository/DefaultNamespaceStrategy.java | 11 ++++----- .../DefaultNamespaceStrategyTest.java | 24 +++++++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 scm-webapp/src/test/java/sonia/scm/repository/DefaultNamespaceStrategyTest.java diff --git a/scm-webapp/src/main/java/sonia/scm/repository/DefaultNamespaceStrategy.java b/scm-webapp/src/main/java/sonia/scm/repository/DefaultNamespaceStrategy.java index e68d03909b..9cf2c8ab20 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/DefaultNamespaceStrategy.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/DefaultNamespaceStrategy.java @@ -1,18 +1,17 @@ package sonia.scm.repository; import org.apache.shiro.SecurityUtils; -import org.apache.shiro.subject.Subject; import sonia.scm.plugin.Extension; -import sonia.scm.user.User; - +/** + * The DefaultNamespaceStrategy returns the username of the currently logged in user as namespace. + * @since 2.0.0 + */ @Extension public class DefaultNamespaceStrategy implements NamespaceStrategy { @Override public String getNamespace() { - Subject subject = SecurityUtils.getSubject(); - String displayName = subject.getPrincipals().oneByType(User.class).getName(); - return displayName; + return SecurityUtils.getSubject().getPrincipal().toString(); } } diff --git a/scm-webapp/src/test/java/sonia/scm/repository/DefaultNamespaceStrategyTest.java b/scm-webapp/src/test/java/sonia/scm/repository/DefaultNamespaceStrategyTest.java new file mode 100644 index 0000000000..dc40d1c1cb --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/repository/DefaultNamespaceStrategyTest.java @@ -0,0 +1,24 @@ +package sonia.scm.repository; + +import com.github.sdorra.shiro.ShiroRule; +import com.github.sdorra.shiro.SubjectAware; +import org.junit.Rule; +import org.junit.Test; + +import static org.junit.Assert.*; + +@SubjectAware(configuration = "classpath:sonia/scm/shiro-001.ini") +public class DefaultNamespaceStrategyTest { + + @Rule + public ShiroRule shiroRule = new ShiroRule(); + + private DefaultNamespaceStrategy namespaceStrategy = new DefaultNamespaceStrategy(); + + @Test + @SubjectAware(username = "trillian", password = "secret") + public void testNamespaceStrategy() { + assertEquals("trillian", namespaceStrategy.getNamespace()); + } + +} From aad578fec06f43701a6e206000b3ed7731187926 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 16 Jul 2018 11:25:34 +0200 Subject: [PATCH 15/21] fail durring build, if guava eventbus annotations are used instead of legman annotations --- pom.xml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8d3b3fb0b2..d32294fa33 100644 --- a/pom.xml +++ b/pom.xml @@ -225,6 +225,23 @@ + + com.github.legman + legman-maven-plugin + ${legman.version} + + true + + + + process-classes + + guava-migration-check + + + + + org.apache.maven.plugins maven-compiler-plugin @@ -513,7 +530,7 @@ 4.0 - 1.2.0 + 1.3.0 9.2.10.v20150310 From 1e37dfb3a73e648dd381e05da0aaf63569e244e6 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 16 Jul 2018 11:26:00 +0200 Subject: [PATCH 16/21] use subscribe annotation of legman instead of guava eventbus --- .../java/sonia/scm/repository/GitRepositoryModifyListener.java | 2 +- .../src/main/java/sonia/scm/web/lfs/LfsStoreRemoveListener.java | 2 +- .../java/sonia/scm/repository/LastModifiedUpdateListener.java | 2 +- .../sonia/scm/security/AuthorizationChangedEventProducer.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryModifyListener.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryModifyListener.java index db2b7b09ec..1cbcdc35bf 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryModifyListener.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryModifyListener.java @@ -30,9 +30,9 @@ */ package sonia.scm.repository; +import com.github.legman.Subscribe; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Objects; -import com.google.common.eventbus.Subscribe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.EagerSingleton; diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/lfs/LfsStoreRemoveListener.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/lfs/LfsStoreRemoveListener.java index 3d69dcabe6..18fb333c74 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/lfs/LfsStoreRemoveListener.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/lfs/LfsStoreRemoveListener.java @@ -32,7 +32,7 @@ package sonia.scm.web.lfs; -import com.google.common.eventbus.Subscribe; +import com.github.legman.Subscribe; import com.google.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/scm-webapp/src/main/java/sonia/scm/repository/LastModifiedUpdateListener.java b/scm-webapp/src/main/java/sonia/scm/repository/LastModifiedUpdateListener.java index bf868b2027..a84324cd60 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/LastModifiedUpdateListener.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/LastModifiedUpdateListener.java @@ -33,7 +33,7 @@ package sonia.scm.repository; //~--- non-JDK imports -------------------------------------------------------- -import com.google.common.eventbus.Subscribe; +import com.github.legman.Subscribe; import com.google.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/scm-webapp/src/main/java/sonia/scm/security/AuthorizationChangedEventProducer.java b/scm-webapp/src/main/java/sonia/scm/security/AuthorizationChangedEventProducer.java index c21ec17d18..5a954bb1e7 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/AuthorizationChangedEventProducer.java +++ b/scm-webapp/src/main/java/sonia/scm/security/AuthorizationChangedEventProducer.java @@ -30,8 +30,8 @@ */ package sonia.scm.security; +import com.github.legman.Subscribe; import com.google.common.annotations.VisibleForTesting; -import com.google.common.eventbus.Subscribe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.EagerSingleton; From 01cbbe89da8cc8edbdd7387ffc268cfe4123379c Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 16 Jul 2018 12:03:13 +0200 Subject: [PATCH 17/21] check repository path of hg hooks is in the hg directory, instead of path length check --- .../sonia/scm/repository/RepositoryUtil.java | 26 +++---- .../scm/repository/RepositoryUtilTest.java | 67 +++++++++++++++++++ 2 files changed, 81 insertions(+), 12 deletions(-) create mode 100644 scm-core/src/test/java/sonia/scm/repository/RepositoryUtilTest.java diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryUtil.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryUtil.java index 4bf10387d4..798ac38a0e 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryUtil.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryUtil.java @@ -103,19 +103,21 @@ public final class RepositoryUtil public static String getRepositoryId(File baseDirectory, File directory) throws IOException { String path = directory.getCanonicalPath(); - int directoryLength = baseDirectory.getCanonicalPath().length(); + String basePath = baseDirectory.getCanonicalPath(); - if (directoryLength < path.length()) - { - 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 - { - throw new IllegalStateException("path is shorter as the main repository path"); - } + Preconditions.checkArgument( + path.startsWith(basePath), + "repository path %s is not in the main repository path %s", path, basePath + ); + + String id = IOUtil.trimSeperatorChars(path.substring(basePath.length())); + + Preconditions.checkArgument( + !id.contains("\\") && !id.contains("/"), + "got illegal repository directory with separators in id: %s", path + ); + + return id; } private static void searchRepositoryDirectories(List repositories, diff --git a/scm-core/src/test/java/sonia/scm/repository/RepositoryUtilTest.java b/scm-core/src/test/java/sonia/scm/repository/RepositoryUtilTest.java new file mode 100644 index 0000000000..bbe4814566 --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/repository/RepositoryUtilTest.java @@ -0,0 +1,67 @@ +package sonia.scm.repository; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.io.File; +import java.io.IOException; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +@RunWith(MockitoJUnitRunner.class) +public class RepositoryUtilTest { + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Mock + private AbstractRepositoryHandler repositoryHandler; + + private SimpleRepositoryConfig repositoryConfig = new SimpleRepositoryConfig(); + + @Before + public void setUpMocks() { + when(repositoryHandler.getConfig()).thenReturn(repositoryConfig); + } + + @Test + public void testGetRepositoryId() throws IOException { + File repositoryTypeRoot = temporaryFolder.newFolder(); + repositoryConfig.setRepositoryDirectory(repositoryTypeRoot); + + File repository = new File(repositoryTypeRoot, "abc"); + String id = RepositoryUtil.getRepositoryId(repositoryHandler, repository.getPath()); + assertEquals("abc", id); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetRepositoryIdWithInvalidPath() throws IOException { + File repositoryTypeRoot = temporaryFolder.newFolder(); + repositoryConfig.setRepositoryDirectory(repositoryTypeRoot); + + File repository = new File("/etc/abc"); + String id = RepositoryUtil.getRepositoryId(repositoryHandler, repository.getPath()); + assertEquals("abc", id); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetRepositoryIdWithInvalidPathButSameLength() throws IOException { + File repositoryTypeRoot = temporaryFolder.newFolder(); + repositoryConfig.setRepositoryDirectory(repositoryTypeRoot); + + System.out.println(repositoryTypeRoot); + + File repository = new File(temporaryFolder.newFolder(), "abc"); + System.out.println(repository); + + String id = RepositoryUtil.getRepositoryId(repositoryHandler, repository.getPath()); + assertEquals("abc", id); + } + +} From 0a1ed6c6dac1bd7ba353c3fa74ea66f18bbb02da Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 16 Jul 2018 13:21:55 +0200 Subject: [PATCH 18/21] ignore false positive squid:S2083 --- .../sonia/scm/repository/RepositoryUtil.java | 50 ++++--------------- .../scm/repository/RepositoryUtilTest.java | 12 +++-- 2 files changed, 18 insertions(+), 44 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryUtil.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryUtil.java index 798ac38a0e..0be291d4e1 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryUtil.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryUtil.java @@ -36,8 +36,6 @@ 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; @@ -55,32 +53,10 @@ import java.util.List; * @author Sebastian Sdorra * @since 1.11 */ -public final class RepositoryUtil -{ +public final class RepositoryUtil { - /** the logger for RepositoryUtil */ - private static final Logger logger = - LoggerFactory.getLogger(RepositoryUtil.class); - - //~--- constructors --------------------------------------------------------- - - /** - * Constructs ... - * - */ private RepositoryUtil() {} - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - * - * @param directory - * @param names - * - * @return - */ public static List searchRepositoryDirectories(File directory, String... names) { List repositories = new ArrayList<>(); @@ -89,6 +65,7 @@ public final class RepositoryUtil return repositories; } + @SuppressWarnings("squid:S2083") // ignore, because the path is validated at {@link #getRepositoryId(File, File)} public static String getRepositoryId(AbstractRepositoryHandler handler, String directoryPath) throws IOException { return getRepositoryId(handler.getConfig().getRepositoryDirectory(), new File(directoryPath)); } @@ -120,33 +97,24 @@ public final class RepositoryUtil return id; } - private static void searchRepositoryDirectories(List repositories, - File directory, List names) - { + private static void searchRepositoryDirectories(List repositories, File directory, List names) { boolean found = false; - for (String name : names) - { - if (new File(directory, name).exists()) - { + for (String name : names) { + if (new File(directory, name).exists()) { found = true; break; } } - if (found) - { + if (found) { repositories.add(directory); - } - else - { + } else { File[] directories = directory.listFiles(DirectoryFileFilter.instance); - if (directories != null) - { - for (File d : directories) - { + if (directories != null) { + for (File d : directories) { searchRepositoryDirectories(repositories, d, names); } } diff --git a/scm-core/src/test/java/sonia/scm/repository/RepositoryUtilTest.java b/scm-core/src/test/java/sonia/scm/repository/RepositoryUtilTest.java index bbe4814566..25fa3eeeb3 100644 --- a/scm-core/src/test/java/sonia/scm/repository/RepositoryUtilTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/RepositoryUtilTest.java @@ -55,13 +55,19 @@ public class RepositoryUtilTest { File repositoryTypeRoot = temporaryFolder.newFolder(); repositoryConfig.setRepositoryDirectory(repositoryTypeRoot); - System.out.println(repositoryTypeRoot); - File repository = new File(temporaryFolder.newFolder(), "abc"); - System.out.println(repository); String id = RepositoryUtil.getRepositoryId(repositoryHandler, repository.getPath()); assertEquals("abc", id); } + @Test(expected = IllegalArgumentException.class) + public void testGetRepositoryIdWithInvalidId() throws IOException { + File repositoryTypeRoot = temporaryFolder.newFolder(); + repositoryConfig.setRepositoryDirectory(repositoryTypeRoot); + + File repository = new File(repositoryTypeRoot, "abc/123"); + RepositoryUtil.getRepositoryId(repositoryHandler, repository.getPath()); + } + } From 25d1ac082171b65f7b8c7475ef43bc29ccac9868 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 16 Jul 2018 13:38:57 +0200 Subject: [PATCH 19/21] uncomment the whole import block, to avoid sonarqube sonarqube mark it as bug --- .../scm/api/rest/resources/RepositoryImportResource.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryImportResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryImportResource.java index 4d8fba1c26..a2be057bdf 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryImportResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryImportResource.java @@ -740,7 +740,7 @@ public class RepositoryImportResource for (String repositoryName : repositoryNames) { // TODO #8783 - Repository repository = null; //manager.get(type, repositoryName); + /*Repository repository = null; //manager.get(type, repositoryName); if (repository != null) { @@ -750,7 +750,7 @@ public class RepositoryImportResource { logger.warn("could not find imported repository {}", repositoryName); - } + }*/ } } } From 8a2346271adb90ededa3e76182926f619da27151 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 16 Jul 2018 13:51:37 +0200 Subject: [PATCH 20/21] do not expose exception to the client --- .../sonia/scm/web/HgHookCallbackServlet.java | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java index 4283519011..2734996686 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java @@ -162,20 +162,17 @@ public class HgHookCallbackServlet extends HttpServlet } } - /** - * Method description - * - * - * @param request - * @param response - * - * @throws IOException - * @throws ServletException - */ @Override - protected void doPost(HttpServletRequest request, - HttpServletResponse response) - throws ServletException, IOException + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + try { + handlePostRequest(request, response); + } catch (IOException ex) { + logger.warn("error in hook callback execution, sending internal server error", ex); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + + private void handlePostRequest(HttpServletRequest request, HttpServletResponse response) throws IOException { String strippedURI = HttpUtil.getStrippedURI(request); Matcher m = REGEX_URL.matcher(strippedURI); From 8addd26087c4d5966643e09bf90333a15a674867 Mon Sep 17 00:00:00 2001 From: Johannes Schnatterer Date: Mon, 16 Jul 2018 12:51:24 +0000 Subject: [PATCH 21/21] Close branch feature/repository_namespaces