From 9a06f75bb13c4e1dd72e5f282993fff34e9c0978 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 23 Oct 2011 15:56:47 +0200 Subject: [PATCH 01/21] prepare ui and repository manager for directory structure --- .../AbstractSimpleRepositoryHandler.java | 14 ++- .../java/sonia/scm/repository/Repository.java | 4 +- .../scm/repository/RepositoryManager.java | 37 ++++++ .../src/main/java/sonia/scm/util/IOUtil.java | 23 ++++ .../java/sonia/scm/util/ValidationUtil.java | 17 +++ .../repository/xml/XmlRepositoryManager.java | 110 ++++++++++++++++++ .../resources/js/override/ext.form.vtypes.js | 7 ++ .../sonia.repository.settingsformpanel.js | 2 +- .../repository/XmlRepositoryManagerTest.java | 72 +++++++++++- 9 files changed, 279 insertions(+), 7 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 9feabcbc84..083f0e159a 100644 --- a/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java +++ b/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java @@ -219,8 +219,18 @@ public abstract class AbstractSimpleRepositoryHandler - *
  • The name is not empty and contains only A-z, 0-9, _, -
  • + *
  • The name is not empty and contains only A-z, 0-9, _, -, /
  • *
  • The type is not empty
  • *
  • The contact is empty or contains a valid email address
  • * @@ -445,7 +445,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject @Override public boolean isValid() { - return ValidationUtil.isNameValid(name) && Util.isNotEmpty(type) + return ValidationUtil.isRepositoryNameValid(name) && Util.isNotEmpty(type) && ((Util.isEmpty(contact)) || ValidationUtil.isMailAddressValid(contact)); } 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 355e16faf1..1e90c57d2f 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryManager.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryManager.java @@ -43,6 +43,8 @@ import sonia.scm.TypeManager; import java.util.Collection; +import javax.servlet.http.HttpServletRequest; + /** * The central class for managing {@link Repository} objects. * This class is a singleton and is available via injection. @@ -80,6 +82,41 @@ public interface RepositoryManager */ public Collection getConfiguredTypes(); + /** + * Returns the {@link Repository} associated to the request uri. + * + * + * @param request the current http request + * + * @return associated to the request uri + * @since 1.9 + */ + public Repository getFromRequest(HttpServletRequest request); + + /** + * Returns the {@link Repository} associated to the given type and path. + * + * + * @param type type of the repository (hg, git ...) + * @param uri + * + * @return the {@link Repository} associated to the given type and path + * @since 1.9 + */ + public Repository getFromTypeAndUri(String type, String uri); + + /** + * Returns the {@link Repository} associated to the request uri. + * + * + * + * @param uri request uri without context path + * + * @return associated to the request uri + * @since 1.9 + */ + public Repository getFromUri(String uri); + /** * Returns a {@link RepositoryHandler} by the given type (hg, git, svn ...). * diff --git a/scm-core/src/main/java/sonia/scm/util/IOUtil.java b/scm-core/src/main/java/sonia/scm/util/IOUtil.java index e37ce0a70d..03fbb0f823 100644 --- a/scm-core/src/main/java/sonia/scm/util/IOUtil.java +++ b/scm-core/src/main/java/sonia/scm/util/IOUtil.java @@ -664,6 +664,29 @@ public class IOUtil return getScript(baseFile, baseFile.getAbsolutePath()); } + /** + * Method description + * + * + * @param parent + * @param child + * @since 1.9 + * + * @return + * + */ + public static boolean isChild(File parent, File child) + { + try + { + return child.getCanonicalPath().startsWith(parent.getCanonicalPath()); + } + catch (IOException ex) + { + throw new RuntimeException(ex); + } + } + //~--- methods -------------------------------------------------------------- /** diff --git a/scm-core/src/main/java/sonia/scm/util/ValidationUtil.java b/scm-core/src/main/java/sonia/scm/util/ValidationUtil.java index 7ad5ebfebf..8a5f5f7109 100644 --- a/scm-core/src/main/java/sonia/scm/util/ValidationUtil.java +++ b/scm-core/src/main/java/sonia/scm/util/ValidationUtil.java @@ -51,6 +51,9 @@ public class ValidationUtil /** Field description */ private static final String REGEX_NAME = "^[A-z0-9\\.\\-_]+$"; + /** Field description */ + private static final String REGEX_REPOSITORYNAME = "^[A-z0-9\\.\\-_/]+$"; + /** Field description */ private static final String REGEX_USERNAME = "^[A-z0-9\\.\\-_@]+$"; @@ -125,6 +128,20 @@ public class ValidationUtil return result; } + /** + * Method description + * + * + * @param name + * @since 1.9 + * + * @return + */ + public static boolean isRepositoryNameValid(String name) + { + return Util.isNotEmpty(name) && name.matches(REGEX_REPOSITORYNAME); + } + /** * Method description * diff --git a/scm-webapp/src/main/java/sonia/scm/repository/xml/XmlRepositoryManager.java b/scm-webapp/src/main/java/sonia/scm/repository/xml/XmlRepositoryManager.java index 4193c24453..b535716719 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/xml/XmlRepositoryManager.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/xml/XmlRepositoryManager.java @@ -67,6 +67,7 @@ import sonia.scm.store.Store; import sonia.scm.store.StoreFactory; import sonia.scm.util.AssertUtil; import sonia.scm.util.CollectionAppender; +import sonia.scm.util.HttpUtil; import sonia.scm.util.IOUtil; import sonia.scm.util.SecurityUtil; import sonia.scm.util.Util; @@ -87,6 +88,8 @@ import java.util.Map; import java.util.Set; import java.util.UUID; +import javax.servlet.http.HttpServletRequest; + /** * * @author Sebastian Sdorra @@ -625,6 +628,89 @@ public class XmlRepositoryManager extends AbstractRepositoryManager return viewer; } + /** + * Method description + * + * + * @param request + * + * @return + */ + @Override + public Repository getFromRequest(HttpServletRequest request) + { + AssertUtil.assertIsNotNull(request); + + return getFromUri(HttpUtil.getStrippedURI(request)); + } + + /** + * Method description + * + * + * @param type + * @param uri + * + * @return + */ + @Override + public Repository getFromTypeAndUri(String type, String uri) + { + AssertUtil.assertIsNotEmpty(type); + AssertUtil.assertIsNotEmpty(uri); + + Repository repository = null; + + if (handlerMap.containsKey(type)) + { + Collection repositories = repositoryDB.values(); + + for (Repository r : repositories) + { + if (type.equals(r.getType()) && isNameMatching(r, uri)) + { + if (isReader(r)) + { + repository = r.clone(); + } + + break; + } + } + } + + return repository; + } + + /** + * Method description + * + * + * @param uri + * + * @return + */ + @Override + public Repository getFromUri(String uri) + { + AssertUtil.assertIsNotEmpty(uri); + + if (uri.startsWith(HttpUtil.SEPARATOR_PATH)) + { + uri = uri.substring(1); + } + + int typeSeperator = uri.indexOf(HttpUtil.SEPARATOR_PATH); + + AssertUtil.assertPositive(typeSeperator); + + String type = uri.substring(0, typeSeperator); + + uri = uri.substring(typeSeperator + 1); + + return getFromTypeAndUri(type, uri); + } + /** * Method description * @@ -814,6 +900,30 @@ public class XmlRepositoryManager extends AbstractRepositoryManager return handler; } + /** + * Method description + * + * + * @param repository + * @param path + * + * @return + */ + private boolean isNameMatching(Repository repository, String path) + { + boolean result = false; + String name = repository.getName(); + + if (path.startsWith(name)) + { + String sub = path.substring(name.length()); + + result = Util.isEmpty(sub) || sub.startsWith(HttpUtil.SEPARATOR_PATH); + } + + return result; + } + /** * Method description * diff --git a/scm-webapp/src/main/webapp/resources/js/override/ext.form.vtypes.js b/scm-webapp/src/main/webapp/resources/js/override/ext.form.vtypes.js index 1a73cbef5d..f711e65242 100644 --- a/scm-webapp/src/main/webapp/resources/js/override/ext.form.vtypes.js +++ b/scm-webapp/src/main/webapp/resources/js/override/ext.form.vtypes.js @@ -51,6 +51,13 @@ Ext.apply(Ext.form.VTypes, { nameText: 'The name is invalid.', + // repository name validator + repositoryName: function(val){ + return /^[A-z0-9\.\-_\/]+$/.test(val); + }, + + repositoryNameText: 'The name of the repository is invalid.', + // username validator username: function(val){ diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.settingsformpanel.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.settingsformpanel.js index 9c2cf57f6a..3987f2076c 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.settingsformpanel.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.settingsformpanel.js @@ -43,7 +43,7 @@ Sonia.repository.SettingsFormPanel = Ext.extend(Sonia.repository.FormPanel, { readOnly: update, allowBlank: false, helpText: this.nameHelpText, - vtype: 'name' + vtype: 'repositoryName' },{ fieldLabel: this.typeText, name: 'type', diff --git a/scm-webapp/src/test/java/sonia/scm/repository/XmlRepositoryManagerTest.java b/scm-webapp/src/test/java/sonia/scm/repository/XmlRepositoryManagerTest.java index a58f3f292a..dd501461c9 100644 --- a/scm-webapp/src/test/java/sonia/scm/repository/XmlRepositoryManagerTest.java +++ b/scm-webapp/src/test/java/sonia/scm/repository/XmlRepositoryManagerTest.java @@ -37,16 +37,22 @@ package sonia.scm.repository; import com.google.inject.Provider; -import sonia.scm.Manager; +import org.junit.Test; + +import sonia.scm.Type; import sonia.scm.repository.xml.XmlRepositoryManager; import sonia.scm.store.JAXBStoreFactory; import sonia.scm.store.StoreFactory; import sonia.scm.util.MockUtil; +import static org.junit.Assert.*; + import static org.mockito.Mockito.*; //~--- JDK imports ------------------------------------------------------------ +import java.io.IOException; + import java.util.HashSet; import java.util.Set; @@ -57,6 +63,36 @@ import java.util.Set; public class XmlRepositoryManagerTest extends RepositoryManagerTestBase { + /** + * Method description + * + * + * @throws IOException + * @throws RepositoryException + */ + @Test + public void getRepositoryFromRequestUriTest() + throws RepositoryException, IOException + { + RepositoryManager m = createManager(); + + m.init(contextProvider); + createRepository(m, new Repository("1", "hg", "scm")); + createRepository(m, new Repository("2", "hg", "scm-test")); + createRepository(m, new Repository("3", "git", "project1/test-1")); + createRepository(m, new Repository("4", "git", "project1/test-2")); + assertEquals("scm", m.getFromUri("hg/scm").getName()); + assertEquals("scm-test", m.getFromUri("hg/scm-test").getName()); + assertEquals("scm-test", m.getFromUri("/hg/scm-test").getName()); + assertEquals("project1/test-1", + m.getFromUri("/git/project1/test-1").getName()); + assertEquals("project1/test-1", + m.getFromUri("/git/project1/test-1/ka/some/path").getName()); + assertNull(m.getFromUri("/git/project1/test-3/ka/some/path")); + } + + //~--- methods -------------------------------------------------------------- + /** * Method description * @@ -64,13 +100,29 @@ public class XmlRepositoryManagerTest extends RepositoryManagerTestBase * @return */ @Override - protected Manager createManager() + protected XmlRepositoryManager createManager() { Set handlerSet = new HashSet(); StoreFactory factory = new JAXBStoreFactory(); factory.init(contextProvider); handlerSet.add(new DummyRepositoryHandler(factory)); + handlerSet.add(new DummyRepositoryHandler(factory) + { + @Override + public Type getType() + { + return new Type("hg", "Mercurial"); + } + }); + handlerSet.add(new DummyRepositoryHandler(factory) + { + @Override + public Type getType() + { + return new Type("git", "Git"); + } + }); Provider> listenerProvider = mock(Provider.class); @@ -85,4 +137,20 @@ public class XmlRepositoryManagerTest extends RepositoryManagerTestBase factory, handlerSet, listenerProvider, hookProvider); } + + /** + * Method description + * + * + * @param m + * @param repository + * + * @throws IOException + * @throws RepositoryException + */ + private void createRepository(RepositoryManager m, Repository repository) + throws RepositoryException, IOException + { + m.create(repository); + } } From fc5c1f2a44dc3e2e8896714c170f92742622a6b9 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 23 Oct 2011 16:38:03 +0200 Subject: [PATCH 02/21] added injection for requested repository --- .../src/main/java/sonia/scm/util/IOUtil.java | 24 ++++ .../web/filter/ProviderPermissionFilter.java | 90 ++++++++++++++ .../main/java/sonia/scm/ScmServletModule.java | 3 + .../scm/repository/RepositoryProvider.java | 113 ++++++++++++++++++ 4 files changed, 230 insertions(+) create mode 100644 scm-core/src/main/java/sonia/scm/web/filter/ProviderPermissionFilter.java create mode 100644 scm-webapp/src/main/java/sonia/scm/repository/RepositoryProvider.java diff --git a/scm-core/src/main/java/sonia/scm/util/IOUtil.java b/scm-core/src/main/java/sonia/scm/util/IOUtil.java index 03fbb0f823..f6557abc89 100644 --- a/scm-core/src/main/java/sonia/scm/util/IOUtil.java +++ b/scm-core/src/main/java/sonia/scm/util/IOUtil.java @@ -592,6 +592,30 @@ public class IOUtil return cmds; } + /** + * Method description + * + * + * @param name + * + * @return + * @since 1.9 + */ + public static String trimSeperatorChars(String name) + { + if (name.startsWith(File.separator)) + { + name = name.substring(1); + } + + if (name.endsWith(File.separator)) + { + name = name.substring(0, name.length() - 1); + } + + return name; + } + //~--- get methods ---------------------------------------------------------- /** diff --git a/scm-core/src/main/java/sonia/scm/web/filter/ProviderPermissionFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/ProviderPermissionFilter.java new file mode 100644 index 0000000000..2263d8a20d --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/web/filter/ProviderPermissionFilter.java @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.web.filter; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.inject.Provider; + +import sonia.scm.repository.Repository; +import sonia.scm.web.security.WebSecurityContext; + +//~--- JDK imports ------------------------------------------------------------ + +import javax.servlet.http.HttpServletRequest; + +/** + * + * @author Sebastian Sdorra + * @since 1.9 + */ +public abstract class ProviderPermissionFilter extends PermissionFilter +{ + + /** + * Constructs ... + * + * + * @param securityContextProvider + * @param repositoryProvider + */ + public ProviderPermissionFilter( + Provider securityContextProvider, + Provider repositoryProvider) + { + super(securityContextProvider); + this.repositoryProvider = repositoryProvider; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param request + * + * @return + */ + @Override + protected Repository getRepository(HttpServletRequest request) + { + return repositoryProvider.get(); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private Provider repositoryProvider; +} diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java index e2c8c3d276..03e097e1e2 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java @@ -61,8 +61,10 @@ import sonia.scm.plugin.PluginLoader; import sonia.scm.plugin.PluginManager; import sonia.scm.plugin.ScriptResourceServlet; import sonia.scm.repository.ChangesetViewerUtil; +import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryBrowserUtil; import sonia.scm.repository.RepositoryManager; +import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.xml.XmlRepositoryManager; import sonia.scm.security.CipherHandler; import sonia.scm.security.CipherUtil; @@ -198,6 +200,7 @@ public class ScmServletModule extends ServletModule ScmConfiguration config = getScmConfiguration(context); CipherUtil cu = CipherUtil.getInstance(); + bind(Repository.class).toProvider(RepositoryProvider.class); bind(StoreFactory.class).to(JAXBStoreFactory.class); bind(ScmConfiguration.class).toInstance(config); bind(PluginLoader.class).toInstance(pluginLoader); diff --git a/scm-webapp/src/main/java/sonia/scm/repository/RepositoryProvider.java b/scm-webapp/src/main/java/sonia/scm/repository/RepositoryProvider.java new file mode 100644 index 0000000000..dbd9275cc7 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/repository/RepositoryProvider.java @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.repository; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.servlet.RequestScoped; + +//~--- JDK imports ------------------------------------------------------------ + +import javax.servlet.http.HttpServletRequest; + +/** + * + * @author Sebastian Sdorra + */ +@RequestScoped +public class RepositoryProvider implements Provider +{ + + /** Field description */ + public static final String ATTRIBUTE_NAME = "scm.request.repository"; + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + * + * @param requestProvider + * @param manager + */ + @Inject + public RepositoryProvider(Provider requestProvider, + RepositoryManager manager) + { + this.requestProvider = requestProvider; + this.manager = manager; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + public Repository get() + { + Repository repository = null; + HttpServletRequest request = requestProvider.get(); + + if (request != null) + { + repository = (Repository) request.getAttribute(ATTRIBUTE_NAME); + + if (repository == null) + { + repository = manager.getFromRequest(request); + + if (repository != null) + { + request.setAttribute(ATTRIBUTE_NAME, repository); + } + } + } + + return repository; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private RepositoryManager manager; + + /** Field description */ + private Provider requestProvider; +} From 09dc9af0cbb5f081f8203cebc39e4855f4586dc6 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 23 Oct 2011 16:39:09 +0200 Subject: [PATCH 03/21] mercurial support for directory structures --- .../sonia/scm/installer/UnixHgInstaller.java | 4 +- .../scm/installer/WindowsHgInstaller.java | 13 ++--- .../main/java/sonia/scm/web/HgCGIServlet.java | 37 ++++----------- .../sonia/scm/web/HgHookCallbackServlet.java | 47 +++++++++++++++++-- .../sonia/scm/web/HgPermissionFilter.java | 25 +++------- .../src/main/resources/sonia/scm/hghook.py | 4 +- 6 files changed, 68 insertions(+), 62 deletions(-) diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/installer/UnixHgInstaller.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/installer/UnixHgInstaller.java index 26ea293c12..ed81b27bdb 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/installer/UnixHgInstaller.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/installer/UnixHgInstaller.java @@ -77,7 +77,6 @@ public class UnixHgInstaller extends AbstractHgInstaller super.install(baseDirectory, config); // search mercurial (hg) - if (Util.isEmpty(config.getHgBinary())) { String hg = IOUtil.search(COMMAND_HG); @@ -100,9 +99,8 @@ public class UnixHgInstaller extends AbstractHgInstaller } } } - - // search python + // search python if (Util.isEmpty(config.getPythonBinary())) { config.setPythonBinary(IOUtil.search(COMMAND_PYTHON)); diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/installer/WindowsHgInstaller.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/installer/WindowsHgInstaller.java index 879eead8ff..a764997c73 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/installer/WindowsHgInstaller.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/installer/WindowsHgInstaller.java @@ -272,8 +272,9 @@ public class WindowsHgInstaller extends AbstractHgInstaller IOUtil.copy(templateDirectory, new File(libDir, FILE_TEMPLATES)); } - File hg = new File( hgDirectory, FILE_MERCURIAL_EXE ); - if ( hg.exists() ) + File hg = new File(hgDirectory, FILE_MERCURIAL_EXE); + + if (hg.exists()) { config.setHgBinary(hg.getAbsolutePath()); } @@ -322,8 +323,8 @@ public class WindowsHgInstaller extends AbstractHgInstaller private File getMercurialDirectory(String hgBinary) { File directory = null; - - if ( Util.isNotEmpty(hgBinary) ) + + if (Util.isNotEmpty(hgBinary)) { File hg = new File(hgBinary); @@ -332,8 +333,8 @@ public class WindowsHgInstaller extends AbstractHgInstaller directory = hg.getParentFile(); } } - - if ( directory == null ) + + if (directory == null) { directory = getMercurialDirectoryFromRegistry(); } 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 ad46358cc1..9e5219ca57 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 @@ -36,6 +36,7 @@ package sonia.scm.web; //~--- non-JDK imports -------------------------------------------------------- import com.google.inject.Inject; +import com.google.inject.Provider; import com.google.inject.Singleton; import sonia.scm.config.ScmConfiguration; @@ -55,7 +56,6 @@ import java.io.File; import java.io.IOException; import java.util.Enumeration; -import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.ServletException; @@ -103,6 +103,7 @@ public class HgCGIServlet extends HttpServlet * @param cgiExecutorFactory * @param configuration * @param repositoryManager + * @param repositoryProvider * @param handler * @param hookManager */ @@ -110,11 +111,13 @@ public class HgCGIServlet extends HttpServlet public HgCGIServlet(CGIExecutorFactory cgiExecutorFactory, ScmConfiguration configuration, RepositoryManager repositoryManager, + Provider repositoryProvider, HgRepositoryHandler handler, HgHookManager hookManager) { this.cgiExecutorFactory = cgiExecutorFactory; this.configuration = configuration; this.repositoryManager = repositoryManager; + this.repositoryProvider = repositoryProvider; this.handler = handler; this.hookManager = hookManager; } @@ -149,7 +152,7 @@ public class HgCGIServlet extends HttpServlet HttpServletResponse response) throws ServletException, IOException { - Repository repository = getRepository(request); + Repository repository = repositoryProvider.get(); if (repository == null) { @@ -244,33 +247,6 @@ public class HgCGIServlet extends HttpServlet return python; } - /** - * Method description - * - * - * @param request - * - * @return - */ - private Repository getRepository(HttpServletRequest request) - { - Repository repository = null; - String uri = request.getRequestURI(); - - uri = uri.substring(request.getContextPath().length()); - - Matcher m = PATTERN_REPOSITORYNAME.matcher(uri); - - if (m.matches()) - { - String repositoryname = m.group(1); - - repository = getRepository(repositoryname); - } - - return repository; - } - /** * Method description * @@ -303,4 +279,7 @@ public class HgCGIServlet extends HttpServlet /** Field description */ private RepositoryManager repositoryManager; + + /** Field description */ + private Provider repositoryProvider; } 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 a59303ae02..2d7f684cde 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 @@ -51,6 +51,7 @@ import sonia.scm.repository.RepositoryManager; import sonia.scm.repository.RepositoryNotFoundException; import sonia.scm.security.CipherUtil; import sonia.scm.util.HttpUtil; +import sonia.scm.util.IOUtil; import sonia.scm.util.Util; import sonia.scm.web.security.WebSecurityContext; @@ -80,6 +81,9 @@ public class HgHookCallbackServlet extends HttpServlet /** Field description */ public static final String HGHOOK_PRE_RECEIVE = "pretxnchangegroup"; + /** Field description */ + public static final String PARAM_REPOSITORYPATH = "repositoryPath"; + /** Field description */ private static final String PARAM_CHALLENGE = "challenge"; @@ -91,7 +95,7 @@ public class HgHookCallbackServlet extends HttpServlet /** Field description */ private static final Pattern REGEX_URL = - Pattern.compile("^/hook/hg/([^/]+)/([^/]+)$"); + Pattern.compile("^/hook/hg/([^/]+)$"); /** the logger for HgHookCallbackServlet */ private static final Logger logger = @@ -144,8 +148,8 @@ public class HgHookCallbackServlet extends HttpServlet if (m.matches()) { - String repositoryId = m.group(1); - String type = m.group(2); + String repositoryId = getRepositoryName(request); + String type = m.group(1); String challenge = request.getParameter(PARAM_CHALLENGE); if (Util.isNotEmpty(challenge)) @@ -316,6 +320,43 @@ public class HgHookCallbackServlet extends HttpServlet } } + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param request + * + * @return + */ + private String getRepositoryName(HttpServletRequest request) + { + String name = null; + String path = request.getParameter(PARAM_REPOSITORYPATH); + + if (Util.isNotEmpty(path)) + { + int directoryLength = + handler.getConfig().getRepositoryDirectory().getAbsolutePath().length(); + + if (directoryLength < path.length()) + { + name = IOUtil.trimSeperatorChars(path.substring(directoryLength)); + } + else if (logger.isWarnEnabled()) + { + logger.warn("path is shorter as the main hg repository path"); + } + } + else if (logger.isWarnEnabled()) + { + logger.warn("no repository path parameter found"); + } + + return name; + } + //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java index c44c422ea5..865513e8c8 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgPermissionFilter.java @@ -39,9 +39,8 @@ import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; -import sonia.scm.repository.HgRepositoryHandler; -import sonia.scm.repository.RepositoryManager; -import sonia.scm.web.filter.RegexPermissionFilter; +import sonia.scm.repository.Repository; +import sonia.scm.web.filter.ProviderPermissionFilter; import sonia.scm.web.security.WebSecurityContext; //~--- JDK imports ------------------------------------------------------------ @@ -53,7 +52,7 @@ import javax.servlet.http.HttpServletRequest; * @author Sebastian Sdorra */ @Singleton -public class HgPermissionFilter extends RegexPermissionFilter +public class HgPermissionFilter extends ProviderPermissionFilter { /** @@ -61,30 +60,18 @@ public class HgPermissionFilter extends RegexPermissionFilter * * * @param securityContextProvider - * @param repositoryManager + * @param repositoryProvider */ @Inject public HgPermissionFilter( Provider securityContextProvider, - RepositoryManager repositoryManager) + Provider repositoryProvider) { - super(securityContextProvider, repositoryManager); + super(securityContextProvider, repositoryProvider); } //~--- get methods ---------------------------------------------------------- - /** - * Method description - * - * - * @return - */ - @Override - protected String getType() - { - return HgRepositoryHandler.TYPE_NAME; - } - /** * Method description * diff --git a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hghook.py b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hghook.py index 170b0d8769..f03ece6f9e 100644 --- a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hghook.py +++ b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hghook.py @@ -48,9 +48,9 @@ def callback(ui, repo, hooktype, node=None, source=None, pending=None, **kwargs) failure = True if node != None: try: - url = baseUrl + os.path.basename(repo.root) + "/" + hooktype + url = baseUrl + hooktype ui.debug( "send scm-hook to " + url + " and " + node + "\n" ) - data = urllib.urlencode({'node': node, 'challenge': challenge, 'credentials': credentials}) + data = urllib.urlencode({'node': node, 'challenge': challenge, 'credentials': credentials, 'repositoryPath': repo.root}) conn = urllib.urlopen(url, data); if conn.code >= 200 and conn.code < 300: ui.debug( "scm-hook " + hooktype + " success with status code " + str(conn.code) + "\n" ) From 76c5c4ce40be069845944cbfb37bd6ff64dc79cb Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 23 Oct 2011 16:49:44 +0200 Subject: [PATCH 04/21] git support for directory structures --- .../sonia/scm/web/GitPermissionFilter.java | 25 ++------ .../sonia/scm/web/GitRepositoryResolver.java | 55 ------------------ .../java/sonia/scm/web/ScmGitServlet.java | 58 +++++++++---------- 3 files changed, 32 insertions(+), 106 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java index 6c1181021e..d9c24a59bf 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitPermissionFilter.java @@ -39,9 +39,8 @@ import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; -import sonia.scm.repository.GitRepositoryHandler; -import sonia.scm.repository.RepositoryManager; -import sonia.scm.web.filter.RegexPermissionFilter; +import sonia.scm.repository.Repository; +import sonia.scm.web.filter.ProviderPermissionFilter; import sonia.scm.web.security.WebSecurityContext; //~--- JDK imports ------------------------------------------------------------ @@ -53,7 +52,7 @@ import javax.servlet.http.HttpServletRequest; * @author Sebastian Sdorra */ @Singleton -public class GitPermissionFilter extends RegexPermissionFilter +public class GitPermissionFilter extends ProviderPermissionFilter { /** Field description */ @@ -76,30 +75,18 @@ public class GitPermissionFilter extends RegexPermissionFilter * * * @param securityContextProvider - * @param repositoryManager + * @param repositoryProvider */ @Inject public GitPermissionFilter( Provider securityContextProvider, - RepositoryManager repositoryManager) + Provider repositoryProvider) { - super(securityContextProvider, repositoryManager); + super(securityContextProvider, repositoryProvider); } //~--- get methods ---------------------------------------------------------- - /** - * Method description - * - * - * @return - */ - @Override - protected String getType() - { - return GitRepositoryHandler.TYPE_NAME; - } - /** * Method description * 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 daec3add99..5ddd000490 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 @@ -86,56 +86,6 @@ public class GitRepositoryResolver this.handler = handler; } - //~--- get methods ---------------------------------------------------------- - - /** - * Method description - * - * - * @param name - * - * @return - */ - private static boolean isUnreasonableName(final String name) - { - if (name.length() == 0) - { - return true; // no empty paths - } - - if (name.indexOf('\\') >= 0) - { - return true; // no windows/dos style paths - } - - if (new File(name).isAbsolute()) - { - return true; // no absolute paths - } - - if (name.startsWith("../")) - { - return true; // no "l../etc/passwd" - } - - if (name.contains("/../")) - { - return true; // no "foo/../etc/passwd" - } - - if (name.contains("/./")) - { - return true; // "foo/./foo" is insane to ask - } - - if (name.contains("//")) - { - return true; // double slashes is sloppy, don't use it - } - - return false; // is a reasonable name - } - //~--- methods -------------------------------------------------------------- /** @@ -158,11 +108,6 @@ public class GitRepositoryResolver { Repository repository = null; - if (isUnreasonableName(repositoryName)) - { - throw new RepositoryNotFoundException(repositoryName); - } - try { GitConfig config = handler.getConfig(); diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java index a4d13cae93..5eb1c1b0c5 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/ScmGitServlet.java @@ -36,21 +36,20 @@ package sonia.scm.web; //~--- non-JDK imports -------------------------------------------------------- import com.google.inject.Inject; +import com.google.inject.Provider; import com.google.inject.Singleton; import org.eclipse.jgit.http.server.GitServlet; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.transport.resolver.RepositoryResolver; +import sonia.scm.repository.GitUtil; import sonia.scm.util.HttpUtil; //~--- JDK imports ------------------------------------------------------------ import java.io.IOException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -70,10 +69,6 @@ public class ScmGitServlet extends GitServlet /** Field description */ private static final long serialVersionUID = -7712897339207470674L; - /** Field description */ - private static final Pattern REGEX_REPOSITORYNAME = - Pattern.compile("/git/([^/]+)/?.*"); - //~--- constructors --------------------------------------------------------- /** @@ -83,12 +78,16 @@ public class ScmGitServlet extends GitServlet * * @param repositoryResolver * @param receivePackFactory + * @param repositoryProvider */ @Inject - public ScmGitServlet(GitRepositoryResolver repositoryResolver, - GitReceivePackFactory receivePackFactory) + public ScmGitServlet( + GitRepositoryResolver repositoryResolver, + GitReceivePackFactory receivePackFactory, + Provider repositoryProvider) { this.resolver = repositoryResolver; + this.repositoryProvider = repositoryProvider; setRepositoryResolver(repositoryResolver); setReceivePackFactory(receivePackFactory); } @@ -137,43 +136,38 @@ public class ScmGitServlet extends GitServlet HttpServletResponse response) throws ServletException, IOException { - String uri = HttpUtil.getStrippedURI(request); - Matcher m = REGEX_REPOSITORYNAME.matcher(uri); - String name = null; - Repository repository = null; + sonia.scm.repository.Repository scmRepository = repositoryProvider.get(); - try + if (scmRepository != null) { - if (m.matches()) - { - name = m.group(1); - repository = resolver.open(request, name); - } + Repository repository = null; - if (repository != null) + try { - new GitRepositoryViewer().handleRequest(response, repository, name); + repository = resolver.open(request, scmRepository.getName()); + new GitRepositoryViewer().handleRequest(response, repository, + scmRepository.getName()); } - else + catch (Exception ex) { - response.sendError(HttpServletResponse.SC_NOT_FOUND); + throw new ServletException(ex); + } + finally + { + GitUtil.close(repository); } } - catch (Exception ex) + else { - throw new ServletException(ex); - } - finally - { - if (repository != null) - { - repository.close(); - } + response.sendError(HttpServletResponse.SC_NOT_FOUND); } } //~--- fields --------------------------------------------------------------- + /** Field description */ + private Provider repositoryProvider; + /** Field description */ private RepositoryResolver resolver; } From 69e98420dcde10929ca96418f417a3cdc4aeb75d Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 23 Oct 2011 19:06:45 +0200 Subject: [PATCH 05/21] subversion support for directory structures --- scm-plugins/scm-svn-plugin/pom.xml | 2 +- .../scm/repository/SvnRepositoryHandler.java | 2 +- .../scm/repository/SvnRepositoryHook.java | 19 ++- .../main/java/sonia/scm/web/SvnDAVConfig.java | 76 ++++++++-- .../java/sonia/scm/web/SvnDAVServlet.java | 133 +++++++++++++++++- .../sonia/scm/web/SvnPermissionFilter.java | 25 +--- scm-webapp/pom.xml | 2 +- 7 files changed, 222 insertions(+), 37 deletions(-) diff --git a/scm-plugins/scm-svn-plugin/pom.xml b/scm-plugins/scm-svn-plugin/pom.xml index 7b74b2b464..6e646b9004 100644 --- a/scm-plugins/scm-svn-plugin/pom.xml +++ b/scm-plugins/scm-svn-plugin/pom.xml @@ -53,7 +53,7 @@ - 1.3.5.7 + 1.3.5.8-SNAPSHOT diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnRepositoryHandler.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnRepositoryHandler.java index cbd9254238..536586f95a 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnRepositoryHandler.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnRepositoryHandler.java @@ -102,7 +102,7 @@ public class SvnRepositoryHandler // register hook if (repositoryManager != null) { - FSHooks.registerHook(new SvnRepositoryHook(repositoryManager)); + FSHooks.registerHook(new SvnRepositoryHook(repositoryManager, this)); } else if (logger.isWarnEnabled()) { 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 bceacf5bbd..e8b9e63e4a 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 @@ -46,6 +46,7 @@ import org.tmatesoft.svn.core.internal.io.fs.FSHook; import org.tmatesoft.svn.core.internal.io.fs.FSHookEvent; import org.tmatesoft.svn.core.internal.io.fs.FSHooks; +import sonia.scm.util.IOUtil; import sonia.scm.util.Util; //~--- JDK imports ------------------------------------------------------------ @@ -70,10 +71,13 @@ public class SvnRepositoryHook implements FSHook * * * @param repositoryManager + * @param handler */ - public SvnRepositoryHook(RepositoryManager repositoryManager) + public SvnRepositoryHook(RepositoryManager repositoryManager, + SvnRepositoryHandler handler) { this.repositoryManager = repositoryManager; + this.handler = handler; } //~--- methods -------------------------------------------------------------- @@ -151,8 +155,14 @@ public class SvnRepositoryHook implements FSHook { try { - repositoryManager.fireHookEvent(SvnRepositoryHandler.TYPE_NAME, - directory.getName(), hookEvent); + String name = + directory.getAbsolutePath() + .substring(handler.getConfig().getRepositoryDirectory() + .getAbsolutePath().length()); + + name = IOUtil.trimSeperatorChars(name); + repositoryManager.fireHookEvent(SvnRepositoryHandler.TYPE_NAME, name, + hookEvent); } catch (Exception ex) { @@ -168,6 +178,9 @@ public class SvnRepositoryHook implements FSHook //~--- fields --------------------------------------------------------------- + /** Field description */ + private SvnRepositoryHandler handler; + /** Field description */ private RepositoryManager repositoryManager; } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVConfig.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVConfig.java index 0a39e80561..6145f79609 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVConfig.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnDAVConfig.java @@ -35,10 +35,17 @@ package sonia.scm.web; //~--- non-JDK imports -------------------------------------------------------- +import com.google.inject.Provider; + import org.tmatesoft.svn.core.internal.server.dav.DAVConfig; import org.tmatesoft.svn.core.internal.server.dav.SVNPathBasedAccess; -import sonia.scm.repository.SvnConfig; +import sonia.scm.repository.Repository; +import sonia.scm.repository.SvnRepositoryHandler; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.File; /** * @@ -52,12 +59,15 @@ public class SvnDAVConfig extends DAVConfig * * * @param davConfig - * @param config + * @param handler + * @param repositoryProvider */ - public SvnDAVConfig(DAVConfig davConfig, SvnConfig config) + public SvnDAVConfig(DAVConfig davConfig, SvnRepositoryHandler handler, + Provider repositoryProvider) { this.davConfig = davConfig; - this.config = config; + this.handler = handler; + this.repositoryProvider = repositoryProvider; } //~--- get methods ---------------------------------------------------------- @@ -71,7 +81,7 @@ public class SvnDAVConfig extends DAVConfig @Override public String getActivitiesDBPath() { - return davConfig.getActivitiesDBPath(); + return null; } /** @@ -95,7 +105,19 @@ public class SvnDAVConfig extends DAVConfig @Override public String getRepositoryParentPath() { - return config.getRepositoryDirectory().getAbsolutePath(); + String path = null; + File directory = getRepositoryDirectory(); + + if (directory != null) + { + path = directory.getParent(); + } + else + { + path = davConfig.getRepositoryPath(); + } + + return path; } /** @@ -107,7 +129,19 @@ public class SvnDAVConfig extends DAVConfig @Override public String getRepositoryPath() { - return davConfig.getRepositoryPath(); + String path = null; + File directory = getRepositoryDirectory(); + + if (directory != null) + { + path = directory.getAbsolutePath(); + } + else + { + path = davConfig.getRepositoryPath(); + } + + return path; } /** @@ -227,14 +261,36 @@ public class SvnDAVConfig extends DAVConfig @Override public boolean isUsingRepositoryPathDirective() { - return davConfig.isUsingRepositoryPathDirective(); + return true; + } + + /** + * Method description + * + * + * @return + */ + private File getRepositoryDirectory() + { + File directory = null; + Repository repository = repositoryProvider.get(); + + if (repository != null) + { + directory = handler.getDirectory(repository); + } + + return directory; } //~--- fields --------------------------------------------------------------- /** Field description */ - private SvnConfig config; + private DAVConfig davConfig; /** Field description */ - private DAVConfig davConfig; + private SvnRepositoryHandler handler; + + /** Field description */ + private Provider repositoryProvider; } 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 c5e5f6c6ab..7e7723aa60 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 @@ -36,12 +36,26 @@ package sonia.scm.web; //~--- non-JDK imports -------------------------------------------------------- import com.google.inject.Inject; +import com.google.inject.Provider; import com.google.inject.Singleton; import org.tmatesoft.svn.core.internal.server.dav.DAVConfig; import org.tmatesoft.svn.core.internal.server.dav.DAVServlet; +import sonia.scm.repository.Repository; import sonia.scm.repository.SvnRepositoryHandler; +import sonia.scm.util.AssertUtil; +import sonia.scm.util.HttpUtil; +import sonia.scm.util.IOUtil; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; /** * @@ -61,11 +75,34 @@ public class SvnDAVServlet extends DAVServlet * * * @param handler + * @param repositoryProvider */ @Inject - public SvnDAVServlet(SvnRepositoryHandler handler) + public SvnDAVServlet(SvnRepositoryHandler handler, + Provider repositoryProvider) { this.handler = handler; + this.repositoryProvider = repositoryProvider; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param request + * @param response + * + * @throws IOException + * @throws ServletException + */ + @Override + public void service(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + super.service(new SvnHttpServletRequestWrapper(request, + repositoryProvider), response); } //~--- get methods ---------------------------------------------------------- @@ -79,11 +116,103 @@ public class SvnDAVServlet extends DAVServlet @Override protected DAVConfig getDAVConfig() { - return new SvnDAVConfig(super.getDAVConfig(), handler.getConfig()); + return new SvnDAVConfig(super.getDAVConfig(), handler, repositoryProvider); } + //~--- inner classes -------------------------------------------------------- + + /** + * Class description + * + * + * @version Enter version here..., 11/10/23 + * @author Enter your name here... + */ + private static class SvnHttpServletRequestWrapper + extends HttpServletRequestWrapper + { + + /** + * Constructs ... + * + * + * @param request + * @param repositoryProvider + */ + public SvnHttpServletRequestWrapper(HttpServletRequest request, + Provider repositoryProvider) + { + super(request); + this.repositoryProvider = repositoryProvider; + } + + //~--- get methods -------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + public String getPathInfo() + { + String pathInfo = super.getPathInfo(); + + AssertUtil.assertIsNotEmpty(pathInfo); + + Repository repository = repositoryProvider.get(); + + if (repository != null) + { + if (pathInfo.startsWith(HttpUtil.SEPARATOR_PATH)) + { + pathInfo = pathInfo.substring(1); + } + + pathInfo = pathInfo.substring(repository.getName().length()); + } + + return pathInfo; + } + + /** + * Method description + * + * + * @return + */ + @Override + public String getServletPath() + { + String servletPath = super.getServletPath(); + Repository repository = repositoryProvider.get(); + + if (repository != null) + { + if (!servletPath.endsWith(HttpUtil.SEPARATOR_PATH)) + { + servletPath = servletPath.concat(HttpUtil.SEPARATOR_PATH); + } + + servletPath = servletPath.concat(repository.getName()); + } + + return servletPath; + } + + //~--- fields ------------------------------------------------------------- + + /** Field description */ + private Provider repositoryProvider; + } + + //~--- fields --------------------------------------------------------------- /** Field description */ private SvnRepositoryHandler handler; + + /** Field description */ + private Provider repositoryProvider; } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java index 9c7d582bd9..24e556f274 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnPermissionFilter.java @@ -39,9 +39,8 @@ import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; -import sonia.scm.repository.RepositoryManager; -import sonia.scm.repository.SvnRepositoryHandler; -import sonia.scm.web.filter.RegexPermissionFilter; +import sonia.scm.repository.Repository; +import sonia.scm.web.filter.ProviderPermissionFilter; import sonia.scm.web.security.WebSecurityContext; //~--- JDK imports ------------------------------------------------------------ @@ -57,7 +56,7 @@ import javax.servlet.http.HttpServletRequest; * @author Sebastian Sdorra */ @Singleton -public class SvnPermissionFilter extends RegexPermissionFilter +public class SvnPermissionFilter extends ProviderPermissionFilter { /** Field description */ @@ -74,30 +73,18 @@ public class SvnPermissionFilter extends RegexPermissionFilter * * * @param securityContextProvider - * @param repositoryManager + * @param repository */ @Inject public SvnPermissionFilter( Provider securityContextProvider, - RepositoryManager repositoryManager) + Provider repository) { - super(securityContextProvider, repositoryManager); + super(securityContextProvider, repository); } //~--- get methods ---------------------------------------------------------- - /** - * Method description - * - * - * @return - */ - @Override - protected String getType() - { - return SvnRepositoryHandler.TYPE_NAME; - } - /** * Method description * diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index 1b053644ab..84427e2955 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -356,7 +356,7 @@ 1.13 1.0 3.0.3 - gfv3ee6 + Tomcat From 237f026a1f46dcbea92939a7bc8bea196afb2d75 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 24 Oct 2011 08:45:33 +0200 Subject: [PATCH 06/21] enable grouping for the repository grid --- .../js/repository/sonia.repository.grid.js | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js index 619aa923e8..26de9b5704 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js @@ -44,16 +44,21 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { initComponent: function(){ - var repositoryStore = new Sonia.rest.JsonStore({ + var repositoryStore = new Ext.data.GroupingStore({ proxy: new Ext.data.HttpProxy({ url: restUrl + 'repositories.json', disableCaching: false }), + reader: new Ext.data.JsonReader({ + fields: [ 'id', 'name', 'type', 'contact', 'description', 'creationDate', 'url', 'public', 'permissions', 'properties' ] + }), id: 'id', - fields: [ 'id', 'name', 'type', 'contact', 'description', 'creationDate', 'url', 'public', 'permissions', 'properties' ], sortInfo: { field: 'name' }, + autoDestroy: true, + autoLoad: true, + groupField: 'name', listeners: { load: { fn: this.storeLoad, @@ -69,7 +74,7 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { width: 125 }, columns: [ - {id: 'name', header: this.colNameText, dataIndex: 'name'}, + {id: 'name', header: this.colNameText, dataIndex: 'name', renderer: this.renderName, groupRenderer: this.renderGroupName, scope: this}, {id: 'type', header: this.colTypeText, dataIndex: 'type', renderer: this.renderRepositoryType, width: 80}, {id: 'contact', header: this.colContactText, dataIndex: 'contact', renderer: this.renderMailto}, {id: 'description', header: this.colDescriptionText, dataIndex: 'description'}, @@ -88,13 +93,38 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { fn: this.onFallBelowMinHeight, scope: this } - } + }, + view: new Ext.grid.GroupingView({ + forceFit: true, + groupMode: 'display', + groupTextTpl: '{group} ({[values.rs.length]} {[values.rs.length > 1 ? "Repositories" : "Repository"]})' + }) }; Ext.apply(this, Ext.apply(this.initialConfig, config)); Sonia.repository.Grid.superclass.initComponent.apply(this, arguments); }, + renderName: function(v, meta, record, rowIndex, colIndex, store){ + // TODO check if grouping is enabled + var i = v.lastIndexOf('/'); + if ( i > 0 ){ + v = v.substring(i+1); + } + return v; + }, + + renderGroupName: function(v){ + var i = v.lastIndexOf('/'); + if ( i > 0 ){ + v = v.substring(0, i); + } else { + // TODO find better text + v = 'main'; + } + return v; + }, + storeLoad: function(){ if (this.searchValue){ this.filterStore(); From 86d1926104d815a9051e642e529389e28b04b77f Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Wed, 26 Oct 2011 08:53:02 +0200 Subject: [PATCH 07/21] fix sort and render methods of new group grid --- .../js/repository/sonia.repository.grid.js | 106 +++++++++++++++--- 1 file changed, 89 insertions(+), 17 deletions(-) diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js index 26de9b5704..5f8783cf1e 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js @@ -41,6 +41,9 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { searchValue: null, typeFilter: null, + + // TODO find better text + mainGroup: 'main', initComponent: function(){ @@ -50,7 +53,30 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { disableCaching: false }), reader: new Ext.data.JsonReader({ - fields: [ 'id', 'name', 'type', 'contact', 'description', 'creationDate', 'url', 'public', 'permissions', 'properties' ] + fields: [{ + name: 'id' + },{ + name: 'group', + convert: this.convertToGroup + },{ + name: 'name' + },{ + name: 'type' + },{ + name: 'contact' + },{ + name: 'description' + },{ + name: 'creationDate' + },{ + name:'url' + },{ + name: 'public' + },{ + name:'permissions' + },{ + name: 'properties' + }] }), id: 'id', sortInfo: { @@ -58,7 +84,10 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { }, autoDestroy: true, autoLoad: true, - groupField: 'name', + remoteGroup: false, + groupOnSort: false, + groupField: 'group', + groupDir: 'AES', listeners: { load: { fn: this.storeLoad, @@ -73,14 +102,46 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { scope: this, width: 125 }, - columns: [ - {id: 'name', header: this.colNameText, dataIndex: 'name', renderer: this.renderName, groupRenderer: this.renderGroupName, scope: this}, - {id: 'type', header: this.colTypeText, dataIndex: 'type', renderer: this.renderRepositoryType, width: 80}, - {id: 'contact', header: this.colContactText, dataIndex: 'contact', renderer: this.renderMailto}, - {id: 'description', header: this.colDescriptionText, dataIndex: 'description'}, - {id: 'creationDate', header: this.colCreationDateText, dataIndex: 'creationDate', renderer: Ext.util.Format.formatTimestamp}, - {id: 'Url', header: this.colUrlText, dataIndex: 'url', renderer: this.renderUrl, width: 250} - ] + columns: [{ + id: 'name', + header: this.colNameText, + dataIndex: 'name', + renderer: this.renderName, + scope: this + },{ + id: 'type', + header: this.colTypeText, + dataIndex: 'type', + renderer: this.renderRepositoryType, + width: 80 + },{ + id: 'contact', + header: this.colContactText, + dataIndex: 'contact', + renderer: this.renderMailto + },{ + id: 'description', + header: this.colDescriptionText, + dataIndex: 'description' + },{ + id: 'creationDate', + header: this.colCreationDateText, + dataIndex: 'creationDate', + renderer: Ext.util.Format.formatTimestamp + },{ + id: 'Url', + header: this.colUrlText, + dataIndex: 'url', + renderer: this.renderUrl, + width: 250 + },{ + id: 'group', + dataIndex: 'group', + hidden: true, + hideable: false, + groupRenderer: this.renderGroupName, + scope: this + }] }); var config = { @@ -95,8 +156,12 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { } }, view: new Ext.grid.GroupingView({ + // TODO configurable + enableGrouping: true, + enableNoGroups: false, forceFit: true, - groupMode: 'display', + groupMode: 'value', + enableGroupingMenu: false, groupTextTpl: '{group} ({[values.rs.length]} {[values.rs.length > 1 ? "Repositories" : "Repository"]})' }) }; @@ -105,6 +170,17 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { Sonia.repository.Grid.superclass.initComponent.apply(this, arguments); }, + convertToGroup: function(v, data){ + var name = data.name; + var i = name.lastIndexOf('/'); + if ( i > 0 ){ + name = name.substring(0, i); + } else { + name = "zzz__"; + } + return name; + }, + renderName: function(v, meta, record, rowIndex, colIndex, store){ // TODO check if grouping is enabled var i = v.lastIndexOf('/'); @@ -115,12 +191,8 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { }, renderGroupName: function(v){ - var i = v.lastIndexOf('/'); - if ( i > 0 ){ - v = v.substring(0, i); - } else { - // TODO find better text - v = 'main'; + if (v == 'zzz__'){ + v = this.mainGroup; } return v; }, From 9135653c343013dd33c54663c63f668c190fb375 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Wed, 26 Oct 2011 09:36:12 +0200 Subject: [PATCH 08/21] added switch to toggle repository grouping view --- .../main/java/sonia/scm/ScmClientConfig.java | 41 +++++++++++++++++++ .../sonia/scm/config/ScmConfiguration.java | 30 ++++++++++++++ .../resources/AuthenticationResource.java | 3 +- .../js/config/sonia.config.scmconfigpanel.js | 12 ++++++ .../js/repository/sonia.repository.grid.js | 13 +++++- 5 files changed, 96 insertions(+), 3 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/ScmClientConfig.java b/scm-core/src/main/java/sonia/scm/ScmClientConfig.java index 6bb6600120..1337655bd6 100644 --- a/scm-core/src/main/java/sonia/scm/ScmClientConfig.java +++ b/scm-core/src/main/java/sonia/scm/ScmClientConfig.java @@ -59,6 +59,20 @@ public class ScmClientConfig this.dateFormat = dateFormat; } + /** + * Constructs {@link ScmClientConfig} object + * + * @since 1.9 + * + * @param dateFormat + * @param enableGroupingGrid + */ + public ScmClientConfig(String dateFormat, boolean enableGroupingGrid) + { + this.dateFormat = dateFormat; + this.enableGroupingGrid = enableGroupingGrid; + } + //~--- get methods ---------------------------------------------------------- /** @@ -74,6 +88,18 @@ public class ScmClientConfig return dateFormat; } + /** + * Returns true if the grouping of repositories is enabled. + * + * @since 1.9 + * + * @return true if the grouping of repositories is enabled + */ + public boolean isEnableGroupingGrid() + { + return enableGroupingGrid; + } + //~--- set methods ---------------------------------------------------------- /** @@ -88,8 +114,23 @@ public class ScmClientConfig this.dateFormat = dateFormat; } + /** + * Enables or disables the grouping of repositories. + * + * @since 1.9 + * + * @param enableGroupingGrid - true to enable repository grouping + */ + public void setEnableGroupingGrid(boolean enableGroupingGrid) + { + this.enableGroupingGrid = enableGroupingGrid; + } + //~--- fields --------------------------------------------------------------- /** Field description */ private String dateFormat; + + /** Field description */ + private boolean enableGroupingGrid = true; } 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 35c55ab8a0..eccc2d40c5 100644 --- a/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java +++ b/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java @@ -164,6 +164,7 @@ public class ScmConfiguration this.proxyPassword = other.proxyPassword; this.forceBaseUrl = other.forceBaseUrl; this.baseUrl = other.baseUrl; + this.enableGroupingGrid = other.enableGroupingGrid; // deprecated fields this.sslPort = other.sslPort; @@ -345,6 +346,19 @@ public class ScmConfiguration return anonymousAccessEnabled; } + /** + * Method description + * + * + * @since 1.9 + * + * @return + */ + public boolean isEnableGroupingGrid() + { + return enableGroupingGrid; + } + /** * Returns true if port forwarding is enabled. * @@ -451,6 +465,19 @@ public class ScmConfiguration this.dateFormat = dateFormat; } + /** + * Method description + * + * + * @since 1.9 + * + * @param enableGroupingGrid + */ + public void setEnableGroupingGrid(boolean enableGroupingGrid) + { + this.enableGroupingGrid = enableGroupingGrid; + } + /** * Method description * @@ -658,6 +685,9 @@ public class ScmConfiguration private Set listeners = new HashSet(); + /** Field description */ + private boolean enableGroupingGrid = false; + /** * JavaScript date format, see http://jacwright.com/projects/javascript/date_format */ diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java index c170bd1f59..47d20b39dc 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java @@ -247,7 +247,8 @@ public class AuthenticationResource { return new ScmState(contextProvider, securityContext, repositoryManger.getConfiguredTypes(), - new ScmClientConfig(configuration.getDateFormat())); + new ScmClientConfig(configuration.getDateFormat(), + configuration.isEnableGroupingGrid())); } //~--- fields --------------------------------------------------------------- diff --git a/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js b/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js index 579d05f13e..657e5e67d6 100644 --- a/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js +++ b/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js @@ -57,6 +57,9 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{ baseUrlText: 'Base Url', forceBaseUrlText: 'Force Base Url', + // TODO i18n + enableGroupingGridText: 'Enable repository Groups', + // help servernameHelpText: 'The name of this server. This name will be part of the repository url.', @@ -79,6 +82,9 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{ proxyPasswordHelpText: 'The password for the proxy server authentication.', baseUrlHelpText: 'The url of the application (with context path) i.e. http://localhost:8080/scm', forceBaseUrlHelpText: 'Redirects to the base url if the request comes from a other url', + + // TODO i18n + enableGroupingGridHelpText: 'Enable repository Groups. A complete page reload is required after a change of this value.', initComponent: function(){ @@ -99,6 +105,12 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{ name: 'force-base-url', inputValue: 'true', helpText: this.forceBaseUrlHelpText + },{ + xtype: 'checkbox', + fieldLabel: this.enableGroupingGridText, + name: 'enableGroupingGrid', + inputValue: 'true', + helpText: this.enableGroupingGridHelpText },{ xtype: 'textfield', fieldLabel: this.dateFormatText, diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js index 5f8783cf1e..b08d55330e 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js @@ -144,6 +144,16 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { }] }); + if (debug){ + var msg = "grouping is "; + if ( state.clientConfig.enableGroupingGrid ){ + msg += "enabled"; + } else { + msg += "disabled"; + } + console.debug( msg ); + } + var config = { autoExpandColumn: 'description', store: repositoryStore, @@ -156,8 +166,7 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { } }, view: new Ext.grid.GroupingView({ - // TODO configurable - enableGrouping: true, + enableGrouping: state.clientConfig.enableGroupingGrid, enableNoGroups: false, forceFit: true, groupMode: 'value', From fc16bca79486f5719c769625c1667b8c0234c7af Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Wed, 26 Oct 2011 18:45:33 +0200 Subject: [PATCH 09/21] enable grouping view by default --- .../main/java/sonia/scm/ScmClientConfig.java | 23 ++++++++++--------- .../sonia/scm/config/ScmConfiguration.java | 17 ++++++-------- .../resources/AuthenticationResource.java | 2 +- .../js/config/sonia.config.scmconfigpanel.js | 10 ++++---- .../js/repository/sonia.repository.grid.js | 8 +++---- 5 files changed, 29 insertions(+), 31 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/ScmClientConfig.java b/scm-core/src/main/java/sonia/scm/ScmClientConfig.java index 1337655bd6..9cfcd86d25 100644 --- a/scm-core/src/main/java/sonia/scm/ScmClientConfig.java +++ b/scm-core/src/main/java/sonia/scm/ScmClientConfig.java @@ -65,12 +65,12 @@ public class ScmClientConfig * @since 1.9 * * @param dateFormat - * @param enableGroupingGrid + * @param disableGroupingGrid true to disable repository grouping */ - public ScmClientConfig(String dateFormat, boolean enableGroupingGrid) + public ScmClientConfig(String dateFormat, boolean disableGroupingGrid) { this.dateFormat = dateFormat; - this.enableGroupingGrid = enableGroupingGrid; + this.disableGroupingGrid = disableGroupingGrid; } //~--- get methods ---------------------------------------------------------- @@ -89,15 +89,15 @@ public class ScmClientConfig } /** - * Returns true if the grouping of repositories is enabled. + * Returns true if the grouping of repositories is disabled. * * @since 1.9 * - * @return true if the grouping of repositories is enabled + * @return true if the grouping of repositories is disabled */ - public boolean isEnableGroupingGrid() + public boolean isDisableGroupingGrid() { - return enableGroupingGrid; + return disableGroupingGrid; } //~--- set methods ---------------------------------------------------------- @@ -119,11 +119,12 @@ public class ScmClientConfig * * @since 1.9 * - * @param enableGroupingGrid - true to enable repository grouping + * + * @param disableGroupingGrid */ - public void setEnableGroupingGrid(boolean enableGroupingGrid) + public void setDisableGroupingGrid(boolean disableGroupingGrid) { - this.enableGroupingGrid = enableGroupingGrid; + this.disableGroupingGrid = disableGroupingGrid; } //~--- fields --------------------------------------------------------------- @@ -132,5 +133,5 @@ public class ScmClientConfig private String dateFormat; /** Field description */ - private boolean enableGroupingGrid = true; + private boolean disableGroupingGrid = true; } 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 eccc2d40c5..1d8163e14b 100644 --- a/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java +++ b/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java @@ -164,7 +164,7 @@ public class ScmConfiguration this.proxyPassword = other.proxyPassword; this.forceBaseUrl = other.forceBaseUrl; this.baseUrl = other.baseUrl; - this.enableGroupingGrid = other.enableGroupingGrid; + this.disableGroupingGrid = other.disableGroupingGrid; // deprecated fields this.sslPort = other.sslPort; @@ -349,14 +349,12 @@ public class ScmConfiguration /** * Method description * - * * @since 1.9 - * * @return */ - public boolean isEnableGroupingGrid() + public boolean isDisableGroupingGrid() { - return enableGroupingGrid; + return disableGroupingGrid; } /** @@ -468,14 +466,13 @@ public class ScmConfiguration /** * Method description * - * * @since 1.9 * - * @param enableGroupingGrid + * @param disableGroupingGrid */ - public void setEnableGroupingGrid(boolean enableGroupingGrid) + public void setDisableGroupingGrid(boolean disableGroupingGrid) { - this.enableGroupingGrid = enableGroupingGrid; + this.disableGroupingGrid = disableGroupingGrid; } /** @@ -686,7 +683,7 @@ public class ScmConfiguration new HashSet(); /** Field description */ - private boolean enableGroupingGrid = false; + private boolean disableGroupingGrid = false; /** * JavaScript date format, see http://jacwright.com/projects/javascript/date_format diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java index 47d20b39dc..531228a87b 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java @@ -248,7 +248,7 @@ public class AuthenticationResource return new ScmState(contextProvider, securityContext, repositoryManger.getConfiguredTypes(), new ScmClientConfig(configuration.getDateFormat(), - configuration.isEnableGroupingGrid())); + configuration.isDisableGroupingGrid())); } //~--- fields --------------------------------------------------------------- diff --git a/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js b/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js index 657e5e67d6..0ca5e4772d 100644 --- a/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js +++ b/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js @@ -58,7 +58,7 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{ forceBaseUrlText: 'Force Base Url', // TODO i18n - enableGroupingGridText: 'Enable repository Groups', + disableGroupingGridText: 'Disable repository Groups', // help @@ -84,7 +84,7 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{ forceBaseUrlHelpText: 'Redirects to the base url if the request comes from a other url', // TODO i18n - enableGroupingGridHelpText: 'Enable repository Groups. A complete page reload is required after a change of this value.', + disableGroupingGridHelpText: 'Disable repository Groups. A complete page reload is required after a change of this value.', initComponent: function(){ @@ -107,10 +107,10 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{ helpText: this.forceBaseUrlHelpText },{ xtype: 'checkbox', - fieldLabel: this.enableGroupingGridText, - name: 'enableGroupingGrid', + fieldLabel: this.disableGroupingGridText, + name: 'disableGroupingGrid', inputValue: 'true', - helpText: this.enableGroupingGridHelpText + helpText: this.disableGroupingGridHelpText },{ xtype: 'textfield', fieldLabel: this.dateFormatText, diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js index b08d55330e..6bc75e1dd5 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js @@ -146,10 +146,10 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { if (debug){ var msg = "grouping is "; - if ( state.clientConfig.enableGroupingGrid ){ - msg += "enabled"; - } else { + if ( state.clientConfig.disableGroupingGrid ){ msg += "disabled"; + } else { + msg += "enabled"; } console.debug( msg ); } @@ -166,7 +166,7 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { } }, view: new Ext.grid.GroupingView({ - enableGrouping: state.clientConfig.enableGroupingGrid, + enableGrouping: ! state.clientConfig.disableGroupingGrid, enableNoGroups: false, forceFit: true, groupMode: 'value', From fe9d6f06e6698a2ac3482891cb70eb1900773268 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Fri, 11 Nov 2011 13:24:20 +0100 Subject: [PATCH 10/21] improve loggin of jaxbstore --- .../main/java/sonia/scm/store/JAXBStore.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/scm-webapp/src/main/java/sonia/scm/store/JAXBStore.java b/scm-webapp/src/main/java/sonia/scm/store/JAXBStore.java index dc01ff908b..d17906bad1 100644 --- a/scm-webapp/src/main/java/sonia/scm/store/JAXBStore.java +++ b/scm-webapp/src/main/java/sonia/scm/store/JAXBStore.java @@ -69,6 +69,8 @@ public class JAXBStore implements Store */ public JAXBStore(Class type, File configFile) { + this.type = type; + try { context = JAXBContext.newInstance(type); @@ -91,6 +93,11 @@ public class JAXBStore implements Store @Override public T get() { + if (logger.isDebugEnabled()) + { + logger.debug("load {} from store {}", type, configFile); + } + T result = null; if (configFile.exists()) @@ -108,6 +115,17 @@ public class JAXBStore implements Store return result; } + /** + * Method description + * + * + * @return + */ + public Class getType() + { + return type; + } + //~--- set methods ---------------------------------------------------------- /** @@ -145,4 +163,7 @@ public class JAXBStore implements Store /** Field description */ private JAXBContext context; + + /** Field description */ + private Class type; } From fc1688a73d3b97988916a6390ff6c072ee5bd256 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 19 Nov 2011 13:11:04 +0100 Subject: [PATCH 11/21] remove unused method --- .../src/main/java/sonia/scm/web/HgCGIServlet.java | 13 ------------- 1 file changed, 13 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 9e5219ca57..30e6828b7f 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 @@ -247,19 +247,6 @@ public class HgCGIServlet extends HttpServlet return python; } - /** - * Method description - * - * - * @param repositoryname - * - * @return - */ - private Repository getRepository(String repositoryname) - { - return repositoryManager.get(HgRepositoryHandler.TYPE_NAME, repositoryname); - } - //~--- fields --------------------------------------------------------------- /** Field description */ From 589a5a735456472d84d511cd72d2bcf677eae94b Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 19 Nov 2011 13:12:04 +0100 Subject: [PATCH 12/21] remove unused repository manager --- .../src/main/java/sonia/scm/web/HgCGIServlet.java | 6 ------ 1 file changed, 6 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 30e6828b7f..b74d46612c 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 @@ -102,7 +102,6 @@ public class HgCGIServlet extends HttpServlet * * @param cgiExecutorFactory * @param configuration - * @param repositoryManager * @param repositoryProvider * @param handler * @param hookManager @@ -110,13 +109,11 @@ public class HgCGIServlet extends HttpServlet @Inject public HgCGIServlet(CGIExecutorFactory cgiExecutorFactory, ScmConfiguration configuration, - RepositoryManager repositoryManager, Provider repositoryProvider, HgRepositoryHandler handler, HgHookManager hookManager) { this.cgiExecutorFactory = cgiExecutorFactory; this.configuration = configuration; - this.repositoryManager = repositoryManager; this.repositoryProvider = repositoryProvider; this.handler = handler; this.hookManager = hookManager; @@ -264,9 +261,6 @@ public class HgCGIServlet extends HttpServlet /** Field description */ private HgHookManager hookManager; - /** Field description */ - private RepositoryManager repositoryManager; - /** Field description */ private Provider repositoryProvider; } From 2d04f991ee0c2aa87862fe358c74e343e7e2bc25 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 19 Nov 2011 14:01:04 +0100 Subject: [PATCH 13/21] use stable version 1.3.5.7 of svnkt-dav --- scm-plugins/scm-svn-plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-plugins/scm-svn-plugin/pom.xml b/scm-plugins/scm-svn-plugin/pom.xml index 6e646b9004..7b74b2b464 100644 --- a/scm-plugins/scm-svn-plugin/pom.xml +++ b/scm-plugins/scm-svn-plugin/pom.xml @@ -53,7 +53,7 @@ - 1.3.5.8-SNAPSHOT + 1.3.5.7 From b4fc971fa9dbd9f292c9ca2efbaa064387811bfe Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 24 Nov 2011 21:05:34 +0100 Subject: [PATCH 14/21] fix getByTypeAndName method for directory structure --- .../sonia/scm/api/rest/resources/RepositoryResource.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 72a9746e77..89d41e13df 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 @@ -416,11 +416,10 @@ public class RepositoryResource * @return the {@link Repository} with the specified type and name */ @GET - @Path("{type}/{name}") + @Path("{type: [a-z]+}/{name: .*}") @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @TypeHint(Repository.class) - public Response getByTypeAndName(@Context Request request, - @PathParam("type") String type, + public Response getByTypeAndName(@PathParam("type") String type, @PathParam("name") String name) { Response response = null; From 7d8b46f1a962ce3186542d17a7897c1c547e3f2b Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 24 Nov 2011 21:06:12 +0100 Subject: [PATCH 15/21] added integration tests for getByTypeAndName --- .../sonia/scm/it/GetRepositoriesITCase.java | 196 ++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 scm-webapp/src/test/java/sonia/scm/it/GetRepositoriesITCase.java diff --git a/scm-webapp/src/test/java/sonia/scm/it/GetRepositoriesITCase.java b/scm-webapp/src/test/java/sonia/scm/it/GetRepositoriesITCase.java new file mode 100644 index 0000000000..6978c897f8 --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/it/GetRepositoriesITCase.java @@ -0,0 +1,196 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.it; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import sonia.scm.repository.Repository; +import sonia.scm.repository.RepositoryTestData; +import sonia.scm.util.IOUtil; + +import static org.junit.Assert.*; + +import static sonia.scm.it.IntegrationTestUtil.*; +import static sonia.scm.it.RepositoryITUtil.*; + +//~--- JDK imports ------------------------------------------------------------ + +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; + +import java.io.IOException; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * + * @author Sebastian Sdorra + */ +@RunWith(Parameterized.class) +public class GetRepositoriesITCase extends AbstractAdminITCaseBase +{ + + /** + * Constructs ... + * + * + * @param repositoryType + */ + public GetRepositoriesITCase(String repositoryType) + { + this.repositoryType = repositoryType; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Parameters + public static Collection createParameters() + { + Collection params = new ArrayList(); + + params.add(new String[] { "git" }); + params.add(new String[] { "svn" }); + + if (IOUtil.search("hg") != null) + { + params.add(new String[] { "hg" }); + } + + return params; + } + + /** + * Method description + * + * + * @throws IOException + */ + @After + public void cleanup() throws IOException + { + deleteRepository(client, repository.getId()); + } + + /** + * Method description + * + */ + @Test + public void testGetById() + { + repository = RepositoryTestData.createHeartOfGold(repositoryType); + repository = createRepository(client, repository); + + String id = repository.getId(); + + assertNotNull(id); + + Repository r = getRepositoryById(client, id); + + assertEquals(id, r.getId()); + } + + /** + * Method description + * + */ + @Test + public void testGetByTypeAndName() + { + repository = RepositoryTestData.create42Puzzle(repositoryType); + testGetByTypeAndName(repository); + } + + /** + * Method description + * + */ + @Test + public void testGetByTypeAndNameWithDirectoryStructure() + { + repository = + RepositoryTestData.createRestaurantAtTheEndOfTheUniverse(repositoryType); + repository.setName("test/".concat(repository.getName())); + testGetByTypeAndName(repository); + } + + /** + * Method description + * + * + * @param repository + */ + private void testGetByTypeAndName(Repository repo) + { + repository = createRepository(client, repo); + + String name = repository.getName(); + WebResource wr = createResource( + client, + "repositories/".concat(repositoryType).concat( + "/").concat(name)); + ClientResponse response = wr.get(ClientResponse.class); + + assertNotNull(response); + + Repository r = response.getEntity(Repository.class); + + response.close(); + assertNotNull(r); + assertEquals(repository.getId(), r.getId()); + assertEquals(repository.getName(), r.getName()); + assertEquals(repository.getType(), r.getType()); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private Repository repository; + + /** Field description */ + private String repositoryType; +} From 6e49c1ff197cce4474963e074d49cd8eb6d013c1 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 24 Nov 2011 22:09:58 +0100 Subject: [PATCH 16/21] fix repository create issue with directory structures --- .../AbstractSimpleRepositoryHandler.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) 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 083f0e159a..0c15f08733 100644 --- a/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java +++ b/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java @@ -64,6 +64,9 @@ public abstract class AbstractSimpleRepositoryHandler Date: Thu, 24 Nov 2011 22:27:25 +0100 Subject: [PATCH 17/21] improve logging --- .../repository/AbstractSimpleRepositoryHandler.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) 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 0c15f08733..9d29db8a87 100644 --- a/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java +++ b/scm-core/src/main/java/sonia/scm/repository/AbstractSimpleRepositoryHandler.java @@ -343,10 +343,20 @@ public abstract class AbstractSimpleRepositoryHandler Date: Thu, 24 Nov 2011 22:40:45 +0100 Subject: [PATCH 18/21] fix git isRepository check --- .../scm/repository/GitRepositoryHandler.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryHandler.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryHandler.java index c1cbdb912e..e0ff384b91 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryHandler.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryHandler.java @@ -62,6 +62,9 @@ public class GitRepositoryHandler extends AbstractSimpleRepositoryHandler { + /** Field description */ + public static final String DIRECTORY_REFS = "refs"; + /** Field description */ public static final String TYPE_DISPLAYNAME = "Git"; @@ -267,4 +270,18 @@ public class GitRepositoryHandler { return GitConfig.class; } + + /** + * Method description + * + * + * @param directory + * + * @return + */ + @Override + protected boolean isRepository(File directory) + { + return new File(directory, DIRECTORY_REFS).exists(); + } } From f9e91a04fd41e1954a1cbe3d24139ea9cce237ac Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 24 Nov 2011 22:43:16 +0100 Subject: [PATCH 19/21] added integration tests for repository creation --- .../scm/it/CreateRepositoriesITCase.java | 193 ++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 scm-webapp/src/test/java/sonia/scm/it/CreateRepositoriesITCase.java diff --git a/scm-webapp/src/test/java/sonia/scm/it/CreateRepositoriesITCase.java b/scm-webapp/src/test/java/sonia/scm/it/CreateRepositoriesITCase.java new file mode 100644 index 0000000000..6ef841b2df --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/it/CreateRepositoriesITCase.java @@ -0,0 +1,193 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.it; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import sonia.scm.repository.Repository; +import sonia.scm.repository.RepositoryTestData; +import sonia.scm.util.IOUtil; + +import static org.junit.Assert.*; + +import static sonia.scm.it.IntegrationTestUtil.*; +import static sonia.scm.it.RepositoryITUtil.*; + +//~--- JDK imports ------------------------------------------------------------ + +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; + +import java.io.IOException; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * + * @author Sebastian Sdorra + */ +@RunWith(Parameterized.class) +public class CreateRepositoriesITCase extends AbstractAdminITCaseBase +{ + + /** + * Constructs ... + * + * + * @param repositoryType + */ + public CreateRepositoriesITCase(String repositoryType) + { + System.out.append("==> CreateRepositoriesITCase - ").println( + repositoryType); + this.repositoryType = repositoryType; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Parameters + public static Collection createParameters() + { + Collection params = new ArrayList(); + + params.add(new String[] { "git" }); + params.add(new String[] { "git" }); + + if (IOUtil.search("hg") != null) + { + params.add(new String[] { "git" }); + } + + return params; + } + + /** + * Method description + * + * + * @throws IOException + */ + @After + public void cleanup() throws IOException + { + deleteRepository(client, repository.getId()); + } + + /** + * Method description + * + */ + @Test + public void testCreate() + { + repository = RepositoryTestData.createHeartOfGold(repositoryType); + repository = createRepository(client, repository); + } + + /** + * Method description + * + */ + @Test + public void testCreateAllreadyExists() + { + repository = RepositoryTestData.create42Puzzle(repositoryType); + repository = createRepository(client, repository); + + WebResource wr = createResource(client, "repositories"); + ClientResponse response = + wr.post(ClientResponse.class, + RepositoryTestData.create42Puzzle(repositoryType)); + + assertNotNull(response); + assertEquals(500, response.getStatus()); + response.close(); + } + + /** + * Method description + * + */ + @Test + public void testCreateAllreadyExistsWithStructure() + { + repository = RepositoryTestData.create42Puzzle(repositoryType); + repository = createRepository(client, repository); + + Repository r = RepositoryTestData.create42Puzzle(repositoryType); + + r.setName(r.getName() + "/" + r.getName()); + + WebResource wr = createResource(client, "repositories"); + ClientResponse response = wr.post(ClientResponse.class, r); + + assertNotNull(response); + System.out.println( response.getStatus() ); + assertEquals(500, response.getStatus()); + response.close(); + } + + /** + * Method description + * + */ + @Test + public void testCreateWithStructure() + { + repository = RepositoryTestData.createHeartOfGold(repositoryType); + repository.setName("test/".concat(repository.getName())); + repository = createRepository(client, repository); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private Repository repository; + + /** Field description */ + private String repositoryType; +} From cf023c30be828d2284d47bdf8bbfa27150734883 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 26 Nov 2011 12:38:39 +0100 Subject: [PATCH 20/21] improve repository tests --- .../sonia/scm/it/RepositoryITCaseBase.java | 75 +++++++++++-------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/scm-webapp/src/test/java/sonia/scm/it/RepositoryITCaseBase.java b/scm-webapp/src/test/java/sonia/scm/it/RepositoryITCaseBase.java index 02810e5eb9..c57f85237e 100644 --- a/scm-webapp/src/test/java/sonia/scm/it/RepositoryITCaseBase.java +++ b/scm-webapp/src/test/java/sonia/scm/it/RepositoryITCaseBase.java @@ -50,6 +50,7 @@ import sonia.scm.repository.client.RepositoryClientFactory; import sonia.scm.user.User; import sonia.scm.user.UserTestData; import sonia.scm.util.IOUtil; +import sonia.scm.util.Util; import static org.junit.Assert.*; @@ -220,36 +221,7 @@ public class RepositoryITCaseBase for (Type t : state.getRepositoryTypes()) { - if (t.getName().equals("git")) - { - Repository gitRepository = createTestRepository("git", owner, write, - read); - - params.add(new Object[] - { - gitRepository, owner, write, read, noperm, "secret" - }); - } - else if (t.getName().equals("svn")) - { - Repository svnRepository = createTestRepository("svn", owner, write, - read); - - params.add(new Object[] - { - svnRepository, owner, write, read, noperm, "secret" - }); - } - else if (t.getName().equals("hg")) - { - Repository hgRepository = createTestRepository("hg", owner, write, - read); - - params.add(new Object[] - { - hgRepository, owner, write, read, noperm, "secret" - }); - } + appendTestParemeter(params, t.getName(), owner, write, read, noperm); } return params; @@ -259,6 +231,40 @@ public class RepositoryITCaseBase * Method description * * + * @param params + * @param type + * @param owner + * @param write + * @param read + * @param noperm + * + * @throws IOException + * @throws RepositoryClientException + */ + private static void appendTestParemeter(Collection params, + String type, User owner, User write, User read, User noperm) + throws RepositoryClientException, IOException + { + Repository repository = createTestRepository(null, type, owner, write, + read); + + params.add(new Object[] + { + repository, owner, write, read, noperm, "secret" + }); + repository = createTestRepository("test", type, owner, write, read); + params.add(new Object[] + { + repository, owner, write, read, noperm, "secret" + }); + } + + /** + * Method description + * + * + * + * @param prefix * @param type * @param owner * @param write @@ -269,13 +275,18 @@ public class RepositoryITCaseBase * @throws IOException * @throws RepositoryClientException */ - private static Repository createTestRepository(String type, User owner, - User write, User read) + private static Repository createTestRepository(String prefix, String type, + User owner, User write, User read) throws RepositoryClientException, IOException { Client client = createAdminClient(); Repository repository = RepositoryTestData.createHeartOfGold(type); + if (Util.isNotEmpty(prefix)) + { + repository.setName(prefix.concat("/").concat(repository.getName())); + } + //J- repository.setPermissions(Arrays.asList( new Permission(owner.getName(), PermissionType.OWNER), From 689536eadac6722e052288c5c342a99c117694e7 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 26 Nov 2011 12:39:20 +0100 Subject: [PATCH 21/21] close branch issue-47