diff --git a/maven/pom.xml b/maven/pom.xml
index e584ea664d..886e45927a 100644
--- a/maven/pom.xml
+++ b/maven/pom.xml
@@ -6,13 +6,13 @@
sonia.scmscm
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.mavenscm-maven-pluginspom
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-maven-plugins
diff --git a/maven/scm-maven-plugin/pom.xml b/maven/scm-maven-plugin/pom.xml
index beea26afd7..304335efd5 100644
--- a/maven/scm-maven-plugin/pom.xml
+++ b/maven/scm-maven-plugin/pom.xml
@@ -6,12 +6,12 @@
scm-maven-pluginssonia.scm.maven
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.mavenscm-maven-plugin
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTmaven-pluginscm-maven-plugin
diff --git a/maven/scm-plugin-archetype/pom.xml b/maven/scm-plugin-archetype/pom.xml
index 931bad0a01..0b354ee0bb 100644
--- a/maven/scm-plugin-archetype/pom.xml
+++ b/maven/scm-plugin-archetype/pom.xml
@@ -6,12 +6,12 @@
scm-maven-pluginssonia.scm.maven
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.mavenscm-plugin-archetype
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-plugin-archetype
diff --git a/pom.xml b/pom.xml
index db1bb49860..c09c85f055 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
sonia.scmscmpom
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOT
The easiest way to share your Git, Mercurial
and Subversion repositories over http.
@@ -390,8 +390,8 @@
4.10
- 1.6.4
- 1.0.4
+ 1.6.6
+ 1.0.62.53.0
@@ -401,8 +401,8 @@
7.6.4.v20120524
- 1.3.0.201202151440-r
- 1.7.4-1.v1
+ 2.0.0.201206130900-r
+ 1.7.5-11.6
diff --git a/scm-clients/pom.xml b/scm-clients/pom.xml
index 2a8f241d6a..2965268154 100644
--- a/scm-clients/pom.xml
+++ b/scm-clients/pom.xml
@@ -6,13 +6,13 @@
sonia.scmscm
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.clientsscm-clientspom
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-clients
@@ -26,7 +26,7 @@
sonia.scmscm-core
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOT
diff --git a/scm-clients/scm-cli-client/pom.xml b/scm-clients/scm-cli-client/pom.xml
index c3eb4276fa..e4c2b720b7 100644
--- a/scm-clients/scm-cli-client/pom.xml
+++ b/scm-clients/scm-cli-client/pom.xml
@@ -6,12 +6,12 @@
scm-clientssonia.scm.clients
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.clientsscm-cli-client
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-cli-client
@@ -35,7 +35,7 @@
scm-coresonia.scm
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTguice
@@ -55,7 +55,7 @@
sonia.scm.clientsscm-client-impl
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOT
diff --git a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/BooleanModifyOptionHandler.java b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/BooleanModifyOptionHandler.java
index 76d2e350de..46d18badb6 100644
--- a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/BooleanModifyOptionHandler.java
+++ b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/BooleanModifyOptionHandler.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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.cli;
//~--- non-JDK imports --------------------------------------------------------
diff --git a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/CreateRepositorySubCommand.java b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/CreateRepositorySubCommand.java
index 79e8c5a96f..52828eba25 100644
--- a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/CreateRepositorySubCommand.java
+++ b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/CreateRepositorySubCommand.java
@@ -170,7 +170,7 @@ public class CreateRepositorySubCommand extends TemplateSubCommand
Map env = new HashMap();
- env.put("repository", new RepositoryWrapper(repository));
+ env.put("repository", new RepositoryWrapper(config, repository));
renderTemplate(env, GetRepositorySubCommand.TEMPLATE);
}
diff --git a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/GetRepositorySubCommand.java b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/GetRepositorySubCommand.java
index 9e9c0fbe29..c7c497bacf 100644
--- a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/GetRepositorySubCommand.java
+++ b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/GetRepositorySubCommand.java
@@ -104,7 +104,7 @@ public class GetRepositorySubCommand extends TemplateSubCommand
{
Map env = new HashMap();
- env.put("repository", new RepositoryWrapper(repository));
+ env.put("repository", new RepositoryWrapper(config, repository));
renderTemplate(env, TEMPLATE);
}
else
diff --git a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/ListRepositoriesSubCommand.java b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/ListRepositoriesSubCommand.java
index 518bd062d5..2235781791 100644
--- a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/ListRepositoriesSubCommand.java
+++ b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/ListRepositoriesSubCommand.java
@@ -74,7 +74,7 @@ public class ListRepositoriesSubCommand extends TemplateSubCommand
List repositories = session.getRepositoryHandler().getAll();
Map env = new HashMap();
- env.put("repositories", WrapperUtil.wrapRepositories(repositories));
+ env.put("repositories", WrapperUtil.wrapRepositories(config, repositories));
renderTemplate(env, TEMPLATE);
}
}
diff --git a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/ModifyRepositorySubCommand.java b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/ModifyRepositorySubCommand.java
index 1f991fa746..5ec4c59519 100644
--- a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/ModifyRepositorySubCommand.java
+++ b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/ModifyRepositorySubCommand.java
@@ -214,7 +214,7 @@ public class ModifyRepositorySubCommand extends TemplateSubCommand
Map env = new HashMap();
- env.put("repository", new RepositoryWrapper(repository));
+ env.put("repository", new RepositoryWrapper(config, repository));
renderTemplate(env, GetRepositorySubCommand.TEMPLATE);
}
else
diff --git a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/PermissionSubCommand.java b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/PermissionSubCommand.java
index c701a45808..a6b5eba2f5 100644
--- a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/PermissionSubCommand.java
+++ b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/PermissionSubCommand.java
@@ -120,7 +120,7 @@ public abstract class PermissionSubCommand extends TemplateSubCommand
Map env = new HashMap();
- env.put("repository", new RepositoryWrapper(repository));
+ env.put("repository", new RepositoryWrapper(config, repository));
renderTemplate(env, GetRepositorySubCommand.TEMPLATE);
}
else
diff --git a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/wrapper/RepositoryWrapper.java b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/wrapper/RepositoryWrapper.java
index 68d5131cbc..216afde624 100644
--- a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/wrapper/RepositoryWrapper.java
+++ b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/wrapper/RepositoryWrapper.java
@@ -35,6 +35,7 @@ package sonia.scm.cli.wrapper;
//~--- non-JDK imports --------------------------------------------------------
+import sonia.scm.cli.config.ServerConfig;
import sonia.scm.repository.Permission;
import sonia.scm.repository.Repository;
@@ -54,10 +55,25 @@ public class RepositoryWrapper extends AbstractWrapper
* Constructs ...
*
*
+ * @param config
* @param repository
*/
- public RepositoryWrapper(Repository repository)
+ public RepositoryWrapper(ServerConfig config, Repository repository)
{
+ this(config.getServerUrl(), repository);
+ }
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param baseUrl
+ * @param repository
+ */
+ public RepositoryWrapper(String baseUrl, Repository repository)
+ {
+ this.baseUrl = baseUrl;
this.repository = repository;
}
@@ -159,7 +175,7 @@ public class RepositoryWrapper extends AbstractWrapper
*/
public String getUrl()
{
- return repository.getUrl();
+ return repository.createUrl(baseUrl);
}
/**
@@ -186,6 +202,9 @@ public class RepositoryWrapper extends AbstractWrapper
//~--- fields ---------------------------------------------------------------
+ /** Field description */
+ private String baseUrl;
+
/** Field description */
private Repository repository;
}
diff --git a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/wrapper/WrapperUtil.java b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/wrapper/WrapperUtil.java
index dce0bef3fc..f508b45039 100644
--- a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/wrapper/WrapperUtil.java
+++ b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/wrapper/WrapperUtil.java
@@ -35,6 +35,7 @@ package sonia.scm.cli.wrapper;
//~--- non-JDK imports --------------------------------------------------------
+import sonia.scm.cli.config.ServerConfig;
import sonia.scm.group.Group;
import sonia.scm.repository.Repository;
import sonia.scm.user.User;
@@ -76,18 +77,22 @@ public class WrapperUtil
* Method description
*
*
+ *
+ * @param baseUrl
+ *
+ * @param config
* @param repositories
*
* @return
*/
- public static List wrapRepositories(
+ public static List wrapRepositories(ServerConfig config,
Collection repositories)
{
List wrappers = new ArrayList();
for (Repository r : repositories)
{
- wrappers.add(new RepositoryWrapper(r));
+ wrappers.add(new RepositoryWrapper(config.getServerUrl(), r));
}
return wrappers;
diff --git a/scm-clients/scm-client-api/pom.xml b/scm-clients/scm-client-api/pom.xml
index 11c2d5b26b..b113cdbe04 100644
--- a/scm-clients/scm-client-api/pom.xml
+++ b/scm-clients/scm-client-api/pom.xml
@@ -6,13 +6,13 @@
sonia.scm.clientsscm-clients
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.clientsscm-client-apijar
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-client-api
diff --git a/scm-clients/scm-client-impl/pom.xml b/scm-clients/scm-client-impl/pom.xml
index 4bf887cab0..b0994e6702 100644
--- a/scm-clients/scm-client-impl/pom.xml
+++ b/scm-clients/scm-client-impl/pom.xml
@@ -6,13 +6,13 @@
sonia.scm.clientsscm-clients
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.clientsscm-client-impljar
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-client-impl
@@ -36,7 +36,7 @@
scm-coresonia.scm
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTaopalliance
@@ -60,7 +60,7 @@
sonia.scm.clientsscm-client-api
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOT
@@ -112,7 +112,7 @@
sonia.scmscm-test
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTtest
diff --git a/scm-core/pom.xml b/scm-core/pom.xml
index bedccaf606..141ad66a66 100644
--- a/scm-core/pom.xml
+++ b/scm-core/pom.xml
@@ -6,12 +6,12 @@
scmsonia.scm
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scmscm-core
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-core
diff --git a/scm-core/src/main/java/sonia/scm/ServletContainerDetector.java b/scm-core/src/main/java/sonia/scm/ServletContainerDetector.java
index f4f935ce9e..6038abed05 100644
--- a/scm-core/src/main/java/sonia/scm/ServletContainerDetector.java
+++ b/scm-core/src/main/java/sonia/scm/ServletContainerDetector.java
@@ -215,7 +215,7 @@ public class ServletContainerDetector
*/
public boolean isScmServer()
{
- return "scm-server".equals(System.getProperty("app-name"));
+ return "scm-server".equals(System.getProperty("app.name"));
}
/**
diff --git a/scm-core/src/main/java/sonia/scm/filter/GZipFilterConfig.java b/scm-core/src/main/java/sonia/scm/filter/GZipFilterConfig.java
index 047a56c4e4..1132ff1259 100644
--- a/scm-core/src/main/java/sonia/scm/filter/GZipFilterConfig.java
+++ b/scm-core/src/main/java/sonia/scm/filter/GZipFilterConfig.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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.filter;
/**
diff --git a/scm-core/src/main/java/sonia/scm/i18n/Bundle.java b/scm-core/src/main/java/sonia/scm/i18n/Bundle.java
index 9523948cd7..be349fddb7 100644
--- a/scm-core/src/main/java/sonia/scm/i18n/Bundle.java
+++ b/scm-core/src/main/java/sonia/scm/i18n/Bundle.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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.i18n;
//~--- non-JDK imports --------------------------------------------------------
diff --git a/scm-core/src/main/java/sonia/scm/net/HttpRequest.java b/scm-core/src/main/java/sonia/scm/net/HttpRequest.java
index 588e4dd111..68c391c646 100644
--- a/scm-core/src/main/java/sonia/scm/net/HttpRequest.java
+++ b/scm-core/src/main/java/sonia/scm/net/HttpRequest.java
@@ -174,7 +174,7 @@ public class HttpRequest
*
*
* @return
- *
+ *
* @since 1.14
*/
public boolean isDecodeGZip()
@@ -182,6 +182,42 @@ public class HttpRequest
return decodeGZip;
}
+ /**
+ * Method description
+ *
+ *
+ * @return
+ * @since 1.17
+ */
+ public boolean isDisableCertificateValidation()
+ {
+ return disableCertificateValidation;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ * @since 1.17
+ */
+ public boolean isDisableHostnameValidation()
+ {
+ return disableHostnameValidation;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ * @since 1.17
+ */
+ public boolean isIgnoreProxySettings()
+ {
+ return ignoreProxySettings;
+ }
+
//~--- set methods ----------------------------------------------------------
/**
@@ -208,15 +244,41 @@ public class HttpRequest
* @param decodeGZip
*
* @return
- *
+ *
* @since 1.14
*/
public HttpRequest setDecodeGZip(boolean decodeGZip)
{
this.decodeGZip = decodeGZip;
+
return this;
}
+ /**
+ * Method description
+ *
+ *
+ * @param disableCertificateValidation
+ * @since 1.17
+ */
+ public void setDisableCertificateValidation(
+ boolean disableCertificateValidation)
+ {
+ this.disableCertificateValidation = disableCertificateValidation;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param disableHostnameValidation
+ * @since 1.17
+ */
+ public void setDisableHostnameValidation(boolean disableHostnameValidation)
+ {
+ this.disableHostnameValidation = disableHostnameValidation;
+ }
+
/**
* Method description
*
@@ -232,6 +294,18 @@ public class HttpRequest
return this;
}
+ /**
+ * Method description
+ *
+ *
+ * @param ignoreProxySettings
+ * @since 1.17
+ */
+ public void setIgnoreProxySettings(boolean ignoreProxySettings)
+ {
+ this.ignoreProxySettings = ignoreProxySettings;
+ }
+
/**
* Method description
*
@@ -277,10 +351,19 @@ public class HttpRequest
//~--- fields ---------------------------------------------------------------
/** Field description */
- private boolean decodeGZip = false;
+ private Map> headers;
/** Field description */
- private Map> headers;
+ private boolean ignoreProxySettings = false;
+
+ /** Field description */
+ private boolean disableHostnameValidation = false;
+
+ /** Field description */
+ private boolean disableCertificateValidation = false;
+
+ /** Field description */
+ private boolean decodeGZip = false;
/** Field description */
private Map> parameters;
diff --git a/scm-core/src/main/java/sonia/scm/plugin/PluginCondition.java b/scm-core/src/main/java/sonia/scm/plugin/PluginCondition.java
index 11198ae3f8..7cae04f45c 100644
--- a/scm-core/src/main/java/sonia/scm/plugin/PluginCondition.java
+++ b/scm-core/src/main/java/sonia/scm/plugin/PluginCondition.java
@@ -42,6 +42,8 @@ import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
+import java.io.Serializable;
+
import java.util.ArrayList;
import java.util.List;
@@ -57,9 +59,14 @@ import javax.xml.bind.annotation.XmlRootElement;
*/
@XmlRootElement(name = "conditions")
@XmlAccessorType(XmlAccessType.FIELD)
-public class PluginCondition implements Cloneable
+public class PluginCondition implements Cloneable, Serializable
{
+ /** Field description */
+ private static final long serialVersionUID = 2406156062634968672L;
+
+ //~--- constructors ---------------------------------------------------------
+
/**
* Constructs ...
*
diff --git a/scm-core/src/main/java/sonia/scm/plugin/PluginInformation.java b/scm-core/src/main/java/sonia/scm/plugin/PluginInformation.java
index 4031def5a1..47363b9895 100644
--- a/scm-core/src/main/java/sonia/scm/plugin/PluginInformation.java
+++ b/scm-core/src/main/java/sonia/scm/plugin/PluginInformation.java
@@ -40,6 +40,8 @@ import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
+import java.io.Serializable;
+
import java.util.ArrayList;
import java.util.List;
@@ -55,9 +57,14 @@ import javax.xml.bind.annotation.XmlRootElement;
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "plugin-information")
-public class PluginInformation implements Validateable, Cloneable
+public class PluginInformation implements Validateable, Cloneable, Serializable
{
+ /** Field description */
+ private static final long serialVersionUID = 461382048865977206L;
+
+ //~--- methods --------------------------------------------------------------
+
/**
* Method description
*
diff --git a/scm-core/src/main/java/sonia/scm/plugin/PluginRepository.java b/scm-core/src/main/java/sonia/scm/plugin/PluginRepository.java
index 3ea5f40186..eba67110c5 100644
--- a/scm-core/src/main/java/sonia/scm/plugin/PluginRepository.java
+++ b/scm-core/src/main/java/sonia/scm/plugin/PluginRepository.java
@@ -33,13 +33,22 @@
package sonia.scm.plugin;
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.Serializable;
+
/**
*
* @author Sebastian Sdorra
*/
-public class PluginRepository
+public class PluginRepository implements Serializable
{
+ /** Field description */
+ private static final long serialVersionUID = -9504354306304731L;
+
+ //~--- constructors ---------------------------------------------------------
+
/**
* Constructs ...
*
diff --git a/scm-core/src/main/java/sonia/scm/repository/BlameLine.java b/scm-core/src/main/java/sonia/scm/repository/BlameLine.java
index 7d60e6e9f6..ff23ca8fd3 100644
--- a/scm-core/src/main/java/sonia/scm/repository/BlameLine.java
+++ b/scm-core/src/main/java/sonia/scm/repository/BlameLine.java
@@ -37,15 +37,24 @@ package sonia.scm.repository;
import com.google.common.base.Objects;
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.Serializable;
+
/**
* Single line of a file, in a {@link BlameResult}.
*
* @author Sebastian Sdorra
* @since 1.8
*/
-public class BlameLine
+public class BlameLine implements Serializable
{
+ /** Field description */
+ private static final long serialVersionUID = 2816601606921153670L;
+
+ //~--- constructors ---------------------------------------------------------
+
/**
* Constructs ...
*
diff --git a/scm-core/src/main/java/sonia/scm/repository/BlameLinePreProcessor.java b/scm-core/src/main/java/sonia/scm/repository/BlameLinePreProcessor.java
new file mode 100644
index 0000000000..68141f5aaf
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/BlameLinePreProcessor.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of SCM-Manager; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+package sonia.scm.repository;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.plugin.ExtensionPoint;
+
+/**
+ * A pre processor for {@link BlameLine} objects. A pre processor is able to
+ * modify the object before it is delivered to the user interface.
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+@ExtensionPoint
+public interface BlameLinePreProcessor extends PreProcessor
+{
+
+ /**
+ * Process the given blame line.
+ *
+ *
+ * @param blameLine blame line to process.
+ */
+ @Override
+ public void process(BlameLine blameLine);
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/BlameLinePreProcessorFactory.java b/scm-core/src/main/java/sonia/scm/repository/BlameLinePreProcessorFactory.java
new file mode 100644
index 0000000000..8ff5b6e01c
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/BlameLinePreProcessorFactory.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of SCM-Manager; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.repository;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.plugin.ExtensionPoint;
+
+/**
+ * The BlameLinePreProcessorFactory create {@link BlameLinePreProcessor}
+ * objects for a specific repository.
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+@ExtensionPoint
+public interface BlameLinePreProcessorFactory
+ extends PreProcessorFactory
+{
+
+ /**
+ * Create a new {@link BlameLinePreProcessor} for the given repository.
+ *
+ *
+ * @param repository repository
+ *
+ * @return {@link BlameLinePreProcessor} for the given repository
+ */
+ @Override
+ public BlameLinePreProcessor createPreProcessor(Repository repository);
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/BlameResult.java b/scm-core/src/main/java/sonia/scm/repository/BlameResult.java
index a1ef0db44c..3acb4928b1 100644
--- a/scm-core/src/main/java/sonia/scm/repository/BlameResult.java
+++ b/scm-core/src/main/java/sonia/scm/repository/BlameResult.java
@@ -36,9 +36,13 @@ package sonia.scm.repository;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Objects;
+import com.google.common.collect.Lists;
//~--- JDK imports ------------------------------------------------------------
+import java.io.Serializable;
+
+import java.util.Iterator;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
@@ -48,17 +52,23 @@ import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
/**
- * Class description
+ * Changeset information by line for a given file.
*
+ * TODO for 2.0 implement {@link Iterable}
*
* @author Sebastian Sdorra
* @since 1.8
*/
@XmlRootElement(name = "blame-result")
@XmlAccessorType(XmlAccessType.FIELD)
-public class BlameResult
+public class BlameResult implements Serializable, Iterable
{
+ /** Field description */
+ private static final long serialVersionUID = -8606237881465520606L;
+
+ //~--- constructors ---------------------------------------------------------
+
/**
* Constructs ...
*
@@ -131,6 +141,20 @@ public class BlameResult
return Objects.hashCode(total, blameLines);
}
+ /**
+ * Method description
+ *
+ *
+ * @return
+ *
+ * @since 1.17
+ */
+ @Override
+ public Iterator iterator()
+ {
+ return getBlameLines().iterator();
+ }
+
/**
* {@inheritDoc}
*
@@ -158,6 +182,9 @@ public class BlameResult
*/
public List getBlameLines()
{
+ if ( blameLines == null ){
+ blameLines = Lists.newArrayList();
+ }
return blameLines;
}
diff --git a/scm-core/src/main/java/sonia/scm/repository/BlameViewer.java b/scm-core/src/main/java/sonia/scm/repository/BlameViewer.java
index 6192329017..c77d5e92e4 100644
--- a/scm-core/src/main/java/sonia/scm/repository/BlameViewer.java
+++ b/scm-core/src/main/java/sonia/scm/repository/BlameViewer.java
@@ -33,6 +33,10 @@
package sonia.scm.repository;
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.api.RepositoryService;
+
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
@@ -43,7 +47,10 @@ import java.io.IOException;
*
* @author Sebastian Sdorra
* @since 1.8
+ *
+ * @deprecated use {@link RepositoryService#getBlameCommand()} instead.
*/
+@Deprecated
public interface BlameViewer
{
diff --git a/scm-core/src/main/java/sonia/scm/repository/BlameViewerProvider.java b/scm-core/src/main/java/sonia/scm/repository/BlameViewerProvider.java
index 5c2419ac16..6af34a5bf1 100644
--- a/scm-core/src/main/java/sonia/scm/repository/BlameViewerProvider.java
+++ b/scm-core/src/main/java/sonia/scm/repository/BlameViewerProvider.java
@@ -33,11 +33,18 @@
package sonia.scm.repository;
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.api.RepositoryService;
+
/**
*
* @author Sebastian Sdorra
* @since 1.8
+ *
+ * @deprecated use {@link RepositoryService#getBlameCommand()} instead.
*/
+@Deprecated
public interface BlameViewerProvider
{
diff --git a/scm-core/src/main/java/sonia/scm/repository/BlameViewerUtil.java b/scm-core/src/main/java/sonia/scm/repository/BlameViewerUtil.java
index e552a53d1f..d824b256e1 100644
--- a/scm-core/src/main/java/sonia/scm/repository/BlameViewerUtil.java
+++ b/scm-core/src/main/java/sonia/scm/repository/BlameViewerUtil.java
@@ -44,6 +44,7 @@ import org.slf4j.LoggerFactory;
import sonia.scm.NotSupportedFeatuerException;
import sonia.scm.cache.Cache;
import sonia.scm.cache.CacheManager;
+import sonia.scm.repository.api.RepositoryService;
import sonia.scm.util.AssertUtil;
//~--- JDK imports ------------------------------------------------------------
@@ -55,8 +56,11 @@ import java.io.IOException;
*
* @author Sebastian Sdorra
* @since 1.8
+ *
+ * @deprecated use {@link RepositoryService#getBlameCommand()} instead.
*/
@Singleton
+@Deprecated
public class BlameViewerUtil extends PartCacheClearHook
{
@@ -75,7 +79,6 @@ public class BlameViewerUtil extends PartCacheClearHook
*
* @param repositoryManager
* @param cacheManager
- * @return
*/
@Inject
public BlameViewerUtil(RepositoryManager repositoryManager,
diff --git a/scm-core/src/main/java/sonia/scm/repository/BrowserResult.java b/scm-core/src/main/java/sonia/scm/repository/BrowserResult.java
index 7230b2ab48..7880b58f11 100644
--- a/scm-core/src/main/java/sonia/scm/repository/BrowserResult.java
+++ b/scm-core/src/main/java/sonia/scm/repository/BrowserResult.java
@@ -39,6 +39,8 @@ import com.google.common.base.Objects;
//~--- JDK imports ------------------------------------------------------------
+import java.io.Serializable;
+
import java.util.Iterator;
import java.util.List;
@@ -55,9 +57,14 @@ import javax.xml.bind.annotation.XmlRootElement;
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "browser-result")
-public class BrowserResult implements Iterable
+public class BrowserResult implements Iterable, Serializable
{
+ /** Field description */
+ private static final long serialVersionUID = 2818662048045182761L;
+
+ //~--- constructors ---------------------------------------------------------
+
/**
* Constructs ...
*
diff --git a/scm-core/src/main/java/sonia/scm/repository/Changeset.java b/scm-core/src/main/java/sonia/scm/repository/Changeset.java
index 3fb89a064e..379582c8c8 100644
--- a/scm-core/src/main/java/sonia/scm/repository/Changeset.java
+++ b/scm-core/src/main/java/sonia/scm/repository/Changeset.java
@@ -62,7 +62,7 @@ import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "changeset")
@XmlAccessorType(XmlAccessType.FIELD)
public class Changeset extends BasicPropertiesAware
- implements Validateable, Cloneable, Serializable
+ implements Validateable, Serializable
{
/** Field description */
@@ -108,26 +108,6 @@ public class Changeset extends BasicPropertiesAware
//~--- methods --------------------------------------------------------------
- /**
- * {@inheritDoc}
- *
- *
- * @return
- */
- @Override
- public Changeset clone()
- {
- Changeset changeset = new Changeset(id, date, author, description);
-
- changeset.setBranches(branches);
- changeset.setTags(tags);
- changeset.setModifications(modifications);
- changeset.setProperties(properties);
- changeset.setParents(parents);
-
- return changeset;
- }
-
/**
* {@inheritDoc}
*
diff --git a/scm-core/src/main/java/sonia/scm/repository/ChangesetPagingResult.java b/scm-core/src/main/java/sonia/scm/repository/ChangesetPagingResult.java
index d4a105d22b..2b1b455939 100644
--- a/scm-core/src/main/java/sonia/scm/repository/ChangesetPagingResult.java
+++ b/scm-core/src/main/java/sonia/scm/repository/ChangesetPagingResult.java
@@ -35,6 +35,8 @@ package sonia.scm.repository;
//~--- JDK imports ------------------------------------------------------------
+import java.io.Serializable;
+
import java.util.Iterator;
import java.util.List;
@@ -50,9 +52,14 @@ import javax.xml.bind.annotation.XmlRootElement;
*/
@XmlRootElement(name = "changeset-paging")
@XmlAccessorType(XmlAccessType.FIELD)
-public class ChangesetPagingResult implements Iterable
+public class ChangesetPagingResult implements Iterable, Serializable
{
+ /** Field description */
+ private static final long serialVersionUID = -8678755403658841733L;
+
+ //~--- constructors ---------------------------------------------------------
+
/**
* Constructs ...
*
diff --git a/scm-core/src/main/java/sonia/scm/repository/ChangesetPreProcessor.java b/scm-core/src/main/java/sonia/scm/repository/ChangesetPreProcessor.java
index 3e6db77967..0758f2d0a9 100644
--- a/scm-core/src/main/java/sonia/scm/repository/ChangesetPreProcessor.java
+++ b/scm-core/src/main/java/sonia/scm/repository/ChangesetPreProcessor.java
@@ -38,7 +38,11 @@ package sonia.scm.repository;
import sonia.scm.plugin.ExtensionPoint;
/**
- *
+ * A pre processor for {@link Changeset} objects. A pre processor is able to
+ * modify the object before it is delivered to the user interface.
+ *
+ * TODO for 2.0 extends {@link PreProcessor} interface.
+ *
* @author Sebastian Sdorra
*/
@ExtensionPoint
@@ -46,10 +50,10 @@ public interface ChangesetPreProcessor
{
/**
- * Method description
+ * Process the given changeset.
*
*
- * @param changeset
+ * @param changeset changeset to process
*/
public void process(Changeset changeset);
}
diff --git a/scm-core/src/main/java/sonia/scm/repository/ChangesetPreProcessorFactory.java b/scm-core/src/main/java/sonia/scm/repository/ChangesetPreProcessorFactory.java
index fc3cc92387..47ab5786e2 100644
--- a/scm-core/src/main/java/sonia/scm/repository/ChangesetPreProcessorFactory.java
+++ b/scm-core/src/main/java/sonia/scm/repository/ChangesetPreProcessorFactory.java
@@ -38,6 +38,10 @@ package sonia.scm.repository;
import sonia.scm.plugin.ExtensionPoint;
/**
+ * The ChangesetPreProcessorFactory create {@link ChangesetPreProcessor}
+ * objects for a specific repository.
+ *
+ * TODO for 2.0 extends {@link PreProcessorFactory} interface.
*
* @author Sebastian Sdorra
* @since 1.7
@@ -47,12 +51,12 @@ public interface ChangesetPreProcessorFactory
{
/**
- * Method description
+ * Create a new {@link ChangesetPreProcessor} for the given repository.
*
*
- * @param repository
+ * @param repository repository
*
- * @return
+ * @return {@link ChangesetPreProcessor} for the given repository
*/
public ChangesetPreProcessor createPreProcessor(Repository repository);
}
diff --git a/scm-core/src/main/java/sonia/scm/repository/ChangesetViewer.java b/scm-core/src/main/java/sonia/scm/repository/ChangesetViewer.java
index 0f9561e4d0..7d925bb8f4 100644
--- a/scm-core/src/main/java/sonia/scm/repository/ChangesetViewer.java
+++ b/scm-core/src/main/java/sonia/scm/repository/ChangesetViewer.java
@@ -33,6 +33,10 @@
package sonia.scm.repository;
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.api.RepositoryService;
+
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
@@ -40,7 +44,10 @@ import java.io.IOException;
/**
*
* @author Sebastian Sdorra
+ *
+ * @deprecated use {@link RepositoryService#getLogCommand()} instead.
*/
+@Deprecated
public interface ChangesetViewer
{
diff --git a/scm-core/src/main/java/sonia/scm/repository/ChangesetViewerProvider.java b/scm-core/src/main/java/sonia/scm/repository/ChangesetViewerProvider.java
index 4ccf0b86af..54ed628a60 100644
--- a/scm-core/src/main/java/sonia/scm/repository/ChangesetViewerProvider.java
+++ b/scm-core/src/main/java/sonia/scm/repository/ChangesetViewerProvider.java
@@ -33,11 +33,18 @@
package sonia.scm.repository;
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.api.RepositoryService;
+
/**
*
* @author Sebastian Sdorra
* @since 1.8
+ *
+ * @deprecated use {@link RepositoryService#getLogCommand()} instead.
*/
+@Deprecated
public interface ChangesetViewerProvider
{
diff --git a/scm-core/src/main/java/sonia/scm/repository/ChangesetViewerUtil.java b/scm-core/src/main/java/sonia/scm/repository/ChangesetViewerUtil.java
index 75c62964e5..1e12f9ab76 100644
--- a/scm-core/src/main/java/sonia/scm/repository/ChangesetViewerUtil.java
+++ b/scm-core/src/main/java/sonia/scm/repository/ChangesetViewerUtil.java
@@ -37,13 +37,13 @@ package sonia.scm.repository;
import com.google.inject.Inject;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.NotSupportedFeatuerException;
import sonia.scm.cache.Cache;
import sonia.scm.cache.CacheManager;
+import sonia.scm.repository.api.RepositoryService;
import sonia.scm.util.AssertUtil;
import sonia.scm.util.Util;
@@ -58,7 +58,10 @@ import java.util.Set;
*
* @author Sebastian Sdorra
* @since 1.6
+ *
+ * @deprecated use {@link RepositoryService#getLogCommand()} instead.
*/
+@Deprecated
public class ChangesetViewerUtil extends PartCacheClearHook
{
@@ -468,8 +471,6 @@ public class ChangesetViewerUtil extends PartCacheClearHook
}
}
-
-
/**
* Method description
*
diff --git a/scm-core/src/main/java/sonia/scm/repository/DiffViewer.java b/scm-core/src/main/java/sonia/scm/repository/DiffViewer.java
index 8b9ba11187..149d1b22b9 100644
--- a/scm-core/src/main/java/sonia/scm/repository/DiffViewer.java
+++ b/scm-core/src/main/java/sonia/scm/repository/DiffViewer.java
@@ -37,12 +37,16 @@ package sonia.scm.repository;
import java.io.IOException;
import java.io.OutputStream;
+import sonia.scm.repository.api.RepositoryService;
/**
*
* @author Sebastian Sdorra
* @since 1.8
+ *
+ * @deprecated use {@link RepositoryService#getDiffCommand()} instead.
*/
+@Deprecated
public interface DiffViewer
{
diff --git a/scm-core/src/main/java/sonia/scm/repository/DiffViewerProvider.java b/scm-core/src/main/java/sonia/scm/repository/DiffViewerProvider.java
index eea836977b..4876d3a5c7 100644
--- a/scm-core/src/main/java/sonia/scm/repository/DiffViewerProvider.java
+++ b/scm-core/src/main/java/sonia/scm/repository/DiffViewerProvider.java
@@ -33,11 +33,18 @@
package sonia.scm.repository;
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.api.RepositoryService;
+
/**
*
* @author Sebastian Sdorra
* @since 1.8
+ *
+ * @deprecated use {@link RepositoryService#getDiffCommand()} instead.
*/
+@Deprecated
public interface DiffViewerProvider
{
diff --git a/scm-core/src/main/java/sonia/scm/repository/EscapeUtil.java b/scm-core/src/main/java/sonia/scm/repository/EscapeUtil.java
index 291bd4a553..b4e85faac0 100644
--- a/scm-core/src/main/java/sonia/scm/repository/EscapeUtil.java
+++ b/scm-core/src/main/java/sonia/scm/repository/EscapeUtil.java
@@ -1,27 +1,29 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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
*
@@ -68,6 +70,34 @@ public class EscapeUtil
}
}
+ /**
+ * Method description
+ *
+ *
+ * @param result
+ * @since 1.17
+ */
+ public static void escape(BlameResult result)
+ {
+ for (BlameLine line : result.getBlameLines())
+ {
+ escape(line);
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param line
+ * @since 1.17
+ */
+ public static void escape(BlameLine line)
+ {
+ line.setDescription(escape(line.getDescription()));
+ escape(line.getAuthor());
+ }
+
/**
* Method description
*
@@ -90,17 +120,25 @@ public class EscapeUtil
public static void escape(Changeset changeset)
{
changeset.setDescription(escape(changeset.getDescription()));
+ escape(changeset.getAuthor());
+ changeset.setBranches(escapeList(changeset.getBranches()));
+ changeset.setTags(escapeList(changeset.getTags()));
+ }
- Person person = changeset.getAuthor();
-
+ /**
+ * Method description
+ *
+ *
+ * @param person
+ * @since 1.17
+ */
+ public static void escape(Person person)
+ {
if (person != null)
{
person.setName(escape(person.getName()));
person.setMail(escape(person.getMail()));
}
-
- changeset.setBranches(escapeList(changeset.getBranches()));
- changeset.setTags(escapeList(changeset.getTags()));
}
/**
diff --git a/scm-core/src/main/java/sonia/scm/repository/FileObject.java b/scm-core/src/main/java/sonia/scm/repository/FileObject.java
index 089ac48361..df6576464d 100644
--- a/scm-core/src/main/java/sonia/scm/repository/FileObject.java
+++ b/scm-core/src/main/java/sonia/scm/repository/FileObject.java
@@ -41,6 +41,8 @@ import sonia.scm.LastModifiedAware;
//~--- JDK imports ------------------------------------------------------------
+import java.io.Serializable;
+
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
@@ -53,9 +55,14 @@ import javax.xml.bind.annotation.XmlRootElement;
*/
@XmlRootElement(name = "file")
@XmlAccessorType(XmlAccessType.FIELD)
-public class FileObject implements LastModifiedAware
+public class FileObject implements LastModifiedAware, Serializable
{
+ /** Field description */
+ private static final long serialVersionUID = -5562537629609891499L;
+
+ //~--- methods --------------------------------------------------------------
+
/**
* {@inheritDoc}
*
diff --git a/scm-core/src/main/java/sonia/scm/repository/FileObjectPreProcessor.java b/scm-core/src/main/java/sonia/scm/repository/FileObjectPreProcessor.java
index 1f4e2e42ea..0e6560136f 100644
--- a/scm-core/src/main/java/sonia/scm/repository/FileObjectPreProcessor.java
+++ b/scm-core/src/main/java/sonia/scm/repository/FileObjectPreProcessor.java
@@ -33,10 +33,16 @@
package sonia.scm.repository;
+//~--- non-JDK imports --------------------------------------------------------
+
import sonia.scm.plugin.ExtensionPoint;
/**
- *
+ * A pre processor for {@link FileObject} objects. A pre processor is able to
+ * modify the object before it is delivered to the user interface.
+ *
+ * TODO for 2.0 extends {@link PreProcessor} interface.
+ *
* @author Sebastian Sdorra
* @since 1.10
*/
@@ -45,10 +51,10 @@ public interface FileObjectPreProcessor
{
/**
- * Method description
+ * Process the given file object.
*
*
- * @param fileObject
+ * @param fileObject file object to process
*/
public void process(FileObject fileObject);
}
diff --git a/scm-core/src/main/java/sonia/scm/repository/FileObjectPreProcessorFactory.java b/scm-core/src/main/java/sonia/scm/repository/FileObjectPreProcessorFactory.java
index 2e3dce877c..746aed75f3 100644
--- a/scm-core/src/main/java/sonia/scm/repository/FileObjectPreProcessorFactory.java
+++ b/scm-core/src/main/java/sonia/scm/repository/FileObjectPreProcessorFactory.java
@@ -38,6 +38,10 @@ package sonia.scm.repository;
import sonia.scm.plugin.ExtensionPoint;
/**
+ * The FileObjectPreProcessorFactory create {@link FileObjectPreProcessor}
+ * objects for a specific repository.
+ *
+ * TODO for 2.0 extends {@link PreProcessorFactory} interface.
*
* @author Sebastian Sdorra
* @since 1.10
@@ -47,12 +51,12 @@ public interface FileObjectPreProcessorFactory
{
/**
- * Method description
+ * Create a new {@link FileObjectPreProcessor} for the given repository.
*
*
- * @param repository
+ * @param repository repository
*
- * @return
+ * @return {@link FileObjectPreProcessor} for the given repository
*/
public FileObjectPreProcessor createPreProcessor(Repository repository);
}
diff --git a/scm-core/src/main/java/sonia/scm/repository/PreProcessor.java b/scm-core/src/main/java/sonia/scm/repository/PreProcessor.java
new file mode 100644
index 0000000000..992f5b07e6
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/PreProcessor.java
@@ -0,0 +1,54 @@
+/**
+ * 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;
+
+/**
+ * A pre processor is able to modify a object before it is delivered
+ * to the user interface.
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ *
+ * @param object type
+ */
+public interface PreProcessor
+{
+
+ /**
+ * Process the given object.
+ *
+ *
+ * @param item object to process
+ */
+ public void process(T item);
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/PreProcessorFactory.java b/scm-core/src/main/java/sonia/scm/repository/PreProcessorFactory.java
new file mode 100644
index 0000000000..91a452d1bc
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/PreProcessorFactory.java
@@ -0,0 +1,57 @@
+/**
+ * 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;
+
+/**
+ * A pre processor factory creates a specific {@link PreProcessor} for
+ * the given repository.
+ *
+ * @author Sebastian Sdorra
+ *
+ * @param object type for the {@link PreProcessor}
+ * @since 1.17
+ */
+public interface PreProcessorFactory
+{
+
+ /**
+ * Create a new {@link PreProcessor} for the given repository.
+ *
+ *
+ * @param repository repository
+ *
+ * @return {@link PreProcessor} for the given repository
+ */
+ public PreProcessor createPreProcessor(Repository repository);
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/PreProcessorUtil.java b/scm-core/src/main/java/sonia/scm/repository/PreProcessorUtil.java
new file mode 100644
index 0000000000..89d8099996
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/PreProcessorUtil.java
@@ -0,0 +1,628 @@
+/**
+ * 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.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.inject.Inject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.util.Util;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public class PreProcessorUtil
+{
+
+ /**
+ * the logger for PreProcessorUtil
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(PreProcessorUtil.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param changesetPreProcessorSet
+ * @param changesetPreProcessorFactorySet
+ * @param fileObjectPreProcessorSet
+ * @param fileObjectPreProcessorFactorySet
+ * @param blameLinePreProcessorSet
+ * @param blameLinePreProcessorFactorySet
+ */
+ @Inject
+ public PreProcessorUtil(
+ Set changesetPreProcessorSet,
+ Set changesetPreProcessorFactorySet,
+ Set fileObjectPreProcessorSet,
+ Set fileObjectPreProcessorFactorySet,
+ Set blameLinePreProcessorSet,
+ Set blameLinePreProcessorFactorySet)
+ {
+ this.changesetPreProcessorSet =
+ Collections2.transform(changesetPreProcessorSet,
+ new Function()
+ {
+ @Override
+ public ChangesetPreProcessorWrapper apply(ChangesetPreProcessor input)
+ {
+ return new ChangesetPreProcessorWrapper(input);
+ }
+ });
+ this.changesetPreProcessorFactorySet =
+ Collections2.transform(changesetPreProcessorFactorySet,
+ new Function()
+ {
+ @Override
+ public ChangesetPreProcessorFactoryWrapper apply(
+ ChangesetPreProcessorFactory input)
+ {
+ return new ChangesetPreProcessorFactoryWrapper(input);
+ }
+ });
+ this.fileObjectPreProcessorSet =
+ Collections2.transform(fileObjectPreProcessorSet,
+ new Function()
+ {
+ @Override
+ public FileObjectPreProcessorWrapper apply(FileObjectPreProcessor input)
+ {
+ return new FileObjectPreProcessorWrapper(input);
+ }
+ });
+ this.fileObjectPreProcessorFactorySet =
+ Collections2.transform(fileObjectPreProcessorFactorySet,
+ new Function()
+ {
+ @Override
+ public FileObjectPreProcessorFactoryWrapper apply(
+ FileObjectPreProcessorFactory input)
+ {
+ return new FileObjectPreProcessorFactoryWrapper(input);
+ }
+ });
+ this.blameLinePreProcessorSet = blameLinePreProcessorSet;
+ this.blameLinePreProcessorFactorySet = blameLinePreProcessorFactorySet;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ * @param blameLine
+ */
+ public void prepareForReturn(Repository repository, BlameLine blameLine)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("prepare blame line {} of repository {} for return",
+ blameLine.getLineNumber(), repository.getName());
+ }
+
+ EscapeUtil.escape(blameLine);
+
+ PreProcessorHandler handler =
+ new PreProcessorHandler(blameLinePreProcessorFactorySet,
+ blameLinePreProcessorSet, repository);
+
+ handler.callPreProcessors(blameLine);
+ handler.callPreProcessorFactories(blameLine);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ * @param blameResult
+ */
+ public void prepareForReturn(Repository repository, BlameResult blameResult)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("prepare blame result of repository {} for return",
+ repository.getName());
+ }
+
+ EscapeUtil.escape(blameResult);
+
+ PreProcessorHandler handler =
+ new PreProcessorHandler(blameLinePreProcessorFactorySet,
+ blameLinePreProcessorSet, repository);
+
+ handler.callPreProcessors(blameResult.getBlameLines());
+ handler.callPreProcessorFactories(blameResult.getBlameLines());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ * @param changeset
+ */
+ public void prepareForReturn(Repository repository, Changeset changeset)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("prepare changeset {} of repository {} for return",
+ changeset.getId(), repository.getName());
+ }
+
+ EscapeUtil.escape(changeset);
+
+ PreProcessorHandler handler =
+ new PreProcessorHandler(changesetPreProcessorFactorySet,
+ changesetPreProcessorSet, repository);
+
+ handler.callPreProcessors(changeset);
+ handler.callPreProcessorFactories(changeset);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ * @param changeset
+ * @param result
+ */
+ public void prepareForReturn(Repository repository, BrowserResult result)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("prepare browser result of repository {} for return",
+ repository.getName());
+ }
+
+ EscapeUtil.escape(result);
+
+ PreProcessorHandler handler =
+ new PreProcessorHandler(fileObjectPreProcessorFactorySet,
+ fileObjectPreProcessorSet, repository);
+
+ handler.callPreProcessors(result);
+ handler.callPreProcessorFactories(result);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ * @param result
+ */
+ public void prepareForReturn(Repository repository,
+ ChangesetPagingResult result)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("prepare changesets of repository {} for return",
+ repository.getName());
+ }
+
+ EscapeUtil.escape(result);
+
+ PreProcessorHandler handler =
+ new PreProcessorHandler(changesetPreProcessorFactorySet,
+ changesetPreProcessorSet, repository);
+
+ handler.callPreProcessors(result);
+ handler.callPreProcessorFactories(result);
+ }
+
+ //~--- inner classes --------------------------------------------------------
+
+ /**
+ * Class description
+ *
+ *
+ * @version Enter version here..., 12/06/16
+ * @author Enter your name here...
+ */
+ private static class ChangesetPreProcessorFactoryWrapper
+ implements PreProcessorFactory
+ {
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param preProcessorFactory
+ */
+ public ChangesetPreProcessorFactoryWrapper(
+ ChangesetPreProcessorFactory preProcessorFactory)
+ {
+ this.preProcessorFactory = preProcessorFactory;
+ }
+
+ //~--- methods ------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ *
+ * @return
+ */
+ @Override
+ public PreProcessor createPreProcessor(Repository repository)
+ {
+ PreProcessor preProcessor = null;
+ ChangesetPreProcessor changesetPreProcessor =
+ preProcessorFactory.createPreProcessor(repository);
+
+ if (changesetPreProcessor != null)
+ {
+ preProcessor = new ChangesetPreProcessorWrapper(changesetPreProcessor);
+ }
+
+ return preProcessor;
+ }
+
+ //~--- fields -------------------------------------------------------------
+
+ /** Field description */
+ private ChangesetPreProcessorFactory preProcessorFactory;
+ }
+
+
+ /**
+ * Class description
+ *
+ *
+ * @version Enter version here..., 12/06/16
+ * @author Enter your name here...
+ */
+ private static class ChangesetPreProcessorWrapper
+ implements PreProcessor
+ {
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param preProcessor
+ */
+ public ChangesetPreProcessorWrapper(ChangesetPreProcessor preProcessor)
+ {
+ this.preProcessor = preProcessor;
+ }
+
+ //~--- methods ------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param item
+ */
+ @Override
+ public void process(Changeset item)
+ {
+ preProcessor.process(item);
+ }
+
+ //~--- fields -------------------------------------------------------------
+
+ /** Field description */
+ private ChangesetPreProcessor preProcessor;
+ }
+
+
+ /**
+ * Class description
+ *
+ *
+ * @version Enter version here..., 12/06/16
+ * @author Enter your name here...
+ */
+ private static class FileObjectPreProcessorFactoryWrapper
+ implements PreProcessorFactory
+ {
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param preProcessorFactory
+ */
+ public FileObjectPreProcessorFactoryWrapper(
+ FileObjectPreProcessorFactory preProcessorFactory)
+ {
+ this.preProcessorFactory = preProcessorFactory;
+ }
+
+ //~--- methods ------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ *
+ * @return
+ */
+ @Override
+ public PreProcessor createPreProcessor(Repository repository)
+ {
+ PreProcessor preProcessor = null;
+ FileObjectPreProcessor fileObjectPreProcessor =
+ preProcessorFactory.createPreProcessor(repository);
+
+ if (fileObjectPreProcessor != null)
+ {
+ preProcessor =
+ new FileObjectPreProcessorWrapper(fileObjectPreProcessor);
+ }
+
+ return preProcessor;
+ }
+
+ //~--- fields -------------------------------------------------------------
+
+ /** Field description */
+ private FileObjectPreProcessorFactory preProcessorFactory;
+ }
+
+
+ /**
+ * Class description
+ *
+ *
+ * @version Enter version here..., 12/06/16
+ * @author Enter your name here...
+ */
+ private static class FileObjectPreProcessorWrapper
+ implements PreProcessor
+ {
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param preProcessor
+ */
+ public FileObjectPreProcessorWrapper(FileObjectPreProcessor preProcessor)
+ {
+ this.preProcessor = preProcessor;
+ }
+
+ //~--- methods ------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param item
+ */
+ @Override
+ public void process(FileObject item)
+ {
+ preProcessor.process(item);
+ }
+
+ //~--- fields -------------------------------------------------------------
+
+ /** Field description */
+ private FileObjectPreProcessor preProcessor;
+ }
+
+
+ /**
+ * Class description
+ *
+ *
+ * @param
+ *
+ * @version Enter version here..., 12/06/16
+ * @author Enter your name here...
+ */
+ private static class PreProcessorHandler
+ {
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param preProcessorFactorySet
+ * @param preProcessorSet
+ * @param repository
+ */
+ public PreProcessorHandler(
+ Collection extends PreProcessorFactory> preProcessorFactorySet,
+ Collection extends PreProcessor> preProcessorSet,
+ Repository repository)
+ {
+ this.preProcessorFactorySet = preProcessorFactorySet;
+ this.preProcessorSet = preProcessorSet;
+ this.repository = repository;
+ }
+
+ //~--- methods ------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ *
+ *
+ * @param preProcessorFactorySet
+ * @param repository
+ * @param changesets
+ * @param items
+ * @param
+ */
+ public void callPreProcessorFactories(Iterable items)
+ {
+ if (Util.isNotEmpty(preProcessorFactorySet))
+ {
+ for (PreProcessorFactory factory : preProcessorFactorySet)
+ {
+ PreProcessor preProcessor = factory.createPreProcessor(repository);
+
+ if (preProcessor != null)
+ {
+ for (T item : items)
+ {
+ preProcessor.process(item);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ *
+ * @param preProcessorFactorySet
+ * @param repository
+ * @param item
+ * @param
+ */
+ public void callPreProcessorFactories(T item)
+ {
+ if (Util.isNotEmpty(preProcessorFactorySet))
+ {
+ for (PreProcessorFactory factory : preProcessorFactorySet)
+ {
+ PreProcessor cpp = factory.createPreProcessor(repository);
+
+ if (cpp != null)
+ {
+ cpp.process(item);
+ }
+ }
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param changesets
+ *
+ * @param preProcessorSet
+ * @param items
+ * @param
+ */
+ public void callPreProcessors(Iterable items)
+ {
+ if (Util.isNotEmpty(preProcessorSet))
+ {
+ for (T item : items)
+ {
+ callPreProcessors(item);
+ }
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param c
+ *
+ * @param preProcessorSet
+ * @param item
+ * @param
+ */
+ public void callPreProcessors(T item)
+ {
+ if (Util.isNotEmpty(preProcessorSet))
+ {
+ for (PreProcessor preProcessor : preProcessorSet)
+ {
+ preProcessor.process(item);
+ }
+ }
+ }
+
+ //~--- fields -------------------------------------------------------------
+
+ /** Field description */
+ private Collection extends PreProcessorFactory> preProcessorFactorySet;
+
+ /** Field description */
+ private Collection extends PreProcessor> preProcessorSet;
+
+ /** Field description */
+ private Repository repository;
+ }
+
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private Collection blameLinePreProcessorFactorySet;
+
+ /** Field description */
+ private Collection blameLinePreProcessorSet;
+
+ /** Field description */
+ private Collection changesetPreProcessorFactorySet;
+
+ /** Field description */
+ private Collection changesetPreProcessorSet;
+
+ /** Field description */
+ private Collection fileObjectPreProcessorFactorySet;
+
+ /** Field description */
+ private Collection fileObjectPreProcessorSet;
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/Repository.java b/scm-core/src/main/java/sonia/scm/repository/Repository.java
index 965f601d65..ea022d4538 100644
--- a/scm-core/src/main/java/sonia/scm/repository/Repository.java
+++ b/scm-core/src/main/java/sonia/scm/repository/Repository.java
@@ -39,6 +39,7 @@ import com.google.common.base.Objects;
import sonia.scm.BasicPropertiesAware;
import sonia.scm.ModelObject;
+import sonia.scm.util.HttpUtil;
import sonia.scm.util.Util;
import sonia.scm.util.ValidationUtil;
@@ -164,6 +165,22 @@ public class Repository extends BasicPropertiesAware implements ModelObject
repository.setArchived(archived);
}
+ /**
+ * Creates the url of the repository.
+ *
+ *
+ * @param baseUrl base url of the server including the context path
+ *
+ * @return url of the repository
+ * @since 1.17
+ */
+ public String createUrl(String baseUrl)
+ {
+ String url = HttpUtil.append(baseUrl, type);
+
+ return HttpUtil.append(url, name);
+ }
+
/**
* Returns true if the {@link Repository} is the same as the obj argument.
*
@@ -343,7 +360,9 @@ public class Repository extends BasicPropertiesAware implements ModelObject
*
*
* @return base url
+ * @deprecated use {@link #createUrl(String)}
*/
+ @Deprecated
public String getUrl()
{
return url;
@@ -511,7 +530,9 @@ public class Repository extends BasicPropertiesAware implements ModelObject
*
*
* @param url base url
+ * @deprecated
*/
+ @Deprecated
public void setUrl(String url)
{
this.url = url;
@@ -550,6 +571,8 @@ public class Repository extends BasicPropertiesAware implements ModelObject
/** Field description */
private String type;
- /** Field description */
+ /**
+ * @deprecated use {@link #createUrl(java.lang.String)} instead
+ */
private String url;
}
diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowser.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowser.java
index abf137dbfd..35e36de289 100644
--- a/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowser.java
+++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowser.java
@@ -33,6 +33,10 @@
package sonia.scm.repository;
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.api.RepositoryService;
+
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
@@ -42,7 +46,10 @@ import java.io.OutputStream;
*
* @author Sebastian Sdorra
* @since 1.5
+ *
+ * @deprecated use {@link RepositoryService#getBrowseCommand()} instead.
*/
+@Deprecated
public interface RepositoryBrowser
{
diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowserProvider.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowserProvider.java
index b87d3481d0..cf017fd168 100644
--- a/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowserProvider.java
+++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowserProvider.java
@@ -33,11 +33,18 @@
package sonia.scm.repository;
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.api.RepositoryService;
+
/**
*
* @author Sebastian Sdorra
* @since 1.5
+ *
+ * @deprecated use {@link RepositoryService#getBrowseCommand()} instead.
*/
+@Deprecated
public interface RepositoryBrowserProvider
{
diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowserUtil.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowserUtil.java
index db31d17287..77abb191d1 100644
--- a/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowserUtil.java
+++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryBrowserUtil.java
@@ -44,6 +44,7 @@ import org.slf4j.LoggerFactory;
import sonia.scm.NotSupportedFeatuerException;
import sonia.scm.cache.Cache;
import sonia.scm.cache.CacheManager;
+import sonia.scm.repository.api.RepositoryService;
import sonia.scm.util.AssertUtil;
import sonia.scm.util.Util;
@@ -59,8 +60,11 @@ import java.util.Set;
*
* @author Sebastian Sdorra
* @since 1.6
+ *
+ * @deprecated use {@link RepositoryService#getBrowseCommand()} instead.
*/
@Singleton
+@Deprecated
public class RepositoryBrowserUtil extends PartCacheClearHook
{
diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryCacheKeyFilter.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryCacheKeyFilter.java
new file mode 100644
index 0000000000..c2c2c41b67
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryCacheKeyFilter.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of SCM-Manager; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+package sonia.scm.repository;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.Filter;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ *
+ * @param
+ */
+public class RepositoryCacheKeyFilter
+ implements Filter
+{
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param repositoryId
+ */
+ public RepositoryCacheKeyFilter(String repositoryId)
+ {
+ this.repositoryId = repositoryId;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param item
+ *
+ * @return
+ */
+ @Override
+ public boolean accept(T item)
+ {
+ return repositoryId.equals(item.getRepositoryId());
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private String repositoryId;
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryHookSupport.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryHookSupport.java
index 63452822ef..3fced455cf 100644
--- a/scm-core/src/main/java/sonia/scm/repository/RepositoryHookSupport.java
+++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryHookSupport.java
@@ -62,9 +62,8 @@ public interface RepositoryHookSupport
/**
* Fires a post receive hook event. This methods calls the
- * {@link PostReceiveHook#onPostReceive(Repository, List)} of each registered
- * {@link PostReceiveHook}.
- *
+ * {@link PostReceiveRepositoryHook#onPostReceive(Repository, List)}
+ * of each registered {@link PostReceiveRepositoryHook}.
*
* @param repository that has changed
* @param event
@@ -73,8 +72,8 @@ public interface RepositoryHookSupport
/**
* Fires a post receive hook event. This methods calls the
- * {@link PostReceiveHook#onPostReceive(Repository, List)} of each registered
- * {@link PostReceiveHook}.
+ * {@link PostReceiveRepositoryHook#onPostReceive(Repository, List)}
+ * of each registered {@link PostReceiveRepositoryHook}.
*
*
* @param type of the repository
diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryTypePredicate.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryTypePredicate.java
index 7b6eb0b302..ac7d389a60 100644
--- a/scm-core/src/main/java/sonia/scm/repository/RepositoryTypePredicate.java
+++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryTypePredicate.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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 --------------------------------------------------------
diff --git a/scm-core/src/main/java/sonia/scm/repository/SubRepository.java b/scm-core/src/main/java/sonia/scm/repository/SubRepository.java
index a00784cae3..3c8acc4831 100644
--- a/scm-core/src/main/java/sonia/scm/repository/SubRepository.java
+++ b/scm-core/src/main/java/sonia/scm/repository/SubRepository.java
@@ -39,6 +39,8 @@ import com.google.common.base.Objects;
//~--- JDK imports ------------------------------------------------------------
+import java.io.Serializable;
+
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
@@ -50,9 +52,14 @@ import javax.xml.bind.annotation.XmlRootElement;
*/
@XmlRootElement(name = "subrepository")
@XmlAccessorType(XmlAccessType.FIELD)
-public class SubRepository
+public class SubRepository implements Serializable
{
+ /** Field description */
+ private static final long serialVersionUID = 6960065820378492531L;
+
+ //~--- constructors ---------------------------------------------------------
+
/**
* Constructs ...
*
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/BlameCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/BlameCommandBuilder.java
new file mode 100644
index 0000000000..0d0b5158e1
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/api/BlameCommandBuilder.java
@@ -0,0 +1,366 @@
+/**
+ * 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.api;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.cache.Cache;
+import sonia.scm.cache.CacheManager;
+import sonia.scm.repository.BlameResult;
+import sonia.scm.repository.PreProcessorUtil;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryCacheKey;
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.repository.spi.BlameCommand;
+import sonia.scm.repository.spi.BlameCommandRequest;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+import java.io.Serializable;
+
+/**
+ * Shows changeset information by line for a given file.
+ * Blame is also known as annotate in some SCM systems.
+ *
+ * Sample:
+ *
+ *
+ * Print each line number and code of the file scm-core/pom.xml at
+ * revision 60c2f2783368:
+ *
+ * BlameCommandBuilder blame = repositoryService.getBlameCommand();
+ * BlameResult result = blame.setRevision("60c2f2783368")
+ * .getBlameResult("scm-core/pom.xml");
+ *
+ * for ( BlameLine line : result ){
+ * System.out.println(line.getLineNumber() + ": " + line.getCode());
+ * }
+ *
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public final class BlameCommandBuilder
+{
+
+ /** name of the cache */
+ static final String CACHE_NAME = "sonia.cache.cmd.blame";
+
+ /**
+ * the logger for BlameCommandBuilder
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(BlameCommandBuilder.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs a new {@link BlameCommandBuilder}, this constructor should
+ * only be called from the {@link RepositoryService}.
+ *
+ * @param cacheManager cache manager
+ * @param blameCommand implementation of the {@link BlameCommand}
+ * @param repository repository to query
+ * @param preProcessorUtil
+ */
+ BlameCommandBuilder(CacheManager cacheManager, BlameCommand blameCommand,
+ Repository repository, PreProcessorUtil preProcessorUtil)
+ {
+ this.cache = cacheManager.getCache(CacheKey.class, BlameResult.class,
+ CACHE_NAME);
+ this.blameCommand = blameCommand;
+ this.repository = repository;
+ this.preProcessorUtil = preProcessorUtil;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Reset each parameter to its default value.
+ *
+ * @return {@code this}
+ */
+ public BlameCommandBuilder reset()
+ {
+ request.reset();
+ this.disableCache = false;
+ this.disablePreProcessors = false;
+
+ return this;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Returns changeset informations by line for the given file.
+ *
+ * @param path path of the file
+ * @return changeset informations by line for the given file
+ *
+ * @throws IllegalArgumentException if the path is null or empty
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ public BlameResult getBlameResult(String path)
+ throws IOException, RepositoryException
+ {
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(path),
+ "path is required");
+
+ BlameCommandRequest requestClone = request.clone();
+
+ requestClone.setPath(path);
+
+ BlameResult result = null;
+
+ if (disableCache)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("create blame for {} with disabled cache", requestClone);
+ }
+
+ result = blameCommand.getBlameResult(requestClone);
+ }
+ else
+ {
+ CacheKey key = new CacheKey(repository, request);
+
+ result = cache.get(key);
+
+ if (result == null)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("create blame for {}", requestClone);
+ }
+
+ result = blameCommand.getBlameResult(requestClone);
+
+ if (result != null)
+ {
+ cache.put(key, result);
+ }
+ }
+ else if (logger.isDebugEnabled())
+ {
+ logger.debug("retrive blame from cache for {}", requestClone);
+ }
+ }
+
+ if (!disablePreProcessors && (result != null))
+ {
+ preProcessorUtil.prepareForReturn(repository, result);
+ }
+
+ return result;
+ }
+
+ //~--- set methods ----------------------------------------------------------
+
+ /**
+ * Disables the cache. This means that every {@link BlameResult}
+ * is directly retrieved from the {@link Repository}. Note: Disabling
+ * the cache cost a lot of performance and could be much more slower.
+ *
+ *
+ * @param disableCache true to disable the cache
+ *
+ * @return {@code this}
+ */
+ public BlameCommandBuilder setDisableCache(boolean disableCache)
+ {
+ this.disableCache = disableCache;
+
+ return this;
+ }
+
+ /**
+ * Disable the execution of pre processors.
+ *
+ *
+ * @param disablePreProcessors true to disable the pre processors execution
+ *
+ * @return {@code this}
+ */
+ public BlameCommandBuilder setDisablePreProcessors(
+ boolean disablePreProcessors)
+ {
+ this.disablePreProcessors = disablePreProcessors;
+
+ return this;
+ }
+
+ /**
+ * Sets the start revision for the blame.
+ *
+ *
+ * @param revision revision to start from
+ *
+ * @return {@code this}
+ */
+ public BlameCommandBuilder setRevision(String revision)
+ {
+ request.setRevision(revision);
+
+ return this;
+ }
+
+ //~--- inner classes --------------------------------------------------------
+
+ /**
+ * Key for cache.
+ *
+ *
+ * @version Enter version here..., 12/06/05
+ * @author Enter your name here...
+ */
+ static class CacheKey implements RepositoryCacheKey, Serializable
+ {
+
+ /** Field description */
+ private static final long serialVersionUID = 8373766042131887789L;
+
+ //~--- constructors -------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param repository
+ * @param request
+ */
+ public CacheKey(Repository repository, BlameCommandRequest request)
+ {
+ this.repositoryId = repository.getId();
+ this.request = request;
+ }
+
+ //~--- methods ------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param obj
+ *
+ * @return
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+
+ final CacheKey other = (CacheKey) obj;
+
+ return Objects.equal(repositoryId, other.repositoryId)
+ && Objects.equal(request, other.request);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public int hashCode()
+ {
+ return Objects.hashCode(repositoryId, request);
+ }
+
+ //~--- get methods --------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public String getRepositoryId()
+ {
+ return repositoryId;
+ }
+
+ //~--- fields -------------------------------------------------------------
+
+ /** Field description */
+ private String repositoryId;
+
+ /** Field description */
+ private BlameCommandRequest request;
+ }
+
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** implementation of the blame command */
+ private BlameCommand blameCommand;
+
+ /** the cache */
+ private Cache cache;
+
+ /** disable change */
+ private boolean disableCache = false;
+
+ /** disable the execution of pre processors */
+ private boolean disablePreProcessors = false;
+
+ /** Field description */
+ private PreProcessorUtil preProcessorUtil;
+
+ /** the repository */
+ private Repository repository;
+
+ /** request for the blame command implementation */
+ private BlameCommandRequest request = new BlameCommandRequest();
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/BrowseCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/BrowseCommandBuilder.java
new file mode 100644
index 0000000000..e3eb0a0be9
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/api/BrowseCommandBuilder.java
@@ -0,0 +1,384 @@
+/**
+ * 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.api;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Objects;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.cache.Cache;
+import sonia.scm.cache.CacheManager;
+import sonia.scm.repository.BrowserResult;
+import sonia.scm.repository.FileObject;
+import sonia.scm.repository.FileObjectNameComparator;
+import sonia.scm.repository.PreProcessorUtil;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryCacheKey;
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.repository.spi.BrowseCommand;
+import sonia.scm.repository.spi.BrowseCommandRequest;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+import java.io.Serializable;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * BrowseCommandBuilder is able to browse the files of a {@link Repository}.
+ *
+ * Sample:
+ *
+ *
+ * Print all paths from folder scm-core at revision 11aeec7db845:
+ *
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public final class CatCommandBuilder
+{
+
+ /**
+ * the logger for CatCommandBuilder
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(CatCommandBuilder.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs a new {@link CatCommandBuilder}, this constructor should
+ * only be called from the {@link RepositoryService}.
+ *
+ * @param catCommand implementation of the {@link CatCommand}
+ */
+ CatCommandBuilder(CatCommand catCommand)
+ {
+ this.catCommand = catCommand;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Reset each parameter to its default value.
+ *
+ * @return {@code this}
+ */
+ public CatCommandBuilder reset()
+ {
+ request.reset();
+
+ return this;
+ }
+
+ /**
+ * Passes the content of the given file to the outputstream.
+ *
+ * @param outputStream outputstream for the content
+ * @param path file path
+ *
+ * @return {@code this}
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ public CatCommandBuilder retriveContent(OutputStream outputStream,
+ String path)
+ throws IOException, RepositoryException
+ {
+ getCatResult(outputStream, path);
+
+ return this;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Returns the content of the given file.
+ *
+ * @param path file path
+ * @return content of the file
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ public String getContent(String path) throws IOException, RepositoryException
+ {
+ String content = null;
+ ByteArrayOutputStream baos = null;
+
+ try
+ {
+ baos = new ByteArrayOutputStream();
+ getCatResult(baos, path);
+ content = baos.toString();
+ }
+ finally
+ {
+ Closeables.closeQuietly(baos);
+ }
+
+ return content;
+ }
+
+ //~--- set methods ----------------------------------------------------------
+
+ /**
+ * Sets the revision of the file.
+ *
+ *
+ * @param revision revision of the file
+ *
+ * @return {@code this}
+ */
+ public CatCommandBuilder setRevision(String revision)
+ {
+ request.setRevision(revision);
+
+ return this;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Executes the cat command.
+ *
+ *
+ * @param outputStream the outputstream for the content
+ * @param path path of the file
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ private void getCatResult(OutputStream outputStream, String path)
+ throws IOException, RepositoryException
+ {
+ Preconditions.checkNotNull(outputStream, "OutputStream is required");
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(path),
+ "path is required");
+
+ CatCommandRequest requestClone = request.clone();
+
+ requestClone.setPath(path);
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("create cat for {}", requestClone);
+ }
+
+ catCommand.getCatResult(requestClone, outputStream);
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** implementation of the cat command */
+ private CatCommand catCommand;
+
+ /** request for the cat command */
+ private CatCommandRequest request = new CatCommandRequest();
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/Command.java b/scm-core/src/main/java/sonia/scm/repository/api/Command.java
new file mode 100644
index 0000000000..5caba59440
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/api/Command.java
@@ -0,0 +1,45 @@
+/**
+ * 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.api;
+
+/**
+ * Enumeration of available commands.
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public enum Command
+{
+ LOG, BROWSE, CAT, DIFF, BLAME
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/CommandNotSupportedException.java b/scm-core/src/main/java/sonia/scm/repository/api/CommandNotSupportedException.java
new file mode 100644
index 0000000000..3b51254659
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/api/CommandNotSupportedException.java
@@ -0,0 +1,94 @@
+/**
+ * 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.api;
+
+/**
+ * This exception is thrown if the {@link RepositoryService} does not support
+ * the requested command.
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public final class CommandNotSupportedException extends RuntimeException
+{
+
+ /**
+ * Constructs a new {@link CommandNotSupportedException}.
+ *
+ *
+ * @param command not supported command
+ */
+ public CommandNotSupportedException(Command command)
+ {
+ //J-
+ this(
+ command,
+ "The requested feature "
+ .concat(command.toString())
+ .concat(" is not supported")
+ );
+ //J+
+ }
+
+ /**
+ * Constructs a new {@link CommandNotSupportedException}.
+ *
+ *
+ * @param command not supported command
+ * @param message message to be shown
+ */
+ public CommandNotSupportedException(Command command, String message)
+ {
+ super(message);
+ this.command = command;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Returns the command which is not supported.
+ *
+ *
+ * @return not supported command
+ */
+ public Command getCommand()
+ {
+ return command;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** not supported command */
+ private Command command;
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/DiffCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/DiffCommandBuilder.java
new file mode 100644
index 0000000000..dfe874813e
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/api/DiffCommandBuilder.java
@@ -0,0 +1,215 @@
+/**
+ * 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.api;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Preconditions;
+import com.google.common.io.Closeables;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.repository.spi.DiffCommand;
+import sonia.scm.repository.spi.DiffCommandRequest;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Shows differences between revisions for a specified file or
+ * the entire revision.
+ * Note: One of the parameter path or revision have to be set.
+ *
+ * Sample:
+ *
+ *
+ * Print the differences from revision 33b93c443867:
+ *
+ *
+ *
+ * TODO check current behavior.
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public final class DiffCommandBuilder
+{
+
+ /**
+ * the logger for DiffCommandBuilder
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(DiffCommandBuilder.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs a new {@link DiffCommandBuilder}, this constructor should
+ * only be called from the {@link RepositoryService}.
+ *
+ * @param implementation of {@link DiffCommand}
+ *
+ * @param diffCommand
+ */
+ DiffCommandBuilder(DiffCommand diffCommand)
+ {
+ this.diffCommand = diffCommand;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Passes the difference of the given parameter to the outputstream.
+ *
+ *
+ * @param outputStream outputstream for the difference
+ *
+ * @return {@code this}
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ public DiffCommandBuilder retriveContent(OutputStream outputStream)
+ throws IOException, RepositoryException
+ {
+ getDiffResult(outputStream);
+
+ return this;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Returns the content of the difference as string.
+ *
+ * @return content of the difference
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ public String getContent() throws IOException, RepositoryException
+ {
+ String content = null;
+ ByteArrayOutputStream baos = null;
+
+ try
+ {
+ baos = new ByteArrayOutputStream();
+ getDiffResult(baos);
+ content = baos.toString();
+ }
+ finally
+ {
+ Closeables.closeQuietly(baos);
+ }
+
+ return content;
+ }
+
+ //~--- set methods ----------------------------------------------------------
+
+ /**
+ * Show the difference only for the given path.
+ *
+ *
+ * @param path path for difference
+ *
+ * @return {@code this}
+ */
+ public DiffCommandBuilder setPath(String path)
+ {
+ request.setPath(path);
+
+ return this;
+ }
+
+ /**
+ * Show the difference only for the given revision.
+ *
+ *
+ * @param revision revision for difference
+ *
+ * @return {@code this}
+ */
+ public DiffCommandBuilder setRevision(String revision)
+ {
+ request.setRevision(revision);
+
+ return this;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param outputStream
+ * @param path
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ private void getDiffResult(OutputStream outputStream)
+ throws IOException, RepositoryException
+ {
+ Preconditions.checkNotNull(outputStream, "OutputStream is required");
+ Preconditions.checkArgument(request.isValid(),
+ "path and/or revision is required");
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("create diff for {}", request);
+ }
+
+ diffCommand.getDiffResult(request, outputStream);
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** implementation of the diff command */
+ private DiffCommand diffCommand;
+
+ /** request for the diff command implementation */
+ private DiffCommandRequest request = new DiffCommandRequest();
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/LogCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/LogCommandBuilder.java
new file mode 100644
index 0000000000..e39c3ced14
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/api/LogCommandBuilder.java
@@ -0,0 +1,528 @@
+/**
+ * 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.api;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.cache.Cache;
+import sonia.scm.cache.CacheManager;
+import sonia.scm.repository.Changeset;
+import sonia.scm.repository.ChangesetPagingResult;
+import sonia.scm.repository.PreProcessorUtil;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryCacheKey;
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.repository.spi.LogCommand;
+import sonia.scm.repository.spi.LogCommandRequest;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+import java.io.Serializable;
+
+/**
+ * LogCommandBuilder is able to show the history of a file in a
+ * {@link Repository} or the entire history of a {@link Repository}.
+ * This class could be used to retrieve a single {@link Changeset} by its id
+ * or to get a list of changesets in a {@link ChangesetPagingResult}
+ * which can be used for paging.
+ *
+ * Samples:
+ *
+ *
+ * Retrieve a single {@link Changeset}:
+ *
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public final class LogCommandBuilder
+{
+
+ /** name of the cache */
+ static final String CACHE_NAME = "sonia.cache.cmd.log";
+
+ /**
+ * the logger for LogCommandBuilder
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(LogCommandBuilder.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs a new {@link LogCommandBuilder}, this constructor should
+ * only be called from the {@link RepositoryService}.
+ *
+ * @param cacheManager cache manager
+ * @param logCommand implementation of the {@link LogCommand}
+ * @param repository repository to query
+ * @param preProcessorUtil
+ */
+ LogCommandBuilder(CacheManager cacheManager, LogCommand logCommand,
+ Repository repository, PreProcessorUtil preProcessorUtil)
+ {
+ this.cache = cacheManager.getCache(CacheKey.class,
+ ChangesetPagingResult.class, CACHE_NAME);
+ this.logCommand = logCommand;
+ this.repository = repository;
+ this.preProcessorUtil = preProcessorUtil;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Disable paging limit all available changesets will be retrieved.
+ * This method does the same as {@link #setPagingLimit(int)}
+ * with a value of -1.
+ *
+ *
+ * @return {@code this}
+ */
+ public LogCommandBuilder disablePagingLimit()
+ {
+ request.setPagingLimit(-1);
+
+ return this;
+ }
+
+ /**
+ * Reset each parameter to its default value.
+ *
+ *
+ * @return {@code this}
+ */
+ public LogCommandBuilder reset()
+ {
+ request.reset();
+ this.disableCache = false;
+ this.disablePreProcessors = false;
+
+ return this;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Returns the {@link Changeset} with the given id or null if the
+ * {@link Changeset} could not be found in the {@link Repository}.
+ *
+ *
+ * @param id id of the {@link Changeset}
+ *
+ * @return the {@link Changeset} with the given id or null
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ public Changeset getChangeset(String id)
+ throws IOException, RepositoryException
+ {
+ Changeset changeset = null;
+
+ if (disableCache)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("get changeset for {} with disabled cache", id);
+ }
+
+ changeset = logCommand.getChangeset(id);
+ }
+ else
+ {
+ CacheKey key = new CacheKey(repository, id);
+ ChangesetPagingResult cpr = cache.get(key);
+
+ if (cpr == null)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("get changeset for {}", id);
+ }
+
+ changeset = logCommand.getChangeset(id);
+
+ if (changeset != null)
+ {
+ cpr = new ChangesetPagingResult(1, ImmutableList.of(changeset));
+ cache.put(key, cpr);
+ }
+ }
+ else
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("get changeset {} from cache", id);
+ }
+
+ changeset = cpr.iterator().next();
+ }
+ }
+
+ if (!disablePreProcessors && (changeset != null))
+ {
+ preProcessorUtil.prepareForReturn(repository, changeset);
+ }
+
+ return changeset;
+ }
+
+ /**
+ * Return all changesets with the given parameters.
+ *
+ *
+ * @return all changesets with the given parameters
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ public ChangesetPagingResult getChangesets()
+ throws IOException, RepositoryException
+ {
+ ChangesetPagingResult cpr = null;
+
+ if (disableCache)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("get changesets for {} with disabled cache", request);
+ }
+
+ cpr = logCommand.getChangesets(request);
+ }
+ else
+ {
+ CacheKey key = new CacheKey(repository, request);
+
+ cpr = cache.get(key);
+
+ if (cpr == null)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("get changesets for {}", request);
+ }
+
+ cpr = logCommand.getChangesets(request);
+
+ if (cpr != null)
+ {
+ cache.put(key, cpr);
+ }
+ }
+ else if (logger.isDebugEnabled())
+ {
+ logger.debug("get changesets from cache for {}", request);
+ }
+ }
+
+ if (!disablePreProcessors && (cpr != null))
+ {
+ preProcessorUtil.prepareForReturn(repository, cpr);
+ }
+
+ return cpr;
+ }
+
+ //~--- set methods ----------------------------------------------------------
+
+ /**
+ * Disables the cache for changesets. This means that every {@link Changeset}
+ * is directly retrieved from the {@link Repository}. Note: Disabling
+ * the cache cost a lot of performance and could be much more slower.
+ *
+ *
+ * @param disableCache true to disable the cache
+ *
+ * @return {@code this}
+ */
+ public LogCommandBuilder setDisableCache(boolean disableCache)
+ {
+ this.disableCache = disableCache;
+
+ return this;
+ }
+
+ /**
+ * Disable the execution of pre processors.
+ *
+ *
+ * @param disablePreProcessors true to disable the pre processors execution
+ *
+ * @return {@code this}
+ */
+ public LogCommandBuilder setDisablePreProcessors(boolean disablePreProcessors)
+ {
+ this.disablePreProcessors = disablePreProcessors;
+
+ return this;
+ }
+
+ /**
+ * Retrieve changesets until the given the {@link Changeset}
+ * with the given id.
+ *
+ *
+ * @param endChangeset id of the end {@link Changeset}
+ *
+ * @return {@code this}
+ */
+ public LogCommandBuilder setEndChangeset(String endChangeset)
+ {
+ request.setEndChangeset(endChangeset);
+
+ return this;
+ }
+
+ /**
+ * Set the limit for the returned changesets. The default value is 20.
+ * Setting the value to -1 means to disable the limit.
+ *
+ *
+ * @param pagingLimit limit for returned changesets
+ *
+ * @return {@code this}
+ */
+ public LogCommandBuilder setPagingLimit(int pagingLimit)
+ {
+ request.setPagingLimit(pagingLimit);
+
+ return this;
+ }
+
+ /**
+ * Sets the start value for paging. The value is 0.
+ *
+ *
+ * @param pagingStart start value for paging
+ *
+ * @return {@code this}
+ */
+ public LogCommandBuilder setPagingStart(int pagingStart)
+ {
+ request.setPagingStart(pagingStart);
+
+ return this;
+ }
+
+ /**
+ * Retrieve only changesets which are affect the given path.
+ *
+ *
+ * @param path file path in the {@link Repository}.
+ *
+ * @return {@code this}
+ */
+ public LogCommandBuilder setPath(String path)
+ {
+ request.setPath(path);
+
+ return this;
+ }
+
+ /**
+ * Start at the given {@link Changeset}.
+ *
+ *
+ * @param startChangeset changeset id to start with
+ *
+ * @return {@code this}
+ */
+ public LogCommandBuilder setStartChangeset(String startChangeset)
+ {
+ request.setStartChangeset(startChangeset);
+
+ return this;
+ }
+
+ //~--- inner classes --------------------------------------------------------
+
+ /**
+ * Class description
+ *
+ *
+ * @version Enter version here..., 12/06/05
+ * @author Enter your name here...
+ */
+ static class CacheKey implements RepositoryCacheKey, Serializable
+ {
+
+ /** Field description */
+ private static final long serialVersionUID = 5701675009949268863L;
+
+ //~--- constructors -------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param repository
+ * @param request
+ */
+ public CacheKey(Repository repository, LogCommandRequest request)
+ {
+ this.repositoryId = repository.getId();
+ this.request = request;
+ }
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param repository
+ * @param changesetId
+ */
+ public CacheKey(Repository repository, String changesetId)
+ {
+ this.repositoryId = repository.getId();
+ this.changesetId = changesetId;
+ }
+
+ //~--- methods ------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param obj
+ *
+ * @return
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+
+ final CacheKey other = (CacheKey) obj;
+
+ return Objects.equal(repositoryId, other.repositoryId)
+ && Objects.equal(changesetId, other.changesetId)
+ && Objects.equal(request, other.request);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public int hashCode()
+ {
+ return Objects.hashCode(repositoryId, changesetId, request);
+ }
+
+ //~--- get methods --------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public String getRepositoryId()
+ {
+ return repositoryId;
+ }
+
+ //~--- fields -------------------------------------------------------------
+
+ /** Field description */
+ private String changesetId;
+
+ /** Field description */
+ private String repositoryId;
+
+ /** Field description */
+ private LogCommandRequest request;
+ }
+
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** cache for changesets */
+ private Cache cache;
+
+ /** disable cache */
+ private boolean disableCache = false;
+
+ /** disable the execution of pre processors */
+ private boolean disablePreProcessors = false;
+
+ /** Implementation of the log command */
+ private LogCommand logCommand;
+
+ /** Field description */
+ private PreProcessorUtil preProcessorUtil;
+
+ /** repository to query */
+ private Repository repository;
+
+ /** request for the log command */
+ private LogCommandRequest request = new LogCommandRequest();
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java
new file mode 100644
index 0000000000..8c77eb83f8
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java
@@ -0,0 +1,271 @@
+/**
+ * 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.api;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.cache.CacheManager;
+import sonia.scm.repository.PreProcessorUtil;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.spi.RepositoryServiceProvider;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.Closeable;
+import java.io.IOException;
+
+/**
+ * From the {@link RepositoryService} it is possible to access all commands for
+ * a single {@link Repository}. The {@link RepositoryService} is only access
+ * able from the {@link RepositoryServiceFactory}.
+ *
+ *
+ * Note: Not every {@link RepositoryService} supports every command. If
+ * the command is not supported the method will trow a
+ * {@link CommandNotSupportedException}. It is possible to check if the command
+ * is supported by the {@link RepositoryService} with the
+ * {@link RepositoryService#isSupported(Command)} method.
+ *
+ *
+ * Warning: You should always close the connection to the repository
+ * after work is finished. For closing the connection to the repository use the
+ * {@link #close()} method.
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ *
+ * @apiviz.uses sonia.scm.repository.api.Command
+ * @apiviz.uses sonia.scm.repository.api.BlameCommandBuilder
+ * @apiviz.uses sonia.scm.repository.api.BrowseCommandBuilder
+ * @apiviz.uses sonia.scm.repository.api.CatCommandBuilder
+ * @apiviz.uses sonia.scm.repository.api.DiffCommandBuilder
+ * @apiviz.uses sonia.scm.repository.api.LogCommandBuilder
+ */
+public final class RepositoryService implements Closeable
+{
+
+ /**
+ * the logger for RepositoryService
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(RepositoryService.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs a new {@link RepositoryService}. This constructor should only
+ * be called from the {@link RepositoryServiceFactory}.
+ *
+ * @param cacheManager cache manager
+ * @param provider implementation for {@link RepositoryServiceProvider}
+ * @param repository the repository
+ * @param preProcessorUtil
+ */
+ RepositoryService(CacheManager cacheManager,
+ RepositoryServiceProvider provider, Repository repository,
+ PreProcessorUtil preProcessorUtil)
+ {
+ this.cacheManager = cacheManager;
+ this.provider = provider;
+ this.repository = repository;
+ this.preProcessorUtil = preProcessorUtil;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Closes the connection to the repository and releases all locks
+ * and resources. This method should be called in a finally block e.g.:
+ *
+ *
+ * RepositoryService service = null;
+ * try {
+ * service = factory.create("repositoryId");
+ * // do something with the service
+ * } finally {
+ * if ( service != null ){
+ * service.close();
+ * }
+ * }
+ *
+ */
+ @Override
+ public void close()
+ {
+ try
+ {
+ provider.close();
+ }
+ catch (IOException ex)
+ {
+ logger.error("cound not close repository service provider", ex);
+ }
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * The blame command shows changeset information by line for a given file.
+ *
+ * @return instance of {@link BlameCommandBuilder}
+ * @throws CommandNotSupportedException if the command is not supported
+ * by the implementation of the repository service provider.
+ */
+ public BlameCommandBuilder getBlameCommand()
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("create blame command for repository {}",
+ repository.getName());
+ }
+
+ return new BlameCommandBuilder(cacheManager, provider.getBlameCommand(),
+ repository, preProcessorUtil);
+ }
+
+ /**
+ * The browse command allows browsing of a repository.
+ *
+ * @return instance of {@link BrowseCommandBuilder}
+ * @throws CommandNotSupportedException if the command is not supported
+ * by the implementation of the repository service provider.
+ */
+ public BrowseCommandBuilder getBrowseCommand()
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("create browse command for repository {}",
+ repository.getName());
+ }
+
+ return new BrowseCommandBuilder(cacheManager, provider.getBrowseCommand(),
+ repository, preProcessorUtil);
+ }
+
+ /**
+ * The cat command show the content of a given file.
+ *
+ * @return instance of {@link CatCommandBuilder}
+ * @throws CommandNotSupportedException if the command is not supported
+ * by the implementation of the repository service provider.
+ */
+ public CatCommandBuilder getCatCommand()
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("create cat command for repository {}",
+ repository.getName());
+ }
+
+ return new CatCommandBuilder(provider.getCatCommand());
+ }
+
+ /**
+ * The diff command shows differences between revisions for a specified file
+ * or the entire revision.
+ *
+ * @return instance of {@link DiffCommandBuilder}
+ * @throws CommandNotSupportedException if the command is not supported
+ * by the implementation of the repository service provider.
+ */
+ public DiffCommandBuilder getDiffCommand()
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("create diff command for repository {}",
+ repository.getName());
+ }
+
+ return new DiffCommandBuilder(provider.getDiffCommand());
+ }
+
+ /**
+ * The log command shows revision history of entire repository or files.
+ *
+ * @return instance of {@link LogCommandBuilder}
+ * @throws CommandNotSupportedException if the command is not supported
+ * by the implementation of the repository service provider.
+ */
+ public LogCommandBuilder getLogCommand()
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("create log command for repository {}",
+ repository.getName());
+ }
+
+ return new LogCommandBuilder(cacheManager, provider.getLogCommand(),
+ repository, preProcessorUtil);
+ }
+
+ /**
+ * Returns the repository of this service.
+ *
+ * @return repository of this service
+ */
+ public Repository getRepository()
+ {
+ return repository;
+ }
+
+ /**
+ * Returns true if the command is supported by the repository service.
+ *
+ *
+ * @param command command
+ *
+ * @return true if the command is supported
+ */
+ public boolean isSupported(Command command)
+ {
+ return provider.getSupportedCommands().contains(command);
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** cache manager */
+ private CacheManager cacheManager;
+
+ /** Field description */
+ private PreProcessorUtil preProcessorUtil;
+
+ /** implementation of the repository service provider */
+ private RepositoryServiceProvider provider;
+
+ /** the repository */
+ private Repository repository;
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java
new file mode 100644
index 0000000000..0b42f0820b
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceFactory.java
@@ -0,0 +1,406 @@
+/**
+ * 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.api;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.HandlerEvent;
+import sonia.scm.cache.Cache;
+import sonia.scm.cache.CacheManager;
+import sonia.scm.repository.BlameResult;
+import sonia.scm.repository.BrowserResult;
+import sonia.scm.repository.ChangesetPagingResult;
+import sonia.scm.repository.PermissionType;
+import sonia.scm.repository.PermissionUtil;
+import sonia.scm.repository.PostReceiveRepositoryHook;
+import sonia.scm.repository.PreProcessorUtil;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryCacheKeyFilter;
+import sonia.scm.repository.RepositoryHookEvent;
+import sonia.scm.repository.RepositoryListener;
+import sonia.scm.repository.RepositoryManager;
+import sonia.scm.repository.RepositoryNotFoundException;
+import sonia.scm.repository.spi.RepositoryServiceProvider;
+import sonia.scm.repository.spi.RepositoryServiceResolver;
+import sonia.scm.security.ScmSecurityException;
+import sonia.scm.web.security.WebSecurityContext;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.util.Set;
+
+/**
+ * The {@link RepositoryServiceFactory} is the entrypoint of the repository api.
+ * You could create {@link RepositoryService} from a {@link Repository} and
+ * with the {@link RepositoryService} you could browse and control the entire
+ * {@link Repository}.
+ *
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ *
+ * @apiviz.landmark
+ * @apiviz.uses sonia.scm.repository.api.RepositoryService
+ */
+@Singleton
+public final class RepositoryServiceFactory
+{
+
+ /**
+ * the logger for RepositoryServiceFactory
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(RepositoryServiceFactory.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs a new {@link RepositoryServiceFactory}. This constructor
+ * should not be called manually, it should only be used by the injection
+ * container.
+ *
+ * @param cacheManager cache manager
+ * @param repositoryManager manager for repositories
+ * @param securityContextProvider provider for the current security context
+ * @param resolvers a set of {@link RepositoryServiceResolver}
+ * @param preProcessorUtil helper object for pre processor handling
+ */
+ @Inject
+ public RepositoryServiceFactory(
+ CacheManager cacheManager, RepositoryManager repositoryManager,
+ Provider securityContextProvider,
+ Set resolvers,
+ PreProcessorUtil preProcessorUtil)
+ {
+ this.cacheManager = cacheManager;
+ this.repositoryManager = repositoryManager;
+ this.securityContextProvider = securityContextProvider;
+ this.resolvers = resolvers;
+ this.preProcessorUtil = preProcessorUtil;
+
+ CacheClearHook cch = new CacheClearHook(cacheManager);
+
+ repositoryManager.addHook(cch);
+ repositoryManager.addListener(cch);
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Creates a new RepositoryService for the given repository.
+ *
+ *
+ * @param repositoryId id of the repository
+ *
+ * @return a implementation of RepositoryService
+ * for the given type of repository
+ *
+ * @throws RepositoryNotFoundException if no repository
+ * with the given id is available
+ * @throws RepositoryServiceNotFoundException if no repository service
+ * implementation for this kind of repository is available
+ * @throws IllegalArgumentException if the repository id is null or empty
+ * @throws ScmSecurityException if current user has not read permissions
+ * for that repository
+ */
+ public RepositoryService create(String repositoryId)
+ throws RepositoryNotFoundException
+ {
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(repositoryId),
+ "a non empty repositoryId is required");
+
+ Repository repository = repositoryManager.get(repositoryId);
+
+ if (repository == null)
+ {
+ throw new RepositoryNotFoundException(
+ "could not find a repository with id ".concat(repositoryId));
+ }
+
+ return create(repository);
+ }
+
+ /**
+ * Creates a new RepositoryService for the given repository.
+ *
+ *
+ * @param type type of the repository
+ * @param name name of the repository
+ *
+ * @return a implementation of RepositoryService
+ * for the given type of repository
+ *
+ * @throws RepositoryNotFoundException if no repository
+ * with the given id is available
+ * @throws RepositoryServiceNotFoundException if no repository service
+ * implementation for this kind of repository is available
+ * @throws IllegalArgumentException if one of the parameters is null or empty
+ * @throws ScmSecurityException if current user has not read permissions
+ * for that repository
+ */
+ public RepositoryService create(String type, String name)
+ throws RepositoryNotFoundException
+ {
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(type),
+ "a non empty type is required");
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(name),
+ "a non empty name is required");
+
+ Repository repository = repositoryManager.get(type, name);
+
+ if (repository == null)
+ {
+ StringBuilder msg =
+ new StringBuilder("could not find a repository with type ");
+
+ msg.append(type).append(" and name ").append(name);
+
+ throw new RepositoryNotFoundException(msg.toString());
+ }
+
+ return create(repository);
+ }
+
+ /**
+ * Creates a new RepositoryService for the given repository.
+ *
+ *
+ * @param repository the repository
+ *
+ * @return a implementation of RepositoryService
+ * for the given type of repository
+ *
+ * @throws RepositoryServiceNotFoundException if no repository service
+ * implementation for this kind of repository is available
+ * @throws NullPointerException if the repository is null
+ * @throws ScmSecurityException if current user has not read permissions
+ * for that repository
+ */
+ public RepositoryService create(Repository repository)
+ {
+ Preconditions.checkNotNull(repository, "repository is required");
+
+ // check for read permissions of current user
+ PermissionUtil.assertPermission(repository, securityContextProvider,
+ PermissionType.READ);
+
+ RepositoryService service = null;
+
+ for (RepositoryServiceResolver resolver : resolvers)
+ {
+ RepositoryServiceProvider provider = resolver.reslove(repository);
+
+ if (provider != null)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(
+ "create new repository service for repository {} of type {}",
+ repository.getName(), repository.getType());
+ }
+
+ service = new RepositoryService(cacheManager, provider, repository,
+ preProcessorUtil);
+
+ break;
+ }
+ }
+
+ if (service == null)
+ {
+ throw new RepositoryServiceNotFoundException(repository);
+ }
+
+ return service;
+ }
+
+ //~--- inner classes --------------------------------------------------------
+
+ /**
+ * TODO find a more elegant way
+ *
+ *
+ * @version Enter version here..., 12/06/16
+ * @author Enter your name here...
+ */
+ private static class CacheClearHook extends PostReceiveRepositoryHook
+ implements RepositoryListener
+ {
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param cacheManager
+ */
+ public CacheClearHook(CacheManager cacheManager)
+ {
+ this.blameCache =
+ cacheManager.getCache(BlameCommandBuilder.CacheKey.class,
+ BlameResult.class,
+ BlameCommandBuilder.CACHE_NAME);
+ this.browseCache =
+ cacheManager.getCache(BrowseCommandBuilder.CacheKey.class,
+ BrowserResult.class,
+ BrowseCommandBuilder.CACHE_NAME);
+ this.logCache = cacheManager.getCache(LogCommandBuilder.CacheKey.class,
+ ChangesetPagingResult.class, LogCommandBuilder.CACHE_NAME);
+ }
+
+ //~--- methods ------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param event
+ */
+ @Override
+ public void onEvent(RepositoryHookEvent event)
+ {
+ Repository repository = event.getRepository();
+
+ if (repository != null)
+ {
+ String id = repository.getId();
+
+ clearCaches(id);
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ * @param event
+ */
+ @Override
+ public void onEvent(Repository repository, HandlerEvent event)
+ {
+ if (event == HandlerEvent.DELETE)
+ {
+ clearCaches(repository.getId());
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param repositoryId
+ */
+ @SuppressWarnings("unchecked")
+ private void clearCaches(final String repositoryId)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("clear caches for repository id {}", repositoryId);
+ }
+
+ RepositoryCacheKeyFilter filter =
+ new RepositoryCacheKeyFilter(repositoryId);
+
+ blameCache.removeAll(filter);
+ browseCache.removeAll(filter);
+ logCache.removeAll(filter);
+ }
+
+ //~--- fields -------------------------------------------------------------
+
+ /** Field description */
+ private Cache blameCache;
+
+ /** Field description */
+ private Cache browseCache;
+
+ /** Field description */
+ private Cache logCache;
+ }
+
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private CacheManager cacheManager;
+
+ /** Field description */
+ private PreProcessorUtil preProcessorUtil;
+
+ /** Field description */
+ private RepositoryManager repositoryManager;
+
+ /** Field description */
+ private Set resolvers;
+
+ /** Field description */
+ private Provider securityContextProvider;
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceNotFoundException.java b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceNotFoundException.java
new file mode 100644
index 0000000000..09d6b43a4d
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryServiceNotFoundException.java
@@ -0,0 +1,80 @@
+/**
+ * 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.api;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.Repository;
+
+/**
+ * This exception is throw if no {@link RepositoryService}
+ * is available for the given {@link Repository}.
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public final class RepositoryServiceNotFoundException extends RuntimeException
+{
+
+ /**
+ * Constructs a new {@link RepositoryServiceNotFoundException}.
+ *
+ *
+ * @param repository unsupported repository
+ */
+ public RepositoryServiceNotFoundException(Repository repository)
+ {
+ super("could not find a repository service provider implementation for repository "
+ .concat(repository.getName()));
+ this.repository = repository;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Returns the unsupported repository.
+ *
+ *
+ * @return unsupported repository
+ */
+ public Repository getRepository()
+ {
+ return repository;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** unsupported repository */
+ private Repository repository;
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/package-info.java b/scm-core/src/main/java/sonia/scm/repository/api/package-info.java
new file mode 100644
index 0000000000..a1713ee6a9
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/api/package-info.java
@@ -0,0 +1,37 @@
+/**
+ * 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
+ *
+ */
+
+
+
+/**
+ * API for repository access.
+ */
+package sonia.scm.repository.api;
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/BlameCommand.java b/scm-core/src/main/java/sonia/scm/repository/spi/BlameCommand.java
new file mode 100644
index 0000000000..80c155a534
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/BlameCommand.java
@@ -0,0 +1,66 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.BlameResult;
+import sonia.scm.repository.RepositoryException;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public interface BlameCommand
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ public BlameResult getBlameResult(BlameCommandRequest request)
+ throws IOException, RepositoryException;
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/BlameCommandRequest.java b/scm-core/src/main/java/sonia/scm/repository/spi/BlameCommandRequest.java
new file mode 100644
index 0000000000..f7df5a4371
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/BlameCommandRequest.java
@@ -0,0 +1,68 @@
+/**
+ * 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.spi;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public final class BlameCommandRequest extends FileBaseCommandRequest
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public BlameCommandRequest clone()
+ {
+ BlameCommandRequest clone = null;
+
+ try
+ {
+ clone = (BlameCommandRequest) super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+
+ // this shouldn't happen, since we are Cloneable
+ throw new InternalError("BlameCommandRequest seems not to be cloneable");
+ }
+
+ return clone;
+ }
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/BrowseCommand.java b/scm-core/src/main/java/sonia/scm/repository/spi/BrowseCommand.java
new file mode 100644
index 0000000000..4afc02b125
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/BrowseCommand.java
@@ -0,0 +1,66 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.BrowserResult;
+import sonia.scm.repository.RepositoryException;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public interface BrowseCommand
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ public BrowserResult getBrowserResult(BrowseCommandRequest request)
+ throws IOException, RepositoryException;
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/BrowseCommandRequest.java b/scm-core/src/main/java/sonia/scm/repository/spi/BrowseCommandRequest.java
new file mode 100644
index 0000000000..52fbf96a0d
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/BrowseCommandRequest.java
@@ -0,0 +1,46 @@
+/**
+ * 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.spi;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.Serializable;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public final class BrowseCommandRequest extends FileBaseCommandRequest
+ implements Resetable, Serializable {}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/CatCommand.java b/scm-core/src/main/java/sonia/scm/repository/spi/CatCommand.java
new file mode 100644
index 0000000000..b9a6f52ab0
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/CatCommand.java
@@ -0,0 +1,65 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.RepositoryException;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public interface CatCommand
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ * @param output
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ public void getCatResult(CatCommandRequest request, OutputStream output)
+ throws IOException, RepositoryException;
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/CatCommandRequest.java b/scm-core/src/main/java/sonia/scm/repository/spi/CatCommandRequest.java
new file mode 100644
index 0000000000..1673204b1a
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/CatCommandRequest.java
@@ -0,0 +1,69 @@
+/**
+ * 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.spi;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public final class CatCommandRequest extends FileBaseCommandRequest
+ implements Cloneable
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public CatCommandRequest clone()
+ {
+ CatCommandRequest clone = null;
+
+ try
+ {
+ clone = (CatCommandRequest) super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+
+ // this shouldn't happen, since we are Cloneable
+ throw new InternalError("CatCommandRequest seems not to be cloneable");
+ }
+
+ return clone;
+ }
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/DiffCommand.java b/scm-core/src/main/java/sonia/scm/repository/spi/DiffCommand.java
new file mode 100644
index 0000000000..a4d0c24444
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/DiffCommand.java
@@ -0,0 +1,66 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.RepositoryException;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public interface DiffCommand
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ * @param output
+ *
+ * @throws IOException
+ * @throws RuntimeException
+ * @throws RepositoryException
+ */
+ public void getDiffResult(DiffCommandRequest request, OutputStream output)
+ throws IOException, RepositoryException;
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/DiffCommandRequest.java b/scm-core/src/main/java/sonia/scm/repository/spi/DiffCommandRequest.java
new file mode 100644
index 0000000000..daca399877
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/DiffCommandRequest.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.repository.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Strings;
+
+import sonia.scm.Validateable;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public final class DiffCommandRequest extends FileBaseCommandRequest
+ implements Cloneable, Validateable
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public DiffCommandRequest clone()
+ {
+ DiffCommandRequest clone = null;
+
+ try
+ {
+ clone = (DiffCommandRequest) super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+
+ // this shouldn't happen, since we are Cloneable
+ throw new InternalError("DiffCommandRequest seems not to be cloneable");
+ }
+
+ return clone;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public boolean isValid()
+ {
+ return !Strings.isNullOrEmpty(getPath())
+ ||!Strings.isNullOrEmpty(getRevision());
+ }
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/FileBaseCommandRequest.java b/scm-core/src/main/java/sonia/scm/repository/spi/FileBaseCommandRequest.java
new file mode 100644
index 0000000000..83491a4b22
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/FileBaseCommandRequest.java
@@ -0,0 +1,205 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Objects;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.Serializable;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public abstract class FileBaseCommandRequest
+ implements Resetable, Serializable, Cloneable
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param obj
+ *
+ * @return
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+
+ final FileBaseCommandRequest other = (FileBaseCommandRequest) obj;
+
+ return Objects.equal(path, other.path)
+ && Objects.equal(revision, other.revision);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public int hashCode()
+ {
+ return Objects.hashCode(path, revision);
+ }
+
+ /**
+ * Method description
+ *
+ */
+ @Override
+ public void reset()
+ {
+ path = null;
+ revision = null;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public String toString()
+ {
+ //J-
+ return Objects.toStringHelper(this)
+ .add("path", path)
+ .add("revision", revision)
+ .toString();
+ //J+
+ }
+
+ //~--- set methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param path
+ */
+ public void setPath(String path)
+ {
+ this.path = path;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param revision
+ */
+ public void setRevision(String revision)
+ {
+ this.revision = revision;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ String getPath()
+ {
+ return path;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ String getRevision()
+ {
+ return revision;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ *
+ * @throws CloneNotSupportedException
+ */
+ @Override
+ protected FileBaseCommandRequest clone() throws CloneNotSupportedException
+ {
+ FileBaseCommandRequest clone = null;
+
+ try
+ {
+ clone = (FileBaseCommandRequest) super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+
+ // this shouldn't happen, since we are Cloneable
+ throw new InternalError(
+ "FileBaseCommandRequest seems not to be cloneable");
+ }
+
+ return clone;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private String path;
+
+ /** Field description */
+ private String revision;
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/LogCommand.java b/scm-core/src/main/java/sonia/scm/repository/spi/LogCommand.java
new file mode 100644
index 0000000000..168c279c19
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/LogCommand.java
@@ -0,0 +1,81 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.Changeset;
+import sonia.scm.repository.ChangesetPagingResult;
+import sonia.scm.repository.RepositoryException;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public interface LogCommand
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param id
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ public Changeset getChangeset(String id)
+ throws IOException, RepositoryException;
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ public ChangesetPagingResult getChangesets(LogCommandRequest request)
+ throws IOException, RepositoryException;
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/LogCommandRequest.java b/scm-core/src/main/java/sonia/scm/repository/spi/LogCommandRequest.java
new file mode 100644
index 0000000000..f1ec3e206c
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/LogCommandRequest.java
@@ -0,0 +1,270 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Objects;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.Serializable;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public final class LogCommandRequest implements Serializable, Resetable
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param obj
+ *
+ * @return
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+
+ final LogCommandRequest other = (LogCommandRequest) obj;
+
+ return Objects.equal(startChangeset, other.startChangeset)
+ && Objects.equal(endChangeset, other.endChangeset)
+ && Objects.equal(pagingStart, other.pagingStart)
+ && Objects.equal(pagingLimit, other.pagingLimit)
+ && Objects.equal(path, other.path);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public int hashCode()
+ {
+ return Objects.hashCode(startChangeset, endChangeset, pagingStart,
+ pagingLimit, path);
+ }
+
+ /**
+ * Method description
+ *
+ */
+ @Override
+ public void reset()
+ {
+ startChangeset = null;
+ endChangeset = null;
+ pagingStart = 0;
+ pagingLimit = 20;
+ path = null;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public String toString()
+ {
+ //J-
+ return Objects.toStringHelper(this)
+ .add("startChangeset", startChangeset)
+ .add("endChangeset", endChangeset)
+ .add("pagingStart", pagingStart)
+ .add("pagingLimit", pagingLimit)
+ .add("path", path)
+ .toString();
+ //J+
+ }
+
+ //~--- set methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param endChangeset
+ */
+ public void setEndChangeset(String endChangeset)
+ {
+ this.endChangeset = endChangeset;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param pagingLimit
+ */
+ public void setPagingLimit(int pagingLimit)
+ {
+ this.pagingLimit = pagingLimit;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param pagingStart
+ */
+ public void setPagingStart(int pagingStart)
+ {
+ this.pagingStart = pagingStart;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param path
+ */
+ public void setPath(String path)
+ {
+ this.path = path;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param startChangeset
+ */
+ public void setStartChangeset(String startChangeset)
+ {
+ this.startChangeset = startChangeset;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ String getEndChangeset()
+ {
+ return endChangeset;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ int getPagingLimit()
+ {
+ return pagingLimit;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ int getPagingStart()
+ {
+ return pagingStart;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ String getPath()
+ {
+ return path;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ String getStartChangeset()
+ {
+ return startChangeset;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ boolean isPagingUnlimited()
+ {
+ return pagingLimit < 0;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private String endChangeset;
+
+ /** Field description */
+ private int pagingLimit = 20;
+
+ /** Field description */
+ private int pagingStart = 0;
+
+ /** Field description */
+ private String path;
+
+ /** Field description */
+ private String startChangeset;
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java b/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java
new file mode 100644
index 0000000000..8fbc820d04
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java
@@ -0,0 +1,137 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.api.Command;
+import sonia.scm.repository.api.CommandNotSupportedException;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import java.util.Set;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public abstract class RepositoryServiceProvider implements Closeable
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public abstract Set getSupportedCommands();
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * The default implementation of this method does nothing. If you need to
+ * free resources, close connections or release locks than you have to
+ * override this method.
+ *
+ *
+ * @throws IOException
+ */
+ @Override
+ public void close() throws IOException
+ {
+
+ // should be implmentented from a service provider
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public BlameCommand getBlameCommand()
+ {
+ throw new CommandNotSupportedException(Command.BLAME);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public BrowseCommand getBrowseCommand()
+ {
+ throw new CommandNotSupportedException(Command.BROWSE);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public CatCommand getCatCommand()
+ {
+ throw new CommandNotSupportedException(Command.CAT);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public DiffCommand getDiffCommand()
+ {
+ throw new CommandNotSupportedException(Command.DIFF);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public LogCommand getLogCommand()
+ {
+ throw new CommandNotSupportedException(Command.LOG);
+ }
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceResolver.java b/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceResolver.java
new file mode 100644
index 0000000000..f0ed4c0814
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceResolver.java
@@ -0,0 +1,59 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.plugin.ExtensionPoint;
+import sonia.scm.repository.Repository;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+@ExtensionPoint
+public interface RepositoryServiceResolver
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ *
+ * @return
+ */
+ public RepositoryServiceProvider reslove(Repository repository);
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/Resetable.java b/scm-core/src/main/java/sonia/scm/repository/spi/Resetable.java
new file mode 100644
index 0000000000..e438955c54
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/Resetable.java
@@ -0,0 +1,49 @@
+/**
+ * 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.spi;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public interface Resetable
+{
+
+ /**
+ * Method description
+ *
+ */
+ public void reset();
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/package-info.java b/scm-core/src/main/java/sonia/scm/repository/spi/package-info.java
new file mode 100644
index 0000000000..b6a0c7f646
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/package-info.java
@@ -0,0 +1,37 @@
+/**
+ * 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
+ *
+ */
+
+
+
+/**
+ * SPI for repository access. This package is only for service provider.
+ */
+package sonia.scm.repository.spi;
diff --git a/scm-core/src/main/java/sonia/scm/resources/ResourceNameComparator.java b/scm-core/src/main/java/sonia/scm/resources/ResourceNameComparator.java
index 720c374c3e..bd3cbb4960 100644
--- a/scm-core/src/main/java/sonia/scm/resources/ResourceNameComparator.java
+++ b/scm-core/src/main/java/sonia/scm/resources/ResourceNameComparator.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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.resources;
//~--- non-JDK imports --------------------------------------------------------
diff --git a/scm-core/src/main/java/sonia/scm/store/AbstractListenableStore.java b/scm-core/src/main/java/sonia/scm/store/AbstractListenableStore.java
index c31ec49e08..b7263b2f17 100644
--- a/scm-core/src/main/java/sonia/scm/store/AbstractListenableStore.java
+++ b/scm-core/src/main/java/sonia/scm/store/AbstractListenableStore.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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.store;
//~--- non-JDK imports --------------------------------------------------------
diff --git a/scm-core/src/main/java/sonia/scm/store/ListenableStore.java b/scm-core/src/main/java/sonia/scm/store/ListenableStore.java
index 36c9364e76..026f3dc644 100644
--- a/scm-core/src/main/java/sonia/scm/store/ListenableStore.java
+++ b/scm-core/src/main/java/sonia/scm/store/ListenableStore.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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.store;
//~--- non-JDK imports --------------------------------------------------------
diff --git a/scm-core/src/main/java/sonia/scm/store/ListenableStoreFactory.java b/scm-core/src/main/java/sonia/scm/store/ListenableStoreFactory.java
index 0fee1b62ae..abc67352b3 100644
--- a/scm-core/src/main/java/sonia/scm/store/ListenableStoreFactory.java
+++ b/scm-core/src/main/java/sonia/scm/store/ListenableStoreFactory.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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.store;
/**
diff --git a/scm-core/src/main/java/sonia/scm/util/Util.java b/scm-core/src/main/java/sonia/scm/util/Util.java
index e8e9cadc3b..bfa109f4ec 100644
--- a/scm-core/src/main/java/sonia/scm/util/Util.java
+++ b/scm-core/src/main/java/sonia/scm/util/Util.java
@@ -47,6 +47,7 @@ import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
@@ -398,6 +399,23 @@ public class Util
return parseDate(dateString, null);
}
+ /**
+ * Method description
+ *
+ *
+ * @param value
+ * @param start
+ *
+ * @return
+ *
+ * @since 1.17
+ */
+ public static boolean startWithIgnoreCase(String value, String start)
+ {
+ return (value != null) && (start != null)
+ && value.toUpperCase(Locale.ENGLISH).startsWith(start);
+ }
+
/**
* Method description
*
diff --git a/scm-core/src/main/java/sonia/scm/web/cgi/CGIStatusCodeHandler.java b/scm-core/src/main/java/sonia/scm/web/cgi/CGIStatusCodeHandler.java
index 5efb6fe1e1..d0f8418517 100644
--- a/scm-core/src/main/java/sonia/scm/web/cgi/CGIStatusCodeHandler.java
+++ b/scm-core/src/main/java/sonia/scm/web/cgi/CGIStatusCodeHandler.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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.cgi;
//~--- JDK imports ------------------------------------------------------------
diff --git a/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java
index db33f7f53c..386f27bcd3 100644
--- a/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java
+++ b/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java
@@ -120,18 +120,44 @@ public class BasicAuthenticationFilter extends HttpFilter
User user = null;
String authentication = request.getHeader(HEADER_AUTHORIZATION);
- if (Util.isNotEmpty(authentication)
- && authentication.toUpperCase().startsWith(AUTHORIZATION_BASIC_PREFIX))
+ if (Util.startWithIgnoreCase(authentication, AUTHORIZATION_BASIC_PREFIX))
{
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("found basic authorization header, start authentication");
+ }
+
user = authenticate(request, response, securityContext, authentication);
+
+ if (logger.isTraceEnabled())
+ {
+ if (user != null)
+ {
+ logger.trace("user {} successfully authenticated", user.getName());
+ }
+ else
+ {
+ logger.trace("authentcation failed, user object is null");
+ }
+ }
}
else if (securityContext.isAuthenticated())
{
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("user is allready authenticated");
+ }
+
user = securityContext.getUser();
}
if (user == null)
{
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("could not find user send unauthorized");
+ }
+
HttpUtil.sendUnauthorized(response);
}
else
@@ -192,6 +218,11 @@ public class BasicAuthenticationFilter extends HttpFilter
if (Util.isNotEmpty(username) && Util.isNotEmpty(password))
{
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("try to authenticate user {}", username);
+ }
+
user = securityContext.authenticate(request, response, username,
password);
}
diff --git a/scm-core/src/main/java/sonia/scm/web/filter/LoggingFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/LoggingFilter.java
index 6b3e62695e..42a228af9b 100644
--- a/scm-core/src/main/java/sonia/scm/web/filter/LoggingFilter.java
+++ b/scm-core/src/main/java/sonia/scm/web/filter/LoggingFilter.java
@@ -35,6 +35,8 @@ package sonia.scm.web.filter;
//~--- non-JDK imports --------------------------------------------------------
+import com.google.common.base.Strings;
+import com.google.common.io.Closeables;
import com.google.inject.Singleton;
import org.slf4j.Logger;
@@ -89,7 +91,7 @@ public class LoggingFilter extends HttpFilter
{
if (logger.isDebugEnabled())
{
- boolean logBody = logger.isTraceEnabled();
+ boolean logBody = logger.isTraceEnabled() && isTextRequest(request);
BufferedHttpServletRequest bufferedRequest =
new BufferedHttpServletRequest(request, logBody);
BufferedHttpServletResponse bufferedResponse =
@@ -189,7 +191,12 @@ public class LoggingFilter extends HttpFilter
if (logger.isTraceEnabled())
{
- logger.trace("Content: ".concat(new String(request.getContentBuffer())));
+ byte[] contentBuffer = request.getContentBuffer();
+
+ if ((contentBuffer != null) && (contentBuffer.length > 0))
+ {
+ logger.trace("Content: ".concat(new String(contentBuffer)));
+ }
}
}
@@ -227,22 +234,68 @@ public class LoggingFilter extends HttpFilter
logger.debug("Header: {} = {}", header.getKey(), header.getValue());
}
- if (logger.isTraceEnabled())
+ if (logger.isTraceEnabled() && isTextRequest(orgResponse))
{
byte[] content = response.getContentBuffer();
- ServletOutputStream out = null;
- try
+ if ((content != null) && (content.length > 0))
{
- out = orgResponse.getOutputStream();
- out.write(content);
- }
- finally
- {
- out.close();
- }
+ ServletOutputStream out = null;
- logger.trace("Content: ".concat(new String(content)));
+ try
+ {
+ out = orgResponse.getOutputStream();
+ out.write(content);
+ }
+ finally
+ {
+ Closeables.closeQuietly(out);
+ }
+
+ logger.trace("Content: ".concat(new String(content)));
+ }
}
}
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ *
+ * @return
+ */
+ private boolean isTextRequest(HttpServletRequest request)
+ {
+ return isTextRequest(request.getContentType());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param response
+ *
+ * @return
+ */
+ private boolean isTextRequest(HttpServletResponse response)
+ {
+ return isTextRequest(response.getContentType());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param contentType
+ *
+ * @return
+ */
+ private boolean isTextRequest(String contentType)
+ {
+ return !Strings.isNullOrEmpty(contentType)
+ && contentType.toLowerCase().startsWith("text");
+ }
}
diff --git a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java
index 1e031cead4..fd03813a46 100644
--- a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java
+++ b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java
@@ -151,6 +151,15 @@ public abstract class PermissionFilter extends HttpFilter
if (hasPermission(repository, securityContext, writeRequest))
{
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("{} access to repository {} for user {} granted",
+ new Object[] { writeRequest
+ ? "write"
+ : "read", repository.getName(),
+ user.getName() });
+ }
+
chain.doFilter(request, response);
}
else
diff --git a/scm-core/src/test/java/sonia/scm/repository/RepositoryTest.java b/scm-core/src/test/java/sonia/scm/repository/RepositoryTest.java
new file mode 100644
index 0000000000..98e714b67f
--- /dev/null
+++ b/scm-core/src/test/java/sonia/scm/repository/RepositoryTest.java
@@ -0,0 +1,62 @@
+/**
+ * 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 org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class RepositoryTest
+{
+
+ /**
+ * Method description
+ *
+ */
+ @Test
+ public void testCreateUrl()
+ {
+ Repository repository = new Repository("123", "hg", "test/repo");
+
+ assertEquals("http://localhost:8080/scm/hg/test/repo",
+ repository.createUrl("http://localhost:8080/scm"));
+ assertEquals("http://localhost:8080/scm/hg/test/repo",
+ repository.createUrl("http://localhost:8080/scm/"));
+ }
+}
diff --git a/scm-core/src/test/java/sonia/scm/util/IOUtilTest.java b/scm-core/src/test/java/sonia/scm/util/IOUtilTest.java
index 675fb68b23..d35aab1506 100644
--- a/scm-core/src/test/java/sonia/scm/util/IOUtilTest.java
+++ b/scm-core/src/test/java/sonia/scm/util/IOUtilTest.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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.util;
//~--- non-JDK imports --------------------------------------------------------
diff --git a/scm-dao-orientdb/pom.xml b/scm-dao-orientdb/pom.xml
index 8b51c104eb..16ebe46cf2 100644
--- a/scm-dao-orientdb/pom.xml
+++ b/scm-dao-orientdb/pom.xml
@@ -6,12 +6,12 @@
sonia.scmscm
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scmscm-dao-orientdb
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-dao-orientdb
@@ -26,7 +26,7 @@
sonia.scmscm-core
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOT
@@ -52,7 +52,7 @@
sonia.scmscm-test
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTtest
diff --git a/scm-dao-xml/pom.xml b/scm-dao-xml/pom.xml
index c6d49f47d2..d23f2cfe24 100644
--- a/scm-dao-xml/pom.xml
+++ b/scm-dao-xml/pom.xml
@@ -6,12 +6,12 @@
sonia.scmscm
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scmscm-dao-xml
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-dao-xml
@@ -26,7 +26,7 @@
sonia.scmscm-core
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOT
@@ -34,7 +34,7 @@
sonia.scmscm-test
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTtest
diff --git a/scm-plugin-backend/pom.xml b/scm-plugin-backend/pom.xml
index 0db75ef201..4966149d4a 100644
--- a/scm-plugin-backend/pom.xml
+++ b/scm-plugin-backend/pom.xml
@@ -6,13 +6,13 @@
scmsonia.scm
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scmscm-plugin-backendwar
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOT${project.artifactId}
@@ -42,7 +42,7 @@
sonia.scmscm-core
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOT
diff --git a/scm-plugins/pom.xml b/scm-plugins/pom.xml
index f1917c6cf6..ed7a59bff7 100644
--- a/scm-plugins/pom.xml
+++ b/scm-plugins/pom.xml
@@ -6,13 +6,13 @@
sonia.scmscm
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.pluginsscm-pluginspom
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-plugins
@@ -26,7 +26,7 @@
sonia.scmscm-core
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOT
@@ -59,7 +59,7 @@
sonia.scm.mavenscm-maven-plugin
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTprocess-resources
diff --git a/scm-plugins/scm-git-plugin/pom.xml b/scm-plugins/scm-git-plugin/pom.xml
index 41cdd07593..81bc875c00 100644
--- a/scm-plugins/scm-git-plugin/pom.xml
+++ b/scm-plugins/scm-git-plugin/pom.xml
@@ -6,12 +6,12 @@
scm-pluginssonia.scm.plugins
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.pluginsscm-git-plugin
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-git-pluginhttps://bitbucket.org/sdorra/scm-managerPlugin for the version control system Git
@@ -55,7 +55,7 @@
sonia.scmscm-test
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTtest
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitBlameViewer.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitBlameViewer.java
index c6cf493433..6e575db31f 100644
--- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitBlameViewer.java
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitBlameViewer.java
@@ -37,6 +37,7 @@ package sonia.scm.repository;
import org.eclipse.jgit.api.BlameCommand;
import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.blame.BlameResult;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
@@ -123,20 +124,19 @@ public class GitBlameViewer implements BlameViewer
List blameLines = new ArrayList();
int total = gitBlameResult.getResultContents().size();
int i = 0;
-
+
for (; i < total; i++)
{
- RevCommit commit = gitBlameResult.getSourceCommit(i);
-
- if ( commit != null )
- {
+ RevCommit commit = gitBlameResult.getSourceCommit(i);
+
+ if (commit != null)
+ {
PersonIdent author = gitBlameResult.getSourceAuthor(i);
BlameLine blameLine = new BlameLine();
blameLine.setLineNumber(i + 1);
blameLine.setAuthor(new Person(author.getName(),
author.getEmailAddress()));
-
blameLine.setDescription(commit.getShortMessage());
long when = GitUtil.getCommitTime(commit);
@@ -151,7 +151,7 @@ public class GitBlameViewer implements BlameViewer
blameLine.setCode(content);
blameLines.add(blameLine);
- }
+ }
}
blameResult = new sonia.scm.repository.BlameResult(i, blameLines);
@@ -160,6 +160,10 @@ public class GitBlameViewer implements BlameViewer
{
logger.error("could not open repository", ex);
}
+ catch (GitAPIException ex)
+ {
+ logger.error("could not create blame view", ex);
+ }
return blameResult;
}
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetConverter.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetConverter.java
index 549b6103a3..c638f992d8 100644
--- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetConverter.java
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetConverter.java
@@ -237,9 +237,9 @@ public class GitChangesetConverter implements Closeable
}
else
{
- if (logger.isWarnEnabled())
+ if (logger.isTraceEnabled())
{
- logger.warn("no parent at position 0 for commit {}", commit);
+ logger.trace("no parent at position 0 for commit {}", commit);
}
treeWalk.addTree(new EmptyTreeIterator());
@@ -247,9 +247,9 @@ public class GitChangesetConverter implements Closeable
}
else
{
- if (logger.isWarnEnabled())
+ if (logger.isTraceEnabled())
{
- logger.warn("no parent available for commit {}", commit);
+ logger.trace("no parent available for commit {}", commit);
}
treeWalk.addTree(new EmptyTreeIterator());
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetViewer.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetViewer.java
index 30ef4111c6..4fdb4713bd 100644
--- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetViewer.java
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetViewer.java
@@ -36,6 +36,7 @@ package sonia.scm.repository;
//~--- non-JDK imports --------------------------------------------------------
import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -198,6 +199,10 @@ public class GitChangesetViewer implements ChangesetViewer
{
logger.error("could not read changesets", ex);
}
+ catch (GitAPIException ex)
+ {
+ logger.error("could not read changesets", ex);
+ }
catch (IOException ex)
{
logger.error("could not open repository", ex);
@@ -279,6 +284,10 @@ public class GitChangesetViewer implements ChangesetViewer
{
logger.error("could not read changesets", ex);
}
+ catch (GitAPIException ex)
+ {
+ logger.error("could not read changesets", ex);
+ }
catch (IOException ex)
{
logger.error("could not open repository", ex);
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java
index bbfc5728ed..07ab9709b8 100644
--- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java
@@ -155,6 +155,36 @@ public class GitUtil
//~--- get methods ----------------------------------------------------------
+ /**
+ * Method description
+ *
+ *
+ * @param repo
+ * @param branchName
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ public static ObjectId getBranchId(org.eclipse.jgit.lib.Repository repo,
+ String branchName)
+ throws IOException
+ {
+ ObjectId branchId = null;
+ Ref ref = repo.getRef(branchName);
+
+ if (ref != null)
+ {
+ branchId = ref.getObjectId();
+ }
+ else if (logger.isWarnEnabled())
+ {
+ logger.warn("could not find branch for {}", branchName);
+ }
+
+ return branchId;
+ }
+
/**
* Method description
*
@@ -209,9 +239,9 @@ public class GitUtil
}
}
- if (logger.isInfoEnabled())
+ if (logger.isDebugEnabled())
{
- logger.info("use {}:{} as repository head", head, id);
+ logger.debug("use {}:{} as repository head", head, id);
}
return id;
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java
new file mode 100644
index 0000000000..dc26777f65
--- /dev/null
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java
@@ -0,0 +1,88 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.eclipse.jgit.lib.Repository;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class AbstractGitCommand
+{
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ protected AbstractGitCommand(GitContext context,
+ sonia.scm.repository.Repository repository)
+ {
+ this.repository = repository;
+ this.context = context;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ protected Repository open() throws IOException
+ {
+ return context.open();
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ protected GitContext context;
+
+ /** Field description */
+ protected sonia.scm.repository.Repository repository;
+}
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBlameCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBlameCommand.java
new file mode 100644
index 0000000000..a48b4b2b1e
--- /dev/null
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBlameCommand.java
@@ -0,0 +1,182 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.repository.BlameLine;
+import sonia.scm.repository.BlameResult;
+import sonia.scm.repository.GitUtil;
+import sonia.scm.repository.Person;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryException;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class GitBlameCommand extends AbstractGitCommand implements BlameCommand
+{
+
+ /**
+ * the logger for GitBlameCommand
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(GitBlameCommand.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ public GitBlameCommand(GitContext context, Repository repository)
+ {
+ super(context, repository);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public BlameResult getBlameResult(BlameCommandRequest request)
+ throws IOException, RepositoryException
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("try to create blame for {}", request);
+ }
+
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(request.getPath()),
+ "path is empty or null");
+
+ BlameResult result = null;
+
+ try
+ {
+ org.eclipse.jgit.lib.Repository gr = open();
+ org.eclipse.jgit.api.BlameCommand blame = new Git(gr).blame();
+
+ blame.setFilePath(request.getPath());
+
+ ObjectId revId = GitUtil.getRevisionId(gr, request.getRevision());
+
+ blame.setStartCommit(revId);
+
+ org.eclipse.jgit.blame.BlameResult gitBlameResult = blame.call();
+
+ if (gitBlameResult == null)
+ {
+ throw new RepositoryException(
+ "could not create blame result for path ".concat(
+ request.getPath()));
+ }
+
+ List blameLines = new ArrayList();
+ int total = gitBlameResult.getResultContents().size();
+ int i = 0;
+
+ for (; i < total; i++)
+ {
+ RevCommit commit = gitBlameResult.getSourceCommit(i);
+
+ if (commit != null)
+ {
+ PersonIdent author = gitBlameResult.getSourceAuthor(i);
+ BlameLine blameLine = new BlameLine();
+
+ blameLine.setLineNumber(i + 1);
+ blameLine.setAuthor(new Person(author.getName(),
+ author.getEmailAddress()));
+ blameLine.setDescription(commit.getShortMessage());
+
+ long when = GitUtil.getCommitTime(commit);
+
+ blameLine.setWhen(when);
+
+ String rev = commit.getId().getName();
+
+ blameLine.setRevision(rev);
+
+ String content = gitBlameResult.getResultContents().getString(i);
+
+ blameLine.setCode(content);
+ blameLines.add(blameLine);
+ }
+ }
+
+ result = new BlameResult(i, blameLines);
+ }
+ catch (GitAPIException ex)
+ {
+ throw new RepositoryException("could not create blame view", ex);
+ }
+
+ return result;
+ }
+}
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBrowseCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBrowseCommand.java
new file mode 100644
index 0000000000..3dc4eacd80
--- /dev/null
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBrowseCommand.java
@@ -0,0 +1,469 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevTree;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
+import org.eclipse.jgit.treewalk.filter.PathFilter;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.repository.BrowserResult;
+import sonia.scm.repository.FileObject;
+import sonia.scm.repository.GitSubModuleParser;
+import sonia.scm.repository.GitUtil;
+import sonia.scm.repository.PathNotFoundException;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.repository.SubRepository;
+import sonia.scm.util.Util;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class GitBrowseCommand extends AbstractGitCommand
+ implements BrowseCommand
+{
+
+ /** Field description */
+ public static final String PATH_MODULES = ".gitmodules";
+
+ /**
+ * the logger for GitBrowseCommand
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(GitBrowseCommand.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ public GitBrowseCommand(GitContext context, Repository repository)
+ {
+ super(context, repository);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public BrowserResult getBrowserResult(BrowseCommandRequest request)
+ throws IOException, RepositoryException
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("try to create browse result for {}", request);
+ }
+
+ BrowserResult result = null;
+ org.eclipse.jgit.lib.Repository repo = open();
+ ObjectId revId = null;
+
+ if (Util.isEmpty(request.getRevision()))
+ {
+ revId = GitUtil.getRepositoryHead(repo);
+ }
+ else
+ {
+ revId = GitUtil.getRevisionId(repo, request.getRevision());
+ }
+
+ if (revId != null)
+ {
+ result = getResult(repo, revId, request.getPath());
+ }
+ else
+ {
+ if (Util.isNotEmpty(request.getRevision()))
+ {
+ logger.error("could not find revision {}", request.getRevision());
+ }
+ else if (logger.isWarnEnabled())
+ {
+ logger.warn("coul not find head of repository, empty?");
+ }
+
+ result = new BrowserResult(Constants.HEAD, null, null,
+ new ArrayList());
+ }
+
+ return result;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param files
+ * @param repo
+ * @param revId
+ * @param path
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ private void appendSubModules(List files,
+ org.eclipse.jgit.lib.Repository repo,
+ ObjectId revId, String path)
+ throws IOException, RepositoryException
+ {
+ path = Util.nonNull(path);
+
+ Map subRepositories = getSubRepositories(repo,
+ revId);
+
+ if (subRepositories != null)
+ {
+ for (Entry e : subRepositories.entrySet())
+ {
+ String p = e.getKey();
+
+ if (p.startsWith(path))
+ {
+ p = p.substring(path.length());
+
+ if (p.startsWith("/"))
+ {
+ p = p.substring(1);
+ }
+
+ if (p.endsWith("/"))
+ {
+ p = p.substring(0, p.length() - 1);
+ }
+
+ if (!p.contains("/"))
+ {
+ FileObject fo = new FileObject();
+
+ fo.setDirectory(true);
+ fo.setPath(path);
+ fo.setName(p);
+ fo.setSubRepository(e.getValue());
+ files.add(fo);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ *
+ *
+ * @param repo
+ * @param revId
+ * @param treeWalk
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ private FileObject createFileObject(org.eclipse.jgit.lib.Repository repo,
+ ObjectId revId, TreeWalk treeWalk)
+ throws IOException
+ {
+ FileObject file = null;
+
+ try
+ {
+ file = new FileObject();
+
+ String path = treeWalk.getPathString();
+
+ file.setName(treeWalk.getNameString());
+ file.setPath(path);
+
+ ObjectLoader loader = repo.open(treeWalk.getObjectId(0));
+
+ file.setDirectory(loader.getType() == Constants.OBJ_TREE);
+ file.setLength(loader.getSize());
+
+ // don't show message and date for directories to improve performance
+ if (!file.isDirectory())
+ {
+ RevCommit commit = getLatestCommit(repo, revId, path);
+
+ if (commit != null)
+ {
+ file.setLastModified(GitUtil.getCommitTime(commit));
+ file.setDescription(commit.getShortMessage());
+ }
+ else if (logger.isWarnEnabled())
+ {
+ logger.warn("could not find latest commit for {} on {}", path, revId);
+ }
+ }
+ }
+ catch (MissingObjectException ex)
+ {
+ file = null;
+ logger.error("could not fetch object for id {}", revId);
+
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("could not fetch object", ex);
+ }
+ }
+
+ return file;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ *
+ * @param repo
+ * @param revId
+ * @param path
+ *
+ * @return
+ */
+ private RevCommit getLatestCommit(org.eclipse.jgit.lib.Repository repo,
+ ObjectId revId, String path)
+ {
+ RevCommit result = null;
+ RevWalk walk = null;
+
+ try
+ {
+ walk = new RevWalk(repo);
+ walk.setTreeFilter(AndTreeFilter.create(PathFilter.create(path),
+ TreeFilter.ANY_DIFF));
+
+ RevCommit commit = walk.parseCommit(revId);
+
+ walk.markStart(commit);
+ result = Util.getFirst(walk);
+ }
+ catch (Exception ex)
+ {
+ logger.error("could not parse commit for file", ex);
+ }
+ finally
+ {
+ GitUtil.release(walk);
+ }
+
+ return result;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param repo
+ * @param revId
+ * @param path
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ private BrowserResult getResult(org.eclipse.jgit.lib.Repository repo,
+ ObjectId revId, String path)
+ throws IOException, RepositoryException
+ {
+ BrowserResult result = null;
+ RevWalk revWalk = null;
+ TreeWalk treeWalk = null;
+
+ try
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("load repository browser for revision {}", revId.name());
+ }
+
+ treeWalk = new TreeWalk(repo);
+ revWalk = new RevWalk(repo);
+
+ RevTree tree = revWalk.parseTree(revId);
+
+ if (tree != null)
+ {
+ treeWalk.addTree(tree);
+ }
+ else
+ {
+ logger.error("could not find tree for {}", revId.name());
+ }
+
+ result = new BrowserResult();
+
+ List files = new ArrayList();
+
+ appendSubModules(files, repo, revId, path);
+
+ if (Util.isEmpty(path))
+ {
+ while (treeWalk.next())
+ {
+ FileObject fo = createFileObject(repo, revId, treeWalk);
+
+ if (fo != null)
+ {
+ files.add(fo);
+ }
+ }
+ }
+ else
+ {
+ String[] parts = path.split("/");
+ int current = 0;
+ int limit = parts.length;
+
+ while (treeWalk.next())
+ {
+ String name = treeWalk.getNameString();
+
+ if (current >= limit)
+ {
+ String p = treeWalk.getPathString();
+
+ if (p.split("/").length > limit)
+ {
+ FileObject fo = createFileObject(repo, revId, treeWalk);
+
+ if (fo != null)
+ {
+ files.add(fo);
+ }
+ }
+ }
+ else if (name.equalsIgnoreCase(parts[current]))
+ {
+ current++;
+ treeWalk.enterSubtree();
+ }
+ }
+ }
+
+ result.setFiles(files);
+ result.setRevision(revId.getName());
+ }
+ finally
+ {
+ GitUtil.release(revWalk);
+ GitUtil.release(treeWalk);
+ }
+
+ return result;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param repo
+ * @param revision
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ private Map getSubRepositories(
+ org.eclipse.jgit.lib.Repository repo, ObjectId revision)
+ throws IOException, RepositoryException
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("read submodules of {} at {}", repository.getName(),
+ revision);
+ }
+
+ Map subRepositories = null;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ try
+ {
+ new GitCatCommand(context, repository).getContent(repo, revision,
+ PATH_MODULES, baos);
+ subRepositories = GitSubModuleParser.parse(baos.toString());
+ }
+ catch (PathNotFoundException ex)
+ {
+ logger.trace("could not find .gitmodules", ex);
+ }
+
+ return subRepositories;
+ }
+}
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitCatCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitCatCommand.java
new file mode 100644
index 0000000000..17dad775b1
--- /dev/null
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitCatCommand.java
@@ -0,0 +1,195 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevTree;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.filter.PathFilter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.repository.GitUtil;
+import sonia.scm.repository.PathNotFoundException;
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.util.Util;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class GitCatCommand extends AbstractGitCommand implements CatCommand
+{
+
+ /**
+ * the logger for GitCatCommand
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(GitCatCommand.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ public GitCatCommand(GitContext context,
+ sonia.scm.repository.Repository repository)
+ {
+ super(context, repository);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ * @param output
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public void getCatResult(CatCommandRequest request, OutputStream output)
+ throws IOException, RepositoryException
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("try to read content for {}", request);
+ }
+
+ org.eclipse.jgit.lib.Repository repo = null;
+
+ repo = open();
+
+ ObjectId revId = GitUtil.getRevisionId(repo, request.getRevision());
+
+ getContent(repo, revId, request.getPath(), output);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ *
+ * @param repo
+ * @param revId
+ * @param path
+ * @param output
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ void getContent(org.eclipse.jgit.lib.Repository repo, ObjectId revId,
+ String path, OutputStream output)
+ throws IOException, RepositoryException
+ {
+ TreeWalk treeWalk = null;
+ RevWalk revWalk = null;
+
+ try
+ {
+ treeWalk = new TreeWalk(repo);
+ treeWalk.setRecursive(Util.nonNull(path).contains("/"));
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("load content for {} at {}", path, revId.name());
+ }
+
+ revWalk = new RevWalk(repo);
+
+ RevCommit entry = revWalk.parseCommit(revId);
+ RevTree revTree = entry.getTree();
+
+ if (revTree != null)
+ {
+ treeWalk.addTree(revTree);
+ }
+ else
+ {
+ logger.error("could not find tree for {}", revId.name());
+ }
+
+ treeWalk.setFilter(PathFilter.create(path));
+
+ if (treeWalk.next())
+ {
+
+ // Path exists
+ if (treeWalk.getFileMode(0).getObjectType() == Constants.OBJ_BLOB)
+ {
+ ObjectId blobId = treeWalk.getObjectId(0);
+ ObjectLoader loader = repo.open(blobId);
+
+ loader.copyTo(output);
+ }
+ else
+ {
+
+ // Not a blob, its something else (tree, gitlink)
+ throw new PathNotFoundException(path);
+ }
+ }
+ else
+ {
+ throw new PathNotFoundException(path);
+ }
+ }
+ finally
+ {
+ GitUtil.release(revWalk);
+ GitUtil.release(treeWalk);
+ }
+ }
+}
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitContext.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitContext.java
new file mode 100644
index 0000000000..b003395e5a
--- /dev/null
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitContext.java
@@ -0,0 +1,122 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.repository.GitUtil;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class GitContext implements Closeable
+{
+
+ /**
+ * the logger for GitContext
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(GitContext.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param directory
+ */
+ public GitContext(File directory)
+ {
+ this.directory = directory;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ */
+ @Override
+ public void close()
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("close git repository {}", directory);
+ }
+
+ GitUtil.close(repository);
+ repository = null;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ public org.eclipse.jgit.lib.Repository open() throws IOException
+ {
+ if (repository == null)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("open git repository {}", directory);
+ }
+
+ repository = GitUtil.open(directory);
+ }
+
+ return repository;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private File directory;
+
+ /** Field description */
+ private org.eclipse.jgit.lib.Repository repository;
+}
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitDiffCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitDiffCommand.java
new file mode 100644
index 0000000000..a8edfa8848
--- /dev/null
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitDiffCommand.java
@@ -0,0 +1,171 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.eclipse.jgit.diff.DiffEntry;
+import org.eclipse.jgit.diff.DiffFormatter;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevTree;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.treewalk.EmptyTreeIterator;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.filter.PathFilter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.repository.GitUtil;
+import sonia.scm.repository.Repository;
+import sonia.scm.util.Util;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.BufferedOutputStream;
+import java.io.OutputStream;
+
+import java.util.List;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class GitDiffCommand extends AbstractGitCommand implements DiffCommand
+{
+
+ /**
+ * the logger for GitDiffCommand
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(GitDiffCommand.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ public GitDiffCommand(GitContext context, Repository repository)
+ {
+ super(context, repository);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ * @param output
+ */
+ @Override
+ public void getDiffResult(DiffCommandRequest request, OutputStream output)
+ {
+ RevWalk walk = null;
+ TreeWalk treeWalk = null;
+ DiffFormatter formatter = null;
+
+ try
+ {
+ org.eclipse.jgit.lib.Repository gr = open();
+
+ walk = new RevWalk(gr);
+
+ RevCommit commit = walk.parseCommit(gr.resolve(request.getRevision()));
+
+ walk.markStart(commit);
+ commit = walk.next();
+ treeWalk = new TreeWalk(gr);
+ treeWalk.reset();
+ treeWalk.setRecursive(true);
+
+ if (Util.isNotEmpty(request.getPath()))
+ {
+ treeWalk.setFilter(PathFilter.create(request.getPath()));
+ }
+
+ if (commit.getParentCount() > 0)
+ {
+ RevTree tree = commit.getParent(0).getTree();
+
+ if (tree != null)
+ {
+ treeWalk.addTree(tree);
+ }
+ else
+ {
+ treeWalk.addTree(new EmptyTreeIterator());
+ }
+ }
+ else
+ {
+ treeWalk.addTree(new EmptyTreeIterator());
+ }
+
+ treeWalk.addTree(commit.getTree());
+ formatter = new DiffFormatter(new BufferedOutputStream(output));
+ formatter.setRepository(gr);
+
+ List entries = DiffEntry.scan(treeWalk);
+
+ for (DiffEntry e : entries)
+ {
+ if (!e.getOldId().equals(e.getNewId()))
+ {
+ formatter.format(e);
+ }
+ }
+
+ formatter.flush();
+ }
+ catch (Exception ex)
+ {
+
+ // TODO throw exception
+ logger.error("could not create diff", ex);
+ }
+ finally
+ {
+ GitUtil.release(walk);
+ GitUtil.release(treeWalk);
+ GitUtil.release(formatter);
+ }
+ }
+}
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java
new file mode 100644
index 0000000000..dbcc023bd3
--- /dev/null
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java
@@ -0,0 +1,282 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.api.errors.NoHeadException;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.errors.StopWalkException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.revwalk.filter.RevFilter;
+import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
+import org.eclipse.jgit.treewalk.filter.PathFilter;
+import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.repository.Changeset;
+import sonia.scm.repository.ChangesetPagingResult;
+import sonia.scm.repository.GitChangesetConverter;
+import sonia.scm.repository.GitUtil;
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.util.IOUtil;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class GitLogCommand extends AbstractGitCommand implements LogCommand
+{
+
+ /**
+ * the logger for GitLogCommand
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(GitLogCommand.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ GitLogCommand(GitContext context, sonia.scm.repository.Repository repository)
+ {
+ super(context, repository);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param revision
+ *
+ * @return
+ */
+ @Override
+ public Changeset getChangeset(String revision)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("fetch changeset {}", revision);
+ }
+
+ Changeset changeset = null;
+ Repository gr = null;
+ GitChangesetConverter converter = null;
+
+ try
+ {
+ gr = open();
+
+ if (!gr.getAllRefs().isEmpty())
+ {
+ RevWalk revWalk = new RevWalk(gr);
+ ObjectId id = GitUtil.getRevisionId(gr, revision);
+ RevCommit commit = revWalk.parseCommit(id);
+
+ if (commit != null)
+ {
+ converter = new GitChangesetConverter(gr, revWalk, GitUtil.ID_LENGTH);
+ changeset = converter.createChangeset(commit);
+ }
+ else if (logger.isWarnEnabled())
+ {
+ logger.warn("could not find revision {}", revision);
+ }
+ }
+ }
+ catch (IOException ex)
+ {
+ logger.error("could not open repository", ex);
+ }
+ finally
+ {
+ IOUtil.close(converter);
+ GitUtil.close(gr);
+ }
+
+ return changeset;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public ChangesetPagingResult getChangesets(LogCommandRequest request)
+ throws IOException, RepositoryException
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("fetch changesets for request: {}", request);
+ }
+
+ ChangesetPagingResult changesets = null;
+ GitChangesetConverter converter = null;
+
+ try
+ {
+ org.eclipse.jgit.lib.Repository gr = open();
+
+ if (!gr.getAllRefs().isEmpty())
+ {
+ int counter = 0;
+ int start = request.getPagingStart();
+
+ if (start < 0)
+ {
+ if (logger.isErrorEnabled())
+ {
+ logger.error("start parameter is negative, reset to 0");
+ }
+
+ start = 0;
+ }
+
+ List changesetList = Lists.newArrayList();
+ int limit = request.getPagingLimit();
+ ObjectId startId = null;
+
+ if (!Strings.isNullOrEmpty(request.getStartChangeset()))
+ {
+ startId = gr.resolve(request.getStartChangeset());
+ }
+
+ ObjectId endId = null;
+
+ if (!Strings.isNullOrEmpty(request.getEndChangeset()))
+ {
+ endId = gr.resolve(request.getEndChangeset());
+ }
+
+ RevWalk revWalk = new RevWalk(gr);
+
+ converter = new GitChangesetConverter(gr, revWalk, GitUtil.ID_LENGTH);
+
+ if (!Strings.isNullOrEmpty(request.getPath()))
+ {
+ revWalk.setTreeFilter(
+ AndTreeFilter.create(
+ PathFilter.create(request.getPath()), TreeFilter.ANY_DIFF));
+ }
+
+ ObjectId head = GitUtil.getRepositoryHead(gr);
+
+ if (head != null)
+ {
+ if (startId != null)
+ {
+ revWalk.markStart(revWalk.lookupCommit(startId));
+ }
+ else
+ {
+ revWalk.markStart(revWalk.lookupCommit(head));
+ }
+
+ Iterator iterator = revWalk.iterator();
+
+ while (iterator.hasNext())
+ {
+ RevCommit commit = iterator.next();
+
+ if ((counter >= start)
+ && ((limit < 0) || (counter < start + limit)))
+ {
+ changesetList.add(converter.createChangeset(commit));
+ }
+
+ counter++;
+
+ if ((endId != null) && commit.getId().equals(endId))
+ {
+ break;
+ }
+ }
+ }
+
+ changesets = new ChangesetPagingResult(counter, changesetList);
+ }
+ else if (logger.isWarnEnabled())
+ {
+ logger.warn("the repository {} seems to be empty",
+ repository.getName());
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new RepositoryException("could not create change log", ex);
+ }
+ finally
+ {
+ IOUtil.close(converter);
+ }
+
+ return changesets;
+ }
+}
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java
new file mode 100644
index 0000000000..097d72b6b8
--- /dev/null
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java
@@ -0,0 +1,172 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.collect.ImmutableSet;
+
+import sonia.scm.repository.GitRepositoryHandler;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.api.Command;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+import java.util.Set;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class GitRepositoryServiceProvider extends RepositoryServiceProvider
+{
+
+ /** Field description */
+ private static final Set COMMANDS = ImmutableSet.of(Command.BLAME,
+ Command.BROWSE, Command.CAT,
+ Command.DIFF, Command.LOG);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param handler
+ * @param repository
+ */
+ public GitRepositoryServiceProvider(GitRepositoryHandler handler,
+ Repository repository)
+ {
+ this.repository = repository;
+ context = new GitContext(handler.getDirectory(repository));
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ */
+ @Override
+ public void close() throws IOException
+ {
+ context.close();
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public BlameCommand getBlameCommand()
+ {
+ return new GitBlameCommand(context, repository);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public BrowseCommand getBrowseCommand()
+ {
+ return new GitBrowseCommand(context, repository);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public CatCommand getCatCommand()
+ {
+ return new GitCatCommand(context, repository);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public DiffCommand getDiffCommand()
+ {
+ return new GitDiffCommand(context, repository);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public LogCommand getLogCommand()
+ {
+ return new GitLogCommand(context, repository);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public Set getSupportedCommands()
+ {
+ return COMMANDS;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private GitContext context;
+
+ /** Field description */
+ private Repository repository;
+}
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java
new file mode 100644
index 0000000000..da46605cd7
--- /dev/null
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java
@@ -0,0 +1,95 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.inject.Inject;
+
+import sonia.scm.plugin.ext.Extension;
+import sonia.scm.repository.GitRepositoryHandler;
+import sonia.scm.repository.Repository;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+@Extension
+public class GitRepositoryServiceResolver implements RepositoryServiceResolver
+{
+
+ /** Field description */
+ public static final String TYPE = "git";
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param handler
+ */
+ @Inject
+ public GitRepositoryServiceResolver(GitRepositoryHandler handler)
+ {
+ this.handler = handler;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ *
+ * @return
+ */
+ @Override
+ public GitRepositoryServiceProvider reslove(Repository repository)
+ {
+ GitRepositoryServiceProvider provider = null;
+
+ if (TYPE.equalsIgnoreCase(repository.getType()))
+ {
+ provider = new GitRepositoryServiceProvider(handler, repository);
+ }
+
+ return provider;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private GitRepositoryHandler handler;
+}
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitRepositoryViewer.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitRepositoryViewer.java
index 689a175ee2..857884a888 100644
--- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitRepositoryViewer.java
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitRepositoryViewer.java
@@ -38,12 +38,16 @@ package sonia.scm.web;
import org.apache.commons.lang.StringEscapeUtils;
import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import sonia.scm.io.RegexResourceProcessor;
import sonia.scm.io.ResourceProcessor;
import sonia.scm.repository.GitUtil;
@@ -75,6 +79,12 @@ public class GitRepositoryViewer
/** Field description */
public static final String RESOURCE_GITINDEX = "/sonia/scm/git.index.html";
+ /**
+ * the logger for GitRepositoryViewer
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(GitRepositoryViewer.class);
+
//~--- methods --------------------------------------------------------------
/**
@@ -107,16 +117,23 @@ public class GitRepositoryViewer
int c = 0;
ObjectId head = GitUtil.getRepositoryHead(repository);
- for (RevCommit commit : git.log().add(head).call())
+ try
{
- appendCommit(sb, commit);
- c++;
-
- if (c > logSize)
+ for (RevCommit commit : git.log().add(head).call())
{
- break;
+ appendCommit(sb, commit);
+ c++;
+
+ if (c > logSize)
+ {
+ break;
+ }
}
}
+ catch (GitAPIException ex)
+ {
+ logger.error("could not read changesets", ex);
+ }
}
processor.addVariable("commits", sb.toString());
diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/AbstractGitCommandTestBase.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/AbstractGitCommandTestBase.java
new file mode 100644
index 0000000000..496b71e656
--- /dev/null
+++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/AbstractGitCommandTestBase.java
@@ -0,0 +1,102 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.junit.After;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class AbstractGitCommandTestBase extends ZippedRepositoryTestBase
+{
+
+ /**
+ * Method description
+ *
+ */
+ @After
+ public void close()
+ {
+ context.close();
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ protected GitContext createContext()
+ {
+ if (context == null)
+ {
+ context = new GitContext(repositoryDirectory);
+ }
+
+ return context;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ protected String getType()
+ {
+ return "git";
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ protected String getZippedRepositoryResource()
+ {
+ return "sonia/scm/repository/spi/scm-git-spi-test.zip";
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private GitContext context;
+}
diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBlameCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBlameCommandTest.java
new file mode 100644
index 0000000000..953372020b
--- /dev/null
+++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBlameCommandTest.java
@@ -0,0 +1,144 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.junit.Test;
+
+import sonia.scm.repository.BlameLine;
+import sonia.scm.repository.BlameResult;
+import sonia.scm.repository.RepositoryException;
+
+import static org.junit.Assert.*;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class GitBlameCommandTest extends AbstractGitCommandTestBase
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetBlameResult() throws IOException, RepositoryException
+ {
+ BlameCommandRequest request = new BlameCommandRequest();
+
+ request.setPath("a.txt");
+
+ BlameResult result = createCommand().getBlameResult(request);
+
+ assertNotNull(result);
+ assertEquals(2, result.getTotal());
+
+ BlameLine line = result.getLine(0);
+
+ checkFirstLine(line);
+ line = result.getLine(1);
+ assertEquals(2, line.getLineNumber());
+ assertEquals("fcd0ef1831e4002ac43ea539f4094334c79ea9ec",
+ line.getRevision());
+ checkDate(line.getWhen());
+ assertEquals("line for blame", line.getCode());
+ assertEquals("added new line for blame", line.getDescription());
+ assertEquals("Zaphod Beeblebrox", line.getAuthor().getName());
+ assertEquals("zaphod.beeblebrox@hitchhiker.com",
+ line.getAuthor().getMail());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetBlameResultWithRevision()
+ throws IOException, RepositoryException
+ {
+ BlameCommandRequest request = new BlameCommandRequest();
+
+ request.setPath("a.txt");
+ request.setRevision("86a6645eceefe8b9a247db5eb16e3d89a7e6e6d1");
+
+ BlameResult result = createCommand().getBlameResult(request);
+
+ assertNotNull(result);
+ assertEquals(1, result.getTotal());
+
+ BlameLine line = result.getLine(0);
+
+ checkFirstLine(line);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param line
+ */
+ private void checkFirstLine(BlameLine line)
+ {
+ assertEquals(1, line.getLineNumber());
+ assertEquals("435df2f061add3589cb326cc64be9b9c3897ceca",
+ line.getRevision());
+ checkDate(line.getWhen());
+ assertEquals("a", line.getCode());
+ assertEquals("added a and b files", line.getDescription());
+ assertEquals("Douglas Adams", line.getAuthor().getName());
+ assertEquals("douglas.adams@hitchhiker.com", line.getAuthor().getMail());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ private GitBlameCommand createCommand()
+ {
+ return new GitBlameCommand(createContext(), repository);
+ }
+}
diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBrowseCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBrowseCommandTest.java
new file mode 100644
index 0000000000..d891053f22
--- /dev/null
+++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBrowseCommandTest.java
@@ -0,0 +1,172 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.junit.Test;
+
+import sonia.scm.repository.BrowserResult;
+import sonia.scm.repository.FileObject;
+import sonia.scm.repository.RepositoryException;
+
+import static org.junit.Assert.*;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+import java.util.List;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class GitBrowseCommandTest extends AbstractGitCommandTestBase
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testBrowse() throws IOException, RepositoryException
+ {
+ BrowserResult result =
+ createCommand().getBrowserResult(new BrowseCommandRequest());
+
+ assertNotNull(result);
+
+ List foList = result.getFiles();
+
+ assertNotNull(foList);
+ assertFalse(foList.isEmpty());
+ assertEquals(4, foList.size());
+
+ FileObject a = null;
+ FileObject c = null;
+
+ for (FileObject f : foList)
+ {
+ if ("a.txt".equals(f.getName()))
+ {
+ a = f;
+ }
+ else if ("c".equals(f.getName()))
+ {
+ c = f;
+ }
+ }
+
+ assertNotNull(a);
+ assertFalse(a.isDirectory());
+ assertEquals("a.txt", a.getName());
+ assertEquals("a.txt", a.getPath());
+ assertEquals("added new line for blame", a.getDescription());
+ assertTrue(a.getLength() > 0);
+ checkDate(a.getLastModified());
+ assertNotNull(c);
+ assertTrue(c.isDirectory());
+ assertEquals("c", c.getName());
+ assertEquals("c", c.getPath());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testBrowseSubDirectory() throws IOException, RepositoryException
+ {
+ BrowseCommandRequest request = new BrowseCommandRequest();
+
+ request.setPath("c");
+
+ BrowserResult result = createCommand().getBrowserResult(request);
+
+ assertNotNull(result);
+
+ List foList = result.getFiles();
+
+ assertNotNull(foList);
+ assertFalse(foList.isEmpty());
+ assertEquals(2, foList.size());
+
+ FileObject d = null;
+ FileObject e = null;
+
+ for (FileObject f : foList)
+ {
+ if ("d.txt".equals(f.getName()))
+ {
+ d = f;
+ }
+ else if ("e.txt".equals(f.getName()))
+ {
+ e = f;
+ }
+ }
+
+ assertNotNull(d);
+ assertFalse(d.isDirectory());
+ assertEquals("d.txt", d.getName());
+ assertEquals("c/d.txt", d.getPath());
+ assertEquals("added file d and e in folder c", d.getDescription());
+ assertTrue(d.getLength() > 0);
+ checkDate(d.getLastModified());
+ assertNotNull(e);
+ assertFalse(e.isDirectory());
+ assertEquals("e.txt", e.getName());
+ assertEquals("c/e.txt", e.getPath());
+ assertEquals("added file d and e in folder c", e.getDescription());
+ assertTrue(e.getLength() > 0);
+ checkDate(e.getLastModified());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ private GitBrowseCommand createCommand()
+ {
+ return new GitBrowseCommand(createContext(), repository);
+ }
+}
diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitCatCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitCatCommandTest.java
new file mode 100644
index 0000000000..1a44a0076c
--- /dev/null
+++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitCatCommandTest.java
@@ -0,0 +1,118 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.junit.Test;
+
+import sonia.scm.repository.RepositoryException;
+
+import static org.junit.Assert.*;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * TODO add not found test
+ *
+ * @author Sebastian Sdorra
+ */
+public class GitCatCommandTest extends AbstractGitCommandTestBase
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testCat() throws IOException, RepositoryException
+ {
+ CatCommandRequest request = new CatCommandRequest();
+
+ request.setPath("a.txt");
+ request.setRevision("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4");
+ assertEquals("a and b", execute(request));
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testSimpleCat() throws IOException, RepositoryException
+ {
+ CatCommandRequest request = new CatCommandRequest();
+
+ request.setPath("b.txt");
+ assertEquals("b", execute(request));
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ private String execute(CatCommandRequest request)
+ throws IOException, RepositoryException
+ {
+ String content = null;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ try
+ {
+ new GitCatCommand(createContext(), repository).getCatResult(request,
+ baos);
+ }
+ finally
+ {
+ content = baos.toString().trim();
+ }
+
+ return content;
+ }
+}
diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java
new file mode 100644
index 0000000000..5f7f9055fb
--- /dev/null
+++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java
@@ -0,0 +1,232 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.junit.Test;
+
+import sonia.scm.repository.Changeset;
+import sonia.scm.repository.ChangesetPagingResult;
+import sonia.scm.repository.Modifications;
+import sonia.scm.repository.RepositoryException;
+
+import static org.hamcrest.Matchers.*;
+
+import static org.junit.Assert.*;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class GitLogCommandTest extends AbstractGitCommandTestBase
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetAll() throws IOException, RepositoryException
+ {
+ ChangesetPagingResult result =
+ createCommand().getChangesets(new LogCommandRequest());
+
+ assertNotNull(result);
+ assertEquals(4, result.getTotal());
+ assertEquals(4, result.getChangesets().size());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetAllByPath() throws IOException, RepositoryException
+ {
+ LogCommandRequest request = new LogCommandRequest();
+
+ request.setPath("a.txt");
+
+ ChangesetPagingResult result = createCommand().getChangesets(request);
+
+ assertNotNull(result);
+ assertEquals(2, result.getTotal());
+ assertEquals(2, result.getChangesets().size());
+ assertEquals("fcd0ef1831e4002ac43e", result.getChangesets().get(0).getId());
+ assertEquals("435df2f061add3589cb3", result.getChangesets().get(1).getId());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetAllWithLimit() throws IOException, RepositoryException
+ {
+ LogCommandRequest request = new LogCommandRequest();
+
+ request.setPagingLimit(2);
+
+ ChangesetPagingResult result = createCommand().getChangesets(request);
+
+ assertNotNull(result);
+ assertEquals(4, result.getTotal());
+ assertEquals(2, result.getChangesets().size());
+
+ Changeset c1 = result.getChangesets().get(0);
+
+ assertNotNull(c1);
+ assertEquals("fcd0ef1831e4002ac43e", c1.getId());
+
+ Changeset c2 = result.getChangesets().get(1);
+
+ assertNotNull(c2);
+ assertEquals("86a6645eceefe8b9a247", c2.getId());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetAllWithPaging() throws IOException, RepositoryException
+ {
+ LogCommandRequest request = new LogCommandRequest();
+
+ request.setPagingStart(1);
+ request.setPagingLimit(2);
+
+ ChangesetPagingResult result = createCommand().getChangesets(request);
+
+ assertNotNull(result);
+ assertEquals(4, result.getTotal());
+ assertEquals(2, result.getChangesets().size());
+
+ Changeset c1 = result.getChangesets().get(0);
+
+ assertNotNull(c1);
+ assertEquals("86a6645eceefe8b9a247", c1.getId());
+
+ Changeset c2 = result.getChangesets().get(1);
+
+ assertNotNull(c2);
+ assertEquals("592d797cd36432e59141", c2.getId());
+ }
+
+ /**
+ * Method description
+ *
+ */
+ @Test
+ public void testGetCommit()
+ {
+ GitLogCommand command = createCommand();
+ Changeset c = command.getChangeset("435df2f061add3589cb3");
+
+ assertNotNull(c);
+ assertEquals("435df2f061add3589cb3", c.getId());
+ assertEquals("added a and b files", c.getDescription());
+ checkDate(c.getDate());
+ assertEquals("Douglas Adams", c.getAuthor().getName());
+ assertEquals("douglas.adams@hitchhiker.com", c.getAuthor().getMail());
+ assertEquals("added a and b files", c.getDescription());
+
+ Modifications mods = c.getModifications();
+
+ assertNotNull(mods);
+ assertTrue("modified list should be empty", mods.getModified().isEmpty());
+ assertTrue("removed list should be empty", mods.getRemoved().isEmpty());
+ assertFalse("added list should not be empty", mods.getAdded().isEmpty());
+ assertEquals(2, mods.getAdded().size());
+ assertThat(mods.getAdded(), contains("a.txt", "b.txt"));
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetRange() throws IOException, RepositoryException
+ {
+ LogCommandRequest request = new LogCommandRequest();
+
+ request.setStartChangeset("592d797cd36432e59141");
+ request.setEndChangeset("435df2f061add3589cb3");
+
+ ChangesetPagingResult result = createCommand().getChangesets(request);
+
+ assertNotNull(result);
+ assertEquals(2, result.getTotal());
+ assertEquals(2, result.getChangesets().size());
+
+ Changeset c1 = result.getChangesets().get(0);
+ Changeset c2 = result.getChangesets().get(1);
+
+ assertNotNull(c1);
+ assertEquals("592d797cd36432e59141", c1.getId());
+ assertNotNull(c2);
+ assertEquals("435df2f061add3589cb3", c2.getId());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ private GitLogCommand createCommand()
+ {
+ return new GitLogCommand(createContext(), repository);
+ }
+}
diff --git a/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/spi/scm-git-spi-test.zip b/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/spi/scm-git-spi-test.zip
new file mode 100644
index 0000000000..3fbab0be38
Binary files /dev/null and b/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/spi/scm-git-spi-test.zip differ
diff --git a/scm-plugins/scm-hg-plugin/pom.xml b/scm-plugins/scm-hg-plugin/pom.xml
index c7375aae1d..b8e1bc2bef 100644
--- a/scm-plugins/scm-hg-plugin/pom.xml
+++ b/scm-plugins/scm-hg-plugin/pom.xml
@@ -6,12 +6,12 @@
sonia.scm.pluginsscm-plugins
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.pluginsscm-hg-plugin
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-hg-pluginhttps://bitbucket.org/sdorra/scm-managerPlugin for the version control system Mercurial
@@ -30,7 +30,7 @@
sonia.scmscm-test
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTtest
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/AbstractHgHandler.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/AbstractHgHandler.java
index c1f6f60a76..431d3c0966 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/AbstractHgHandler.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/AbstractHgHandler.java
@@ -35,6 +35,8 @@ package sonia.scm.repository;
//~--- non-JDK imports --------------------------------------------------------
+import com.google.common.io.Closeables;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -57,7 +59,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
/**
@@ -68,45 +69,47 @@ public class AbstractHgHandler
{
/** Field description */
- public static final String ENCODING = "UTF-8";
+ protected static final String ENV_NODE = "HG_NODE";
+
+ /** Field description */
+ protected static final String ENV_PAGE_LIMIT = "SCM_PAGE_LIMIT";
+
+ /** Field description */
+ protected static final String ENV_PAGE_START = "SCM_PAGE_START";
+
+ /** Field description */
+ protected static final String ENV_PATH = "SCM_PATH";
+
+ /** Field description */
+ protected static final String ENV_REPOSITORY_PATH = "SCM_REPOSITORY_PATH";
+
+ /** Field description */
+ protected static final String ENV_REVISION = "SCM_REVISION";
+
+ /** Field description */
+ protected static final String ENV_REVISION_END = "SCM_REVISION_END";
+
+ /** Field description */
+ protected static final String ENV_REVISION_START = "SCM_REVISION_START";
+
+ /** Field description */
+ private static final String ENCODING = "UTF-8";
/** mercurial encoding */
- public static final String ENV_HGENCODING = "HGENCODING";
+ private static final String ENV_HGENCODING = "HGENCODING";
/** Field description */
- public static final String ENV_NODE = "HG_NODE";
-
- /** Field description */
- public static final String ENV_PAGE_LIMIT = "SCM_PAGE_LIMIT";
-
- /** Field description */
- public static final String ENV_PAGE_START = "SCM_PAGE_START";
-
- /** Field description */
- public static final String ENV_PATH = "SCM_PATH";
-
- /** Field description */
- public static final String ENV_PENDING = "HG_PENDING";
+ private static final String ENV_PENDING = "HG_PENDING";
/** python encoding */
- public static final String ENV_PYTHONIOENCODING = "PYTHONIOENCODING";
+ private static final String ENV_PYTHONIOENCODING = "PYTHONIOENCODING";
/** Field description */
- public static final String ENV_PYTHONPATH = "PYTHONPATH";
+ private static final String ENV_PYTHONPATH = "PYTHONPATH";
- /** Field description */
- public static final String ENV_REPOSITORY_PATH = "SCM_REPOSITORY_PATH";
-
- /** Field description */
- public static final String ENV_REVISION = "SCM_REVISION";
-
- /** Field description */
- public static final String ENV_REVISION_END = "SCM_REVISION_END";
-
- /** Field description */
- public static final String ENV_REVISION_START = "SCM_REVISION_START";
-
- /** the logger for AbstractHgHandler */
+ /**
+ * the logger for AbstractHgCommand
+ */
private static final Logger logger =
LoggerFactory.getLogger(AbstractHgHandler.class);
@@ -116,63 +119,35 @@ public class AbstractHgHandler
* Constructs ...
*
*
+ *
* @param handler
* @param context
- * @param directory
+ * @param repository
+ * @param repositoryDirectory
*/
- public AbstractHgHandler(HgRepositoryHandler handler, HgContext context,
- File directory)
+ protected AbstractHgHandler(HgRepositoryHandler handler, HgContext context,
+ Repository repository)
{
- this(handler, null, context, directory);
+ this(handler, context, repository, handler.getDirectory(repository));
}
/**
* Constructs ...
*
*
+ *
* @param handler
* @param context
* @param repository
+ * @param repositoryDirectory
*/
- public AbstractHgHandler(HgRepositoryHandler handler, HgContext context,
- Repository repository)
- {
- this(handler, null, context, handler.getDirectory(repository));
- }
-
- /**
- * Constructs ...
- *
- *
- * @param handler
- * @param jaxbContext
- * @param context
- * @param directory
- */
- public AbstractHgHandler(HgRepositoryHandler handler,
- JAXBContext jaxbContext, HgContext context,
- File directory)
+ protected AbstractHgHandler(HgRepositoryHandler handler, HgContext context,
+ Repository repository, File repositoryDirectory)
{
this.handler = handler;
- this.jaxbContext = jaxbContext;
this.context = context;
- this.directory = directory;
- }
-
- /**
- * Constructs ...
- *
- *
- * @param handler
- * @param jaxbContext
- * @param context
- * @param repository
- */
- public AbstractHgHandler(HgRepositoryHandler handler,
- JAXBContext jaxbContext, HgContext context,
- Repository repository)
- {
- this(handler, jaxbContext, context, handler.getDirectory(repository));
+ this.repository = repository;
+ this.repositoryDirectory = repositoryDirectory;
}
//~--- methods --------------------------------------------------------------
@@ -332,7 +307,8 @@ public class AbstractHgHandler
{
handleErrorStream(p.getErrorStream());
input = p.getInputStream();
- result = (T) jaxbContext.createUnmarshaller().unmarshal(input);
+ result =
+ (T) handler.getJaxbContext().createUnmarshaller().unmarshal(input);
input.close();
}
catch (JAXBException ex)
@@ -343,8 +319,8 @@ public class AbstractHgHandler
}
finally
{
- IOUtil.close(input);
- IOUtil.close(output);
+ Closeables.closeQuietly(input);
+ Closeables.closeQuietly(output);
}
return result;
@@ -399,7 +375,7 @@ public class AbstractHgHandler
ProcessBuilder pb = new ProcessBuilder(cmdList);
- pb.directory(directory);
+ pb.directory(repositoryDirectory);
Map env = pb.environment();
@@ -416,10 +392,11 @@ public class AbstractHgHandler
{
if (logger.isDebugEnabled())
{
- logger.debug("enable hg pending for {}", directory.getAbsolutePath());
+ logger.debug("enable hg pending for {}",
+ repositoryDirectory.getAbsolutePath());
}
- env.put(ENV_PENDING, directory.getAbsolutePath());
+ env.put(ENV_PENDING, repositoryDirectory.getAbsolutePath());
if (extraEnv.containsKey(ENV_REVISION_START))
{
@@ -428,14 +405,15 @@ public class AbstractHgHandler
}
env.put(ENV_PYTHONPATH, HgUtil.getPythonPath(config));
- env.put(ENV_REPOSITORY_PATH, directory.getAbsolutePath());
+ env.put(ENV_REPOSITORY_PATH, repositoryDirectory.getAbsolutePath());
env.putAll(extraEnv);
if (logger.isTraceEnabled())
{
StringBuilder msg = new StringBuilder("start process in directory '");
- msg.append(directory.getAbsolutePath()).append("' with env: \n");
+ msg.append(repositoryDirectory.getAbsolutePath()).append(
+ "' with env: \n");
for (Map.Entry e : env.entrySet())
{
@@ -452,15 +430,15 @@ public class AbstractHgHandler
//~--- fields ---------------------------------------------------------------
+ /** Field description */
+ protected Repository repository;
+
+ /** Field description */
+ protected File repositoryDirectory;
+
/** Field description */
private HgContext context;
- /** Field description */
- private File directory;
-
/** Field description */
private HgRepositoryHandler handler;
-
- /** Field description */
- private JAXBContext jaxbContext;
}
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgBlameViewer.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgBlameViewer.java
index ea192665bc..40dfe0a58d 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgBlameViewer.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgBlameViewer.java
@@ -47,8 +47,6 @@ import java.io.IOException;
import java.util.Map;
-import javax.xml.bind.JAXBContext;
-
/**
*
* @author Sebastian Sdorra
@@ -71,11 +69,10 @@ public class HgBlameViewer extends AbstractHgHandler implements BlameViewer
* @param repository
* @param blameResultContext
*/
- public HgBlameViewer(HgRepositoryHandler handler,
- JAXBContext blameResultContext, HgContext context,
+ public HgBlameViewer(HgRepositoryHandler handler, HgContext context,
Repository repository)
{
- super(handler, blameResultContext, context, repository);
+ super(handler, context, repository);
}
//~--- get methods ----------------------------------------------------------
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgChangesetViewer.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgChangesetViewer.java
index 5a93eef75f..da62011a63 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgChangesetViewer.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgChangesetViewer.java
@@ -74,11 +74,10 @@ public class HgChangesetViewer extends AbstractHgHandler
* @param context
* @param repositoryDirectory
*/
- public HgChangesetViewer(HgRepositoryHandler handler,
- JAXBContext jaxbContext, HgContext context,
+ public HgChangesetViewer(HgRepositoryHandler handler, HgContext context,
File repositoryDirectory)
{
- super(handler, jaxbContext, context, repositoryDirectory);
+ super(handler, context, null, repositoryDirectory);
}
/**
@@ -95,7 +94,7 @@ public class HgChangesetViewer extends AbstractHgHandler
JAXBContext jaxbContext, HgContext context,
Repository repository)
{
- super(handler, jaxbContext, context, repository);
+ super(handler, context, repository);
}
//~--- get methods ----------------------------------------------------------
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java
index 818bcf5a20..795e01c22b 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java
@@ -36,6 +36,7 @@ package sonia.scm.repository;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Inject;
+import com.google.inject.Provider;
import com.google.inject.Singleton;
import org.slf4j.Logger;
@@ -43,6 +44,9 @@ import org.slf4j.LoggerFactory;
import sonia.scm.ConfigChangedListener;
import sonia.scm.config.ScmConfiguration;
+import sonia.scm.net.HttpClient;
+import sonia.scm.net.HttpRequest;
+import sonia.scm.net.HttpResponse;
import sonia.scm.util.HttpUtil;
import sonia.scm.util.Util;
@@ -81,12 +85,15 @@ public class HgHookManager implements ConfigChangedListener
*
*
* @param configuration
+ * @param httpClientProvider
*/
@Inject
- public HgHookManager(ScmConfiguration configuration)
+ public HgHookManager(ScmConfiguration configuration,
+ Provider httpClientProvider)
{
this.configuration = configuration;
this.configuration.addListener(this);
+ this.httpClientProvider = httpClientProvider;
}
//~--- methods --------------------------------------------------------------
@@ -292,10 +299,15 @@ public class HgHookManager implements ConfigChangedListener
logger.trace("check hook url {}", url);
}
- HttpURLConnection connection =
- (HttpURLConnection) new URL(url).openConnection();
+ HttpRequest request = new HttpRequest(url);
- result = connection.getResponseCode() == 204;
+ request.setDisableCertificateValidation(true);
+ request.setDisableHostnameValidation(true);
+ request.setIgnoreProxySettings(true);
+
+ HttpResponse response = httpClientProvider.get().get(request);
+
+ result = response.getStatusCode() == 204;
}
catch (IOException ex)
{
@@ -318,4 +330,7 @@ public class HgHookManager implements ConfigChangedListener
/** Field description */
private volatile String hookUrl;
+
+ /** Field description */
+ private Provider httpClientProvider;
}
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgImportHandler.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgImportHandler.java
index 2d85ea7bf2..30b5063c11 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgImportHandler.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgImportHandler.java
@@ -30,14 +30,19 @@
*/
+
package sonia.scm.repository;
//~--- non-JDK imports --------------------------------------------------------
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import sonia.scm.io.INIConfiguration;
import sonia.scm.io.INIConfigurationReader;
import sonia.scm.io.INIConfigurationWriter;
import sonia.scm.io.INISection;
+import sonia.scm.util.ValidationUtil;
//~--- JDK imports ------------------------------------------------------------
@@ -54,6 +59,12 @@ public class HgImportHandler extends AbstactImportHandler
/** Field description */
public static final String HG_DIR = ".hg";
+ /**
+ * the logger for HgImportHandler
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(HgImportHandler.class);
+
//~--- constructors ---------------------------------------------------------
/**
@@ -103,10 +114,21 @@ public class HgImportHandler extends AbstactImportHandler
else
{
repository.setDescription(web.getParameter("description"));
- repository.setContact(web.getParameter("contact"));
+
+ String contact = web.getParameter("contact");
+
+ if (ValidationUtil.isMailAddressValid(contact))
+ {
+ repository.setContact(contact);
+ }
+ else if (logger.isWarnEnabled())
+ {
+ logger.warn("contact {} is not a valid mail address", contact);
+ }
+
handler.setWebParameter(web);
}
-
+
// issue-97
handler.registerMissingHook(c, repositoryName);
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgPythonScript.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgPythonScript.java
index 927236d6ea..c0a467f5b1 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgPythonScript.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgPythonScript.java
@@ -30,6 +30,7 @@
*/
+
package sonia.scm.repository;
//~--- non-JDK imports --------------------------------------------------------
@@ -47,7 +48,8 @@ import java.io.File;
public enum HgPythonScript
{
BLAME("blame.py"), CHANGELOG("changelog.py"), FILELOG("filelog.py"),
- UTIL("util.py"), HOOK("scmhooks.py"), HGWEB("hgweb.py"), VERSION("version.py");
+ LOG("log.py"), UTIL("util.py"), HOOK("scmhooks.py"), HGWEB("hgweb.py"),
+ VERSION("version.py");
/** Field description */
private static final String BASE_DIRECTORY =
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryBrowser.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryBrowser.java
index 947e2d26b8..4a7c292087 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryBrowser.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryBrowser.java
@@ -47,8 +47,6 @@ import java.io.OutputStream;
import java.util.Map;
-import javax.xml.bind.JAXBContext;
-
/**
*
* @author Sebastian Sdorra
@@ -66,11 +64,10 @@ public class HgRepositoryBrowser extends AbstractHgHandler
* @param repository
* @param browserResultContext
*/
- public HgRepositoryBrowser(HgRepositoryHandler handler,
- JAXBContext browserResultContext,
- HgContext context, Repository repository)
+ public HgRepositoryBrowser(HgRepositoryHandler handler, HgContext context,
+ Repository repository)
{
- super(handler, browserResultContext, context, repository);
+ super(handler, context, repository);
}
//~--- get methods ----------------------------------------------------------
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryHandler.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryHandler.java
index 045f540af6..f883b571af 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryHandler.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryHandler.java
@@ -127,7 +127,8 @@ public class HgRepositoryHandler
try
{
this.jaxbContext = JAXBContext.newInstance(BrowserResult.class,
- BlameResult.class, Changeset.class, ChangesetPagingResult.class);
+ BlameResult.class, Changeset.class, ChangesetPagingResult.class,
+ HgVersion.class);
}
catch (JAXBException ex)
{
@@ -222,8 +223,8 @@ public class HgRepositoryHandler
if (TYPE_NAME.equals(type))
{
- blameViewer = new HgBlameViewer(this, jaxbContext,
- hgContextProvider.get(), repository);
+ blameViewer = new HgBlameViewer(this, hgContextProvider.get(),
+ repository);
}
else
{
@@ -311,6 +312,17 @@ public class HgRepositoryHandler
return new HgImportHandler(this);
}
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public JAXBContext getJaxbContext()
+ {
+ return jaxbContext;
+ }
+
/**
* Method description
*
@@ -322,8 +334,7 @@ public class HgRepositoryHandler
@Override
public RepositoryBrowser getRepositoryBrowser(Repository repository)
{
- return new HgRepositoryBrowser(this, jaxbContext, hgContextProvider.get(),
- repository);
+ return new HgRepositoryBrowser(this, hgContextProvider.get(), repository);
}
/**
@@ -352,16 +363,23 @@ public class HgRepositoryHandler
try
{
- JAXBContext context = JAXBContext.newInstance(HgVersion.class);
- HgVersion hgVersion = new HgVersionHandler(this, context,
- hgContextProvider.get(),
+ HgVersion hgVersion = new HgVersionHandler(this, hgContextProvider.get(),
baseDirectory).getVersion();
if (hgVersion != null)
{
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("mercurial/python informations: {}", hgVersion);
+ }
+
version = MessageFormat.format(version, hgVersion.getPython(),
hgVersion.getMercurial());
}
+ else if (logger.isWarnEnabled())
+ {
+ logger.warn("could not retrieve version informations");
+ }
}
catch (Exception ex)
{
@@ -470,8 +488,7 @@ public class HgRepositoryHandler
throw new IllegalStateException("directory not found");
}
- return new HgChangesetViewer(this, jaxbContext, context,
- repositoryDirectory);
+ return new HgChangesetViewer(this, context, repositoryDirectory);
}
//~--- set methods ----------------------------------------------------------
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgVersion.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgVersion.java
index 616d2dbab5..afe6a17ca1 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgVersion.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgVersion.java
@@ -1,36 +1,41 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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.common.base.Objects;
+
//~--- JDK imports ------------------------------------------------------------
import javax.xml.bind.annotation.XmlAccessType;
@@ -46,6 +51,64 @@ import javax.xml.bind.annotation.XmlRootElement;
public class HgVersion
{
+ /**
+ * Method description
+ *
+ *
+ * @param obj
+ *
+ * @return
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+
+ final HgVersion other = (HgVersion) obj;
+
+ return Objects.equal(mercurial, other.mercurial)
+ && Objects.equal(python, other.python);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public int hashCode()
+ {
+ return Objects.hashCode(mercurial, python);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public String toString()
+ {
+ //J-
+ return Objects.toStringHelper(this)
+ .add("mercurial", mercurial)
+ .add("python", python)
+ .toString();
+ //J+
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
/**
* Method description
*
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgVersionHandler.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgVersionHandler.java
index 722b09fab4..e52eee2c8a 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgVersionHandler.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgVersionHandler.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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;
//~--- JDK imports ------------------------------------------------------------
@@ -36,8 +37,6 @@ package sonia.scm.repository;
import java.io.File;
import java.io.IOException;
-import javax.xml.bind.JAXBContext;
-
/**
*
* @author Sebastian Sdorra
@@ -54,10 +53,10 @@ public class HgVersionHandler extends AbstractHgHandler
* @param context
* @param directory
*/
- public HgVersionHandler(HgRepositoryHandler handler, JAXBContext jaxbContext,
- HgContext context, File directory)
+ public HgVersionHandler(HgRepositoryHandler handler, HgContext context,
+ File directory)
{
- super(handler, jaxbContext, context, directory);
+ super(handler, context, null, directory);
}
//~--- get methods ----------------------------------------------------------
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/AbstractHgCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/AbstractHgCommand.java
new file mode 100644
index 0000000000..26613150c1
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/AbstractHgCommand.java
@@ -0,0 +1,88 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.AbstractHgHandler;
+import sonia.scm.repository.HgContext;
+import sonia.scm.repository.HgRepositoryHandler;
+import sonia.scm.repository.Repository;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+
+import java.util.Map;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class AbstractHgCommand extends AbstractHgHandler
+{
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param handler
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ protected AbstractHgCommand(HgRepositoryHandler handler, HgContext context,
+ Repository repository, File repositoryDirectory)
+ {
+ super(handler, context, repository, repositoryDirectory);
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param revision
+ * @param path
+ *
+ * @param request
+ *
+ * @return
+ */
+ protected Map createEnvironment(FileBaseCommandRequest request)
+ {
+ return createEnvironment(request.getRevision(), request.getPath());
+ }
+}
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgBlameCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgBlameCommand.java
new file mode 100644
index 0000000000..4c9d3f7f06
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgBlameCommand.java
@@ -0,0 +1,110 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.repository.BlameResult;
+import sonia.scm.repository.HgContext;
+import sonia.scm.repository.HgPythonScript;
+import sonia.scm.repository.HgRepositoryHandler;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryException;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.IOException;
+
+import java.util.Map;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class HgBlameCommand extends AbstractHgCommand implements BlameCommand
+{
+
+ /**
+ * the logger for HgBlameCommand
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(HgBlameCommand.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param handler
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ public HgBlameCommand(HgRepositoryHandler handler, HgContext context,
+ Repository repository, File repositoryDirectory)
+ {
+ super(handler, context, repository, repositoryDirectory);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public BlameResult getBlameResult(BlameCommandRequest request)
+ throws IOException, RepositoryException
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("get blame result for {}", request);
+ }
+
+ Map env = createEnvironment(request);
+
+ return getResultFromScript(BlameResult.class, HgPythonScript.BLAME, env);
+ }
+}
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgBrowseCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgBrowseCommand.java
new file mode 100644
index 0000000000..56ce86734c
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgBrowseCommand.java
@@ -0,0 +1,98 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.repository.BrowserResult;
+import sonia.scm.repository.HgContext;
+import sonia.scm.repository.HgPythonScript;
+import sonia.scm.repository.HgRepositoryHandler;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryException;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.IOException;
+
+import java.util.Map;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class HgBrowseCommand extends AbstractHgCommand implements BrowseCommand
+{
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param handler
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ public HgBrowseCommand(HgRepositoryHandler handler, HgContext context,
+ Repository repository, File repositoryDirectory)
+ {
+ super(handler, context, repository, repositoryDirectory);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param revision
+ * @param path
+ *
+ * @param request
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public BrowserResult getBrowserResult(BrowseCommandRequest request)
+ throws IOException, RepositoryException
+ {
+ Map env = createEnvironment(request);
+
+ return getResultFromScript(BrowserResult.class, HgPythonScript.FILELOG,
+ env);
+ }
+}
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgCatCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgCatCommand.java
new file mode 100644
index 0000000000..69c012e52a
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgCatCommand.java
@@ -0,0 +1,108 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.io.ByteStreams;
+import com.google.common.io.Closeables;
+
+import sonia.scm.repository.HgContext;
+import sonia.scm.repository.HgRepositoryHandler;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.util.Util;
+import sonia.scm.web.HgUtil;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class HgCatCommand extends AbstractHgCommand implements CatCommand
+{
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param handler
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ HgCatCommand(HgRepositoryHandler handler, HgContext context,
+ Repository repository, File repositoryDirectory)
+ {
+ super(handler, context, repository, repositoryDirectory);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ * @param output
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public void getCatResult(CatCommandRequest request, OutputStream output)
+ throws IOException, RepositoryException
+ {
+ String revision = HgUtil.getRevision(request.getRevision());
+ Process p = createHgProcess("cat", "-r", revision,
+ Util.nonNull(request.getPath()));
+ InputStream input = null;
+
+ try
+ {
+ handleErrorStream(p.getErrorStream());
+ input = p.getInputStream();
+ ByteStreams.copy(input, output);
+ }
+ finally
+ {
+ Closeables.closeQuietly(input);
+ }
+ }
+}
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgDiffCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgDiffCommand.java
new file mode 100644
index 0000000000..8ec6d58367
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgDiffCommand.java
@@ -0,0 +1,106 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.io.ByteStreams;
+import com.google.common.io.Closeables;
+
+import sonia.scm.repository.HgContext;
+import sonia.scm.repository.HgRepositoryHandler;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.util.Util;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class HgDiffCommand extends AbstractHgCommand implements DiffCommand
+{
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param handler
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ public HgDiffCommand(HgRepositoryHandler handler, HgContext context,
+ Repository repository, File repositoryDirectory)
+ {
+ super(handler, context, repository, repositoryDirectory);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ * @param output
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public void getDiffResult(DiffCommandRequest request, OutputStream output)
+ throws IOException, RepositoryException
+ {
+ Process p = createHgProcess("diff", "-c", request.getRevision(),
+ Util.nonNull(request.getPath()));
+ InputStream input = null;
+
+ try
+ {
+ handleErrorStream(p.getErrorStream());
+ input = p.getInputStream();
+ ByteStreams.copy(input, output);
+ }
+ finally
+ {
+ Closeables.closeQuietly(input);
+ }
+ }
+}
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgLogCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgLogCommand.java
new file mode 100644
index 0000000000..d90211d437
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgLogCommand.java
@@ -0,0 +1,136 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Maps;
+
+import sonia.scm.repository.Changeset;
+import sonia.scm.repository.ChangesetPagingResult;
+import sonia.scm.repository.HgContext;
+import sonia.scm.repository.HgPythonScript;
+import sonia.scm.repository.HgRepositoryHandler;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.util.Util;
+import sonia.scm.web.HgUtil;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.IOException;
+
+import java.util.Map;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class HgLogCommand extends AbstractHgCommand implements LogCommand
+{
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param handler
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ public HgLogCommand(HgRepositoryHandler handler, HgContext context,
+ Repository repository, File repositoryDirectory)
+ {
+ super(handler, context, repository, repositoryDirectory);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param id
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public Changeset getChangeset(String id)
+ throws IOException, RepositoryException
+ {
+ Map env = Maps.newHashMap();
+
+ env.put(ENV_REVISION, HgUtil.getRevision(id));
+ env.put(ENV_PATH, Util.EMPTY_STRING);
+ env.put(ENV_PAGE_START, "0");
+ env.put(ENV_PAGE_LIMIT, "1");
+ env.put(ENV_REVISION_START, Util.EMPTY_STRING);
+ env.put(ENV_REVISION_END, Util.EMPTY_STRING);
+
+ return getResultFromScript(Changeset.class, HgPythonScript.LOG, env);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public ChangesetPagingResult getChangesets(LogCommandRequest request)
+ throws IOException, RepositoryException
+ {
+ Map env = Maps.newHashMap();
+
+ env.put(ENV_REVISION, Util.EMPTY_STRING);
+ env.put(ENV_PATH, Strings.nullToEmpty(request.getPath()));
+ env.put(ENV_PAGE_START, String.valueOf(request.getPagingStart()));
+ env.put(ENV_PAGE_LIMIT, String.valueOf(request.getPagingLimit()));
+ env.put(ENV_REVISION_START,
+ Strings.nullToEmpty(request.getStartChangeset()));
+ env.put(ENV_REVISION_END, Strings.nullToEmpty(request.getEndChangeset()));
+
+ return getResultFromScript(ChangesetPagingResult.class, HgPythonScript.LOG,
+ env);
+ }
+}
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java
new file mode 100644
index 0000000000..ffcc0fe776
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java
@@ -0,0 +1,176 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Provider;
+
+import sonia.scm.repository.HgContext;
+import sonia.scm.repository.HgRepositoryHandler;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.api.Command;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+
+import java.util.Set;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class HgRepositoryServiceProvider extends RepositoryServiceProvider
+{
+
+ /** Field description */
+ private static final Set COMMANDS = ImmutableSet.of(Command.BLAME,
+ Command.BROWSE, Command.CAT,
+ Command.DIFF, Command.LOG);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param hgContextProvider
+ * @param handler
+ * @param repository
+ */
+ HgRepositoryServiceProvider(HgRepositoryHandler handler,
+ Provider hgContextProvider,
+ Repository repository)
+ {
+ this.hgContextProvider = hgContextProvider;
+ this.handler = handler;
+ this.repository = repository;
+ this.repositoryDirectory = handler.getDirectory(repository);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public HgBlameCommand getBlameCommand()
+ {
+ return new HgBlameCommand(handler, hgContextProvider.get(), repository,
+ repositoryDirectory);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public HgBrowseCommand getBrowseCommand()
+ {
+ return new HgBrowseCommand(handler, hgContextProvider.get(), repository,
+ repositoryDirectory);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public HgCatCommand getCatCommand()
+ {
+ return new HgCatCommand(handler, hgContextProvider.get(), repository,
+ repositoryDirectory);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public HgDiffCommand getDiffCommand()
+ {
+ return new HgDiffCommand(handler, hgContextProvider.get(), repository,
+ repositoryDirectory);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public HgLogCommand getLogCommand()
+ {
+ return new HgLogCommand(handler, hgContextProvider.get(), repository,
+ repositoryDirectory);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public Set getSupportedCommands()
+ {
+ return COMMANDS;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private HgRepositoryHandler handler;
+
+ /** Field description */
+ private Provider hgContextProvider;
+
+ /** Field description */
+ private Repository repository;
+
+ /** Field description */
+ private File repositoryDirectory;
+}
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java
new file mode 100644
index 0000000000..abdfd441e1
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java
@@ -0,0 +1,104 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import sonia.scm.plugin.ext.Extension;
+import sonia.scm.repository.HgContext;
+import sonia.scm.repository.HgRepositoryHandler;
+import sonia.scm.repository.Repository;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+@Extension
+public class HgRepositoryServiceResolver implements RepositoryServiceResolver
+{
+
+ /** Field description */
+ private static final String TYPE = "hg";
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param handler
+ * @param hgContextProvider
+ */
+ @Inject
+ public HgRepositoryServiceResolver(HgRepositoryHandler handler,
+ Provider hgContextProvider)
+ {
+ this.handler = handler;
+ this.hgContextProvider = hgContextProvider;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ *
+ * @return
+ */
+ @Override
+ public HgRepositoryServiceProvider reslove(Repository repository)
+ {
+ HgRepositoryServiceProvider provider = null;
+
+ if (TYPE.equalsIgnoreCase(repository.getType()))
+ {
+ provider = new HgRepositoryServiceProvider(handler, hgContextProvider,
+ repository);
+ }
+
+ return provider;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private HgRepositoryHandler handler;
+
+ /** Field description */
+ private Provider hgContextProvider;
+}
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIExceptionHandler.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIExceptionHandler.java
index 5c67d147e9..c1e068b665 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIExceptionHandler.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIExceptionHandler.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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;
//~--- non-JDK imports --------------------------------------------------------
diff --git a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/python/filelog.py b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/python/filelog.py
index 6fe5fa1f29..af63e1ca98 100644
--- a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/python/filelog.py
+++ b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/python/filelog.py
@@ -44,6 +44,11 @@ def getName(path):
length =- 1
return parts[length - 1]
+def removeTrailingSlash(path):
+ if path.endswith('/'):
+ path = path[0:-1]
+ return path
+
def appendSubRepositoryNode(doc, parentNode, path, subRepositories):
if path in subRepositories:
subRepository = subRepositories[path]
@@ -55,7 +60,7 @@ def appendSubRepositoryNode(doc, parentNode, path, subRepositories):
def createBasicFileNode(doc, parentNode, path, directory):
fileNode = createChildNode(doc, parentNode, 'file')
appendTextNode(doc, fileNode, 'name', getName(path))
- appendTextNode(doc, fileNode, 'path', path)
+ appendTextNode(doc, fileNode, 'path', removeTrailingSlash(path))
appendTextNode(doc, fileNode, 'directory', directory)
return fileNode
diff --git a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/python/log.py b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/python/log.py
new file mode 100644
index 0000000000..4db781321b
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/python/log.py
@@ -0,0 +1,147 @@
+#
+# 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
+#
+#
+
+
+import os
+from util import *
+from xml.dom.minidom import Document
+
+# changeset methods
+
+def appendIdNode(doc, parentNode, ctx):
+ id = getId(ctx)
+ appendTextNode(doc, parentNode, 'id', id)
+
+def appendParentNodes(doc, parentNode, ctx):
+ parents = ctx.parents()
+ if parents:
+ for parent in parents:
+ parentId = getId(parent)
+ appendTextNode(doc, parentNode, 'parents', parentId)
+
+def appendBranchesNode(doc, parentNode, ctx):
+ branch = ctx.branch()
+ if branch != 'default':
+ appendTextNode(doc, parentNode, 'branches', branch)
+
+def appendModifications(doc, parentNode, ctx):
+ status = repo.status(ctx.p1().node(), ctx.node())
+ if status:
+ modificationsNode = createChildNode(doc, parentNode, 'modifications')
+ appendWrappedListNodes(doc, modificationsNode, 'added', 'file', status[1])
+ appendWrappedListNodes(doc, modificationsNode, 'modified', 'file', status[0])
+ appendWrappedListNodes(doc, modificationsNode, 'removed', 'file', status[2])
+
+def appendChangesetNode(doc, parentNode, ctx):
+ changesetNode = createChildNode(doc, parentNode, 'changeset')
+ appendIdNode(doc, changesetNode, ctx)
+ appendParentNodes(doc, changesetNode, ctx)
+ appendTextNode(doc, changesetNode, 'description', ctx.description())
+ appendDateNode(doc, changesetNode, 'date', ctx.date())
+ appendAuthorNodes(doc, changesetNode, ctx)
+ appendBranchesNode(doc, changesetNode, ctx)
+ appendListNodes(doc, changesetNode, 'tags', ctx.tags())
+ appendModifications(doc, changesetNode, ctx)
+
+# changeset methods end
+
+# change log methods
+
+def createBasicNodes(doc, ctxs):
+ rootNode = doc.createElement('changeset-paging')
+ doc.appendChild(rootNode)
+ total = str(len(ctxs))
+ appendTextNode(doc, rootNode, 'total', total)
+ return createChildNode(doc, rootNode, 'changesets')
+
+def collectChangesets(repo, path, startNode, endNode):
+ start = 'tip'
+ end = '0'
+ if len(startNode) > 0:
+ start = startNode
+ if len(endNode) > 0:
+ end = endNode
+
+ ctxs = []
+ startRev = repo[start].rev()
+ endRev = repo[end].rev() - 1
+
+ onlyWithPath = len(path) > 0
+
+ for i in range(startRev, endRev, -1):
+ ctx = repo[i]
+ if onlyWithPath:
+ if path in ctx.files():
+ ctxs.append(ctx)
+ else:
+ ctxs.append(ctx)
+
+ return ctxs
+
+def stripChangesets(ctxs, start, limit):
+ if limit < 0:
+ ctxs = ctxs[start:]
+ else:
+ limit = limit + start
+ if limit > len(ctxs):
+ ctxs = ctxs[start:]
+ else:
+ ctxs = ctxs[start:limit]
+ return ctxs
+
+# change log methods
+
+# main method
+repo = openRepository()
+doc = Document()
+
+# parameter
+path = os.environ['SCM_PATH']
+startNode = os.environ['SCM_REVISION_START']
+endNode = os.environ['SCM_REVISION_END']
+rev = os.environ['SCM_REVISION']
+# paging parameter
+start = int(os.environ['SCM_PAGE_START'])
+limit = int(os.environ['SCM_PAGE_LIMIT'])
+
+if len(rev) > 0:
+ ctx = repo[rev]
+ appendChangesetNode(doc, doc, ctx)
+else:
+ ctxs = collectChangesets(repo, path, startNode, endNode)
+ changesetsNode = createBasicNodes(doc, ctxs)
+ ctxs = stripChangesets(ctxs, start, limit)
+ for ctx in ctxs:
+ appendChangesetNode(doc, changesetsNode, ctx)
+
+
+# write document
+writeXml(doc)
diff --git a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/python/version.py b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/python/version.py
index c6cccc7c6d..b92504d338 100644
--- a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/python/version.py
+++ b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/python/version.py
@@ -1,3 +1,34 @@
+#
+# 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
+#
+#
+
import sys
from mercurial import util
from xml.dom.minidom import Document
diff --git a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/web/cgimessages.properties b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/web/cgimessages.properties
index 6fac1956dd..a42f82271d 100644
--- a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/web/cgimessages.properties
+++ b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/web/cgimessages.properties
@@ -1,9 +1,10 @@
+#
# 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,
@@ -12,7 +13,7 @@
# 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
@@ -23,9 +24,10 @@
# 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
-#
+#
+#
error.notConfigured = The mercurial installation on the scm-manager server seems to be not configured correctly. Please check the settings.
error.statusCode = Mercurial/Python process ends with return code {0}
diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgContextProvider.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgContextProvider.java
new file mode 100644
index 0000000000..4b0979da8d
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgContextProvider.java
@@ -0,0 +1,57 @@
+/**
+ * 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.Provider;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class HgContextProvider implements Provider
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public HgContext get()
+ {
+ return new HgContext();
+ }
+}
diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java
index 21d82f0827..ab052525fe 100644
--- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java
+++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgRepositoryHandlerTest.java
@@ -104,28 +104,4 @@ public class HgRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase
return handler;
}
-
- //~--- inner classes --------------------------------------------------------
-
- /**
- * Dummy {@link Provider} for {@link HgContext}
- *
- *
- * @author Sebastian Sdorra
- */
- private static class HgContextProvider implements Provider
- {
-
- /**
- * Return context for mercurial
- *
- *
- * @return context for mercurial
- */
- @Override
- public HgContext get()
- {
- return new HgContext();
- }
- }
}
diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/TempSCMContextProvider.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/TempSCMContextProvider.java
new file mode 100644
index 0000000000..0e14d8e8ee
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/TempSCMContextProvider.java
@@ -0,0 +1,143 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of SCM-Manager; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+package sonia.scm.repository;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import sonia.scm.SCMContextProvider;
+import sonia.scm.Stage;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class TempSCMContextProvider implements SCMContextProvider
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ */
+ @Override
+ public void close() throws IOException
+ {
+
+ // do nothing
+ }
+
+ /**
+ * Method description
+ *
+ */
+ @Override
+ public void init()
+ {
+
+ // do nothing
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public File getBaseDirectory()
+ {
+ return baseDirectory;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public Stage getStage()
+ {
+ return Stage.DEVELOPMENT;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public Throwable getStartupError()
+ {
+ return null;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public String getVersion()
+ {
+ return "UNIT-Test";
+ }
+
+ //~--- set methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param baseDirectory
+ */
+ public void setBaseDirectory(File baseDirectory)
+ {
+ this.baseDirectory = baseDirectory;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private File baseDirectory;
+}
diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/AbstractHgCommandTestBase.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/AbstractHgCommandTestBase.java
new file mode 100644
index 0000000000..fda5e14462
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/AbstractHgCommandTestBase.java
@@ -0,0 +1,120 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.junit.Assume;
+import org.junit.Before;
+
+import sonia.scm.SCMContext;
+import sonia.scm.io.FileSystem;
+import sonia.scm.repository.HgContextProvider;
+import sonia.scm.repository.HgRepositoryHandler;
+import sonia.scm.repository.TempSCMContextProvider;
+import sonia.scm.store.MemoryStoreFactory;
+
+import static org.mockito.Mockito.*;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class AbstractHgCommandTestBase extends ZippedRepositoryTestBase
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ */
+ @Before
+ public void initHgHandler() throws IOException
+ {
+ File folder = tempFolder.newFolder();
+ TempSCMContextProvider context =
+ (TempSCMContextProvider) SCMContext.getContext();
+
+ context.setBaseDirectory(folder);
+
+ FileSystem fileSystem = mock(FileSystem.class);
+
+ this.handler = new HgRepositoryHandler(new MemoryStoreFactory(),
+ fileSystem, new HgContextProvider());
+ this.handler.init(context);
+
+ // skip tests if hg not in path
+ if (!handler.isConfigured())
+ {
+ System.out.println("WARNING could not find hg, skipping test");
+ Assume.assumeTrue(false);
+ }
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ protected String getType()
+ {
+ return "hg";
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ protected String getZippedRepositoryResource()
+ {
+ return "sonia/scm/repository/spi/scm-hg-spi-test.zip";
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ protected HgRepositoryHandler handler;
+}
diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgBlameCommandTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgBlameCommandTest.java
new file mode 100644
index 0000000000..d55f6d6fce
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgBlameCommandTest.java
@@ -0,0 +1,136 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.junit.Test;
+
+import sonia.scm.repository.BlameLine;
+import sonia.scm.repository.BlameResult;
+import sonia.scm.repository.HgContext;
+import sonia.scm.repository.RepositoryException;
+
+import static org.junit.Assert.*;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class HgBlameCommandTest extends AbstractHgCommandTestBase
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetBlameResult() throws IOException, RepositoryException
+ {
+ BlameCommandRequest request = new BlameCommandRequest();
+
+ request.setPath("a.txt");
+
+ BlameResult result = new HgBlameCommand(handler, new HgContext(),
+ repository,
+ repositoryDirectory).getBlameResult(request);
+
+ assertNotNull(result);
+ assertEquals(2, result.getTotal());
+
+ BlameLine line = result.getLine(0);
+
+ checkFirstLine(line);
+ line = result.getLine(1);
+ assertEquals(2, line.getLineNumber());
+ assertEquals("4:2baab8e80280", line.getRevision());
+ checkDate(line.getWhen());
+ assertEquals("line for blame", line.getCode());
+ assertEquals("added new line for blame", line.getDescription());
+ assertEquals("Zaphod Beeblebrox", line.getAuthor().getName());
+ assertEquals("zaphod.beeblebrox@hitchhiker.com",
+ line.getAuthor().getMail());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetBlameResultWithRevision()
+ throws IOException, RepositoryException
+ {
+ BlameCommandRequest request = new BlameCommandRequest();
+
+ request.setPath("a.txt");
+ request.setRevision("a9bacaf1b7fa");
+
+ BlameResult result = new HgBlameCommand(handler, new HgContext(),
+ repository,
+ repositoryDirectory).getBlameResult(request);
+
+ assertNotNull(result);
+ assertEquals(1, result.getTotal());
+
+ BlameLine line = result.getLine(0);
+
+ checkFirstLine(line);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param line
+ */
+ private void checkFirstLine(BlameLine line)
+ {
+ assertEquals(1, line.getLineNumber());
+ assertEquals("0:a9bacaf1b7fa", line.getRevision());
+ checkDate(line.getWhen());
+ assertEquals("a", line.getCode());
+ assertEquals("added a and b files", line.getDescription());
+ assertEquals("Douglas Adams", line.getAuthor().getName());
+ assertEquals("douglas.adams@hitchhiker.com", line.getAuthor().getMail());
+ }
+}
diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgBrowseCommandTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgBrowseCommandTest.java
new file mode 100644
index 0000000000..e637e0c12a
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgBrowseCommandTest.java
@@ -0,0 +1,166 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.junit.Test;
+
+import sonia.scm.repository.BrowserResult;
+import sonia.scm.repository.FileObject;
+import sonia.scm.repository.HgContext;
+import sonia.scm.repository.RepositoryException;
+
+import static org.junit.Assert.*;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+import java.util.List;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class HgBrowseCommandTest extends AbstractHgCommandTestBase
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testBrowse() throws IOException, RepositoryException
+ {
+ BrowserResult result = new HgBrowseCommand(
+ handler, new HgContext(), repository,
+ repositoryDirectory).getBrowserResult(
+ new BrowseCommandRequest());
+
+ assertNotNull(result);
+
+ List foList = result.getFiles();
+
+ assertNotNull(foList);
+ assertFalse(foList.isEmpty());
+ assertEquals(4, foList.size());
+
+ FileObject a = null;
+ FileObject c = null;
+
+ for (FileObject f : foList)
+ {
+ if ("a.txt".equals(f.getName()))
+ {
+ a = f;
+ }
+ else if ("c".equals(f.getName()))
+ {
+ c = f;
+ }
+ }
+
+ assertNotNull(a);
+ assertFalse(a.isDirectory());
+ assertEquals("a.txt", a.getName());
+ assertEquals("a.txt", a.getPath());
+ assertEquals("added new line for blame", a.getDescription());
+ assertTrue(a.getLength() > 0);
+ checkDate(a.getLastModified());
+ assertNotNull(c);
+ assertTrue(c.isDirectory());
+ assertEquals("c", c.getName());
+ assertEquals("c", c.getPath());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testBrowseSubDirectory() throws IOException, RepositoryException
+ {
+ BrowseCommandRequest request = new BrowseCommandRequest();
+
+ request.setPath("c");
+
+ BrowserResult result = new HgBrowseCommand(handler, new HgContext(),
+ repository,
+ repositoryDirectory).getBrowserResult(request);
+
+ assertNotNull(result);
+
+ List foList = result.getFiles();
+
+ assertNotNull(foList);
+ assertFalse(foList.isEmpty());
+ assertEquals(2, foList.size());
+
+ FileObject d = null;
+ FileObject e = null;
+
+ for (FileObject f : foList)
+ {
+ if ("d.txt".equals(f.getName()))
+ {
+ d = f;
+ }
+ else if ("e.txt".equals(f.getName()))
+ {
+ e = f;
+ }
+ }
+
+ assertNotNull(d);
+ assertFalse(d.isDirectory());
+ assertEquals("d.txt", d.getName());
+ assertEquals("c/d.txt", d.getPath());
+ assertEquals("added file d and e in folder c", d.getDescription());
+ assertTrue(d.getLength() > 0);
+ checkDate(d.getLastModified());
+ assertNotNull(e);
+ assertFalse(e.isDirectory());
+ assertEquals("e.txt", e.getName());
+ assertEquals("c/e.txt", e.getPath());
+ assertEquals("added file d and e in folder c", e.getDescription());
+ assertTrue(e.getLength() > 0);
+ checkDate(e.getLastModified());
+ }
+}
diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgCatCommandTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgCatCommandTest.java
new file mode 100644
index 0000000000..45bfee8414
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgCatCommandTest.java
@@ -0,0 +1,118 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.junit.Test;
+
+import sonia.scm.repository.HgContext;
+import sonia.scm.repository.RepositoryException;
+
+import static org.junit.Assert.*;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class HgCatCommandTest extends AbstractHgCommandTestBase
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testCat() throws IOException, RepositoryException
+ {
+ CatCommandRequest request = new CatCommandRequest();
+
+ request.setPath("a.txt");
+ request.setRevision("a9bacaf1b7fa");
+ assertEquals("a", execute(request));
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testSimpleCat() throws IOException, RepositoryException
+ {
+ CatCommandRequest request = new CatCommandRequest();
+
+ request.setPath("b.txt");
+ assertEquals("b", execute(request));
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ private String execute(CatCommandRequest request)
+ throws IOException, RepositoryException
+ {
+ String content = null;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ try
+ {
+ new HgCatCommand(handler, new HgContext(), repository,
+ repositoryDirectory).getCatResult(request, baos);
+ }
+ finally
+ {
+ content = baos.toString().trim();
+ }
+
+ return content;
+ }
+}
diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgLogCommandTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgLogCommandTest.java
new file mode 100644
index 0000000000..aec477a6d7
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgLogCommandTest.java
@@ -0,0 +1,236 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.junit.Test;
+
+import sonia.scm.repository.Changeset;
+import sonia.scm.repository.ChangesetPagingResult;
+import sonia.scm.repository.HgContext;
+import sonia.scm.repository.Modifications;
+import sonia.scm.repository.RepositoryException;
+
+import static org.hamcrest.Matchers.*;
+
+import static org.junit.Assert.*;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class HgLogCommandTest extends AbstractHgCommandTestBase
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetAll() throws IOException, RepositoryException
+ {
+ ChangesetPagingResult result = new HgLogCommand(
+ handler, new HgContext(), repository,
+ repositoryDirectory).getChangesets(
+ new LogCommandRequest());
+
+ assertNotNull(result);
+ assertEquals(5, result.getTotal());
+ assertEquals(5, result.getChangesets().size());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetAllByPath() throws IOException, RepositoryException
+ {
+ LogCommandRequest request = new LogCommandRequest();
+
+ request.setPath("a.txt");
+
+ ChangesetPagingResult result =
+ new HgLogCommand(handler, new HgContext(), repository,
+ repositoryDirectory).getChangesets(request);
+
+ assertNotNull(result);
+ assertEquals(3, result.getTotal());
+ assertEquals(3, result.getChangesets().size());
+ assertEquals("4:2baab8e80280", result.getChangesets().get(0).getId());
+ assertEquals("2:79b6baf49711", result.getChangesets().get(1).getId());
+ assertEquals("0:a9bacaf1b7fa", result.getChangesets().get(2).getId());
+ }
+
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ */
+ @Test
+ public void testGetAllWithPaging() throws IOException, RepositoryException
+ {
+ LogCommandRequest request = new LogCommandRequest();
+
+ request.setPagingStart(1);
+ request.setPagingLimit(2);
+
+ ChangesetPagingResult result =
+ new HgLogCommand(handler, new HgContext(), repository,
+ repositoryDirectory).getChangesets(request);
+
+ assertNotNull(result);
+ assertEquals(5, result.getTotal());
+ assertEquals(2, result.getChangesets().size());
+
+ Changeset c1 = result.getChangesets().get(0);
+
+ assertNotNull(c1);
+ assertEquals("3:542bf4893dd2", c1.getId());
+
+ Changeset c2 = result.getChangesets().get(1);
+
+ assertNotNull(c2);
+ assertEquals("2:79b6baf49711", c2.getId());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetAllWithLimit() throws IOException, RepositoryException
+ {
+ LogCommandRequest request = new LogCommandRequest();
+
+ request.setPagingLimit(2);
+
+ ChangesetPagingResult result =
+ new HgLogCommand(handler, new HgContext(), repository,
+ repositoryDirectory).getChangesets(request);
+
+ assertNotNull(result);
+ assertEquals(5, result.getTotal());
+ assertEquals(2, result.getChangesets().size());
+
+ Changeset c1 = result.getChangesets().get(0);
+
+ assertNotNull(c1);
+ assertEquals("4:2baab8e80280", c1.getId());
+
+ Changeset c2 = result.getChangesets().get(1);
+
+ assertNotNull(c2);
+ assertEquals("3:542bf4893dd2", c2.getId());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetCommit() throws IOException, RepositoryException
+ {
+ HgLogCommand command = new HgLogCommand(handler, new HgContext(),
+ repository, repositoryDirectory);
+ Changeset c = command.getChangeset("a9bacaf1b7fa");
+
+ assertNotNull(c);
+ assertEquals("0:a9bacaf1b7fa", c.getId());
+ assertEquals("added a and b files", c.getDescription());
+ checkDate(c.getDate());
+ assertEquals("Douglas Adams", c.getAuthor().getName());
+ assertEquals("douglas.adams@hitchhiker.com", c.getAuthor().getMail());
+ assertEquals("added a and b files", c.getDescription());
+
+ Modifications mods = c.getModifications();
+
+ assertNotNull(mods);
+ assertTrue("modified list should be empty", mods.getModified().isEmpty());
+ assertTrue("removed list should be empty", mods.getRemoved().isEmpty());
+ assertFalse("added list should not be empty", mods.getAdded().isEmpty());
+ assertEquals(2, mods.getAdded().size());
+ assertThat(mods.getAdded(), contains("a.txt", "b.txt"));
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetRange() throws IOException, RepositoryException
+ {
+ LogCommandRequest request = new LogCommandRequest();
+
+ request.setStartChangeset("3049df33fdbb");
+ request.setEndChangeset("a9bacaf1b7fa");
+
+ ChangesetPagingResult result =
+ new HgLogCommand(handler, new HgContext(), repository,
+ repositoryDirectory).getChangesets(request);
+
+ assertNotNull(result);
+ assertEquals(2, result.getTotal());
+ assertEquals(2, result.getChangesets().size());
+
+ Changeset c1 = result.getChangesets().get(0);
+ Changeset c2 = result.getChangesets().get(1);
+
+ assertNotNull(c1);
+ assertEquals("1:3049df33fdbb", c1.getId());
+ assertNotNull(c2);
+ assertEquals("0:a9bacaf1b7fa", c2.getId());
+ }
+}
diff --git a/scm-plugins/scm-hg-plugin/src/test/resources/META-INF/services/sonia.scm.SCMContextProvider b/scm-plugins/scm-hg-plugin/src/test/resources/META-INF/services/sonia.scm.SCMContextProvider
new file mode 100644
index 0000000000..64643da7e5
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/test/resources/META-INF/services/sonia.scm.SCMContextProvider
@@ -0,0 +1 @@
+sonia.scm.repository.TempSCMContextProvider
\ No newline at end of file
diff --git a/scm-plugins/scm-hg-plugin/src/test/resources/sonia/scm/repository/spi/scm-hg-spi-test.zip b/scm-plugins/scm-hg-plugin/src/test/resources/sonia/scm/repository/spi/scm-hg-spi-test.zip
new file mode 100644
index 0000000000..4896adc9de
Binary files /dev/null and b/scm-plugins/scm-hg-plugin/src/test/resources/sonia/scm/repository/spi/scm-hg-spi-test.zip differ
diff --git a/scm-plugins/scm-svn-plugin/pom.xml b/scm-plugins/scm-svn-plugin/pom.xml
index 9bb9a7e32c..1bfd63b639 100644
--- a/scm-plugins/scm-svn-plugin/pom.xml
+++ b/scm-plugins/scm-svn-plugin/pom.xml
@@ -6,12 +6,12 @@
scm-pluginssonia.scm.plugins
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.pluginsscm-svn-plugin
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-svn-pluginhttps://bitbucket.org/sdorra/scm-managerPlugin for the version control system Subversion
@@ -48,7 +48,7 @@
sonia.scmscm-test
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTtest
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/Compatibility.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/Compatibility.java
index 3ff8438725..69ba6e2904 100644
--- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/Compatibility.java
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/Compatibility.java
@@ -39,8 +39,11 @@ package sonia.scm.repository;
*/
public enum Compatibility
{
- NONE(false, false, false), PRE14(true, true, true), PRE15(false, true, true),
- PRE16(false, false, true);
+ NONE(false, false, false, false, false),
+ PRE14(true, true, true, true, false), PRE15(false, true, true, true, false),
+ PRE16(false, false, true, true, false),
+ PRE17(false, false, false, true, false),
+ WITH17(false, false, false, false, true);
/**
* Field description
@@ -48,13 +51,18 @@ public enum Compatibility
* @param pre14Compatible
* @param pre15Compatible
* @param pre16Compatible
+ * @param pre17Compatible
+ * @param with17Compatible
*/
private Compatibility(boolean pre14Compatible, boolean pre15Compatible,
- boolean pre16Compatible)
+ boolean pre16Compatible, boolean pre17Compatible,
+ boolean with17Compatible)
{
this.pre14Compatible = pre14Compatible;
this.pre15Compatible = pre15Compatible;
this.pre16Compatible = pre16Compatible;
+ this.pre17Compatible = pre17Compatible;
+ this.with17Compatible = with17Compatible;
}
//~--- get methods ----------------------------------------------------------
@@ -92,6 +100,28 @@ public enum Compatibility
return pre16Compatible;
}
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public boolean isPre17Compatible()
+ {
+ return pre17Compatible;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public boolean isWith17Compatible()
+ {
+ return with17Compatible;
+ }
+
//~--- fields ---------------------------------------------------------------
/** Field description */
@@ -102,4 +132,10 @@ public enum Compatibility
/** Field description */
private boolean pre16Compatible;
+
+ /** Field description */
+ private boolean pre17Compatible;
+
+ /** Field description */
+ private boolean with17Compatible;
}
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 2254e94941..a33c8613e9 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
@@ -293,7 +293,9 @@ public class SvnRepositoryHandler
log.append(directory.getName()).append("\": pre14Compatible=");
log.append(comp.isPre14Compatible()).append(", pre15Compatible=");
log.append(comp.isPre15Compatible()).append(", pre16Compatible=");
- log.append(comp.isPre16Compatible());
+ log.append(comp.isPre16Compatible()).append(", pre17Compatible=");
+ log.append(comp.isPre17Compatible()).append(", with17Compatible=");
+ log.append(comp.isWith17Compatible());
logger.debug(log.toString());
}
@@ -303,7 +305,8 @@ public class SvnRepositoryHandler
{
SVNURL url = SVNRepositoryFactory.createLocalRepository(directory, null,
true, false, comp.isPre14Compatible(),
- comp.isPre15Compatible(), comp.isPre16Compatible());
+ comp.isPre15Compatible(), comp.isPre16Compatible(),
+ comp.isPre17Compatible(), comp.isWith17Compatible());
svnRepository = SVNRepositoryFactory.create(url);
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnUtil.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnUtil.java
index 20491121ef..7d1c533d2e 100644
--- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnUtil.java
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/SvnUtil.java
@@ -101,6 +101,11 @@ public class SvnUtil
public static void appendModification(Modifications modifications, char type,
String path)
{
+ if (path.startsWith("/"))
+ {
+ path = path.substring(1);
+ }
+
switch (type)
{
case SVNLogEntryPath.TYPE_ADDED :
@@ -198,4 +203,36 @@ public class SvnUtil
}
}
}
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param revision
+ *
+ * @return
+ *
+ * @throws RepositoryException
+ */
+ public static long getRevisionNumber(String revision)
+ throws RepositoryException
+ {
+ long revisionNumber = -1;
+
+ if (Util.isNotEmpty(revision))
+ {
+ try
+ {
+ revisionNumber = Long.parseLong(revision);
+ }
+ catch (NumberFormatException ex)
+ {
+ throw new RepositoryException("given revision is not a svnrevision");
+ }
+ }
+
+ return revisionNumber;
+ }
}
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/AbstractSvnCommand.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/AbstractSvnCommand.java
new file mode 100644
index 0000000000..0cc80a8e92
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/AbstractSvnCommand.java
@@ -0,0 +1,88 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.io.SVNRepository;
+import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
+
+import sonia.scm.repository.Repository;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class AbstractSvnCommand
+{
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ protected AbstractSvnCommand(SvnContext context, Repository repository)
+ {
+ this.context = context;
+ this.repository = repository;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ *
+ * @throws SVNException
+ */
+ public SVNRepository open() throws SVNException
+ {
+ return context.open();
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ protected SvnContext context;
+
+ /** Field description */
+ protected Repository repository;
+}
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnBlameCommand.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnBlameCommand.java
new file mode 100644
index 0000000000..9c059d0ea5
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnBlameCommand.java
@@ -0,0 +1,134 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.collect.Lists;
+
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
+import org.tmatesoft.svn.core.io.SVNRepository;
+import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
+import org.tmatesoft.svn.core.wc.SVNLogClient;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+
+import sonia.scm.repository.BlameLine;
+import sonia.scm.repository.BlameResult;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.repository.SvnBlameHandler;
+import sonia.scm.util.Util;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.IOException;
+
+import java.util.List;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class SvnBlameCommand extends AbstractSvnCommand implements BlameCommand
+{
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ public SvnBlameCommand(SvnContext context, Repository repository)
+ {
+ super(context, repository);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public BlameResult getBlameResult(BlameCommandRequest request)
+ throws IOException, RepositoryException
+ {
+ String path = request.getPath();
+ String revision = request.getRevision();
+ List blameLines = Lists.newArrayList();
+ SVNRevision endRevision = null;
+
+ if (Util.isNotEmpty(revision))
+ {
+ endRevision = SVNRevision.create(Long.parseLong(revision));
+ }
+ else
+ {
+ endRevision = SVNRevision.HEAD;
+ }
+
+ try
+ {
+ SVNURL svnurl = SVNURL.fromFile(new File(context.getDirectory(), path));
+ SVNRepository svnRepository =
+ SVNRepositoryFactory.create(context.createUrl());
+ ISVNAuthenticationManager svnManager =
+ svnRepository.getAuthenticationManager();
+ SVNLogClient svnLogClient = new SVNLogClient(svnManager, null);
+
+ svnLogClient.doAnnotate(svnurl, SVNRevision.UNDEFINED,
+ SVNRevision.create(1l), endRevision,
+ new SvnBlameHandler(svnRepository, path,
+ blameLines));
+ }
+ catch (SVNException ex)
+ {
+ throw new RepositoryException("could not create blame result", ex);
+ }
+
+ return new BlameResult(blameLines.size(), blameLines);
+ }
+}
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnBrowseCommand.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnBrowseCommand.java
new file mode 100644
index 0000000000..d1cea1a511
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnBrowseCommand.java
@@ -0,0 +1,230 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.tmatesoft.svn.core.SVNDirEntry;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNNodeKind;
+import org.tmatesoft.svn.core.SVNProperties;
+import org.tmatesoft.svn.core.SVNProperty;
+import org.tmatesoft.svn.core.io.SVNRepository;
+
+import sonia.scm.repository.BrowserResult;
+import sonia.scm.repository.FileObject;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.repository.SubRepository;
+import sonia.scm.repository.SvnUtil;
+import sonia.scm.util.Util;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class SvnBrowseCommand extends AbstractSvnCommand
+ implements BrowseCommand
+{
+
+ /**
+ * the logger for SvnBrowseCommand
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(SvnBrowseCommand.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ SvnBrowseCommand(SvnContext context, Repository repository)
+ {
+ super(context, repository);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public BrowserResult getBrowserResult(BrowseCommandRequest request)
+ throws IOException, RepositoryException
+ {
+ String path = request.getPath();
+ long revisionNumber = SvnUtil.getRevisionNumber(request.getRevision());
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("browser repository {} in path {} at revision {}",
+ new Object[] { repository.getName(),
+ path, revisionNumber });
+ }
+
+ BrowserResult result = null;
+
+ try
+ {
+ SVNRepository svnRepository = open();
+ Collection entries =
+ svnRepository.getDir(Util.nonNull(path), revisionNumber, null,
+ (Collection) null);
+ List children = new ArrayList();
+ String basePath = Util.EMPTY_STRING;
+
+ if (Util.isNotEmpty(path))
+ {
+ basePath = path;
+
+ if (!basePath.endsWith("/"))
+ {
+ basePath = basePath.concat("/");
+ }
+ }
+
+ for (SVNDirEntry entry : entries)
+ {
+ children.add(createFileObject(svnRepository, revisionNumber, entry,
+ basePath));
+ }
+
+ result = new BrowserResult();
+ result.setRevision(String.valueOf(revisionNumber));
+ result.setFiles(children);
+ }
+ catch (SVNException ex)
+ {
+ logger.error("could not open repository", ex);
+ }
+
+ return result;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ *
+ * @param repository
+ * @param revision
+ * @param entry
+ * @param path
+ *
+ * @return
+ */
+ private FileObject createFileObject(SVNRepository repository, long revision,
+ SVNDirEntry entry, String path)
+ {
+ FileObject fileObject = new FileObject();
+
+ fileObject.setName(entry.getName());
+ fileObject.setPath(path.concat(entry.getRelativePath()));
+ fileObject.setDirectory(entry.getKind() == SVNNodeKind.DIR);
+
+ if (entry.getDate() != null)
+ {
+ fileObject.setLastModified(entry.getDate().getTime());
+ }
+
+ fileObject.setLength(entry.getSize());
+ fileObject.setDescription(entry.getCommitMessage());
+
+ if (fileObject.isDirectory() && entry.hasProperties())
+ {
+ fetchExternalsProperty(repository, revision, entry, fileObject);
+ }
+
+ return fileObject;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ * @param revision
+ * @param entry
+ * @param fileObject
+ */
+ private void fetchExternalsProperty(SVNRepository repository, long revision,
+ SVNDirEntry entry, FileObject fileObject)
+ {
+ try
+ {
+ SVNProperties properties = new SVNProperties();
+
+ repository.getFile(entry.getRelativePath(), revision, properties, null);
+
+ String externals = properties.getStringValue(SVNProperty.EXTERNALS);
+
+ if (Util.isNotEmpty(externals))
+ {
+ SubRepository subRepository = new SubRepository(externals);
+
+ fileObject.setSubRepository(subRepository);
+ }
+ }
+ catch (SVNException ex)
+ {
+ logger.error("could not fetch file properties");
+ }
+ }
+}
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnCatCommand.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnCatCommand.java
new file mode 100644
index 0000000000..5acbe5966f
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnCatCommand.java
@@ -0,0 +1,117 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNProperties;
+import org.tmatesoft.svn.core.io.SVNRepository;
+
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.repository.SvnUtil;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class SvnCatCommand extends AbstractSvnCommand implements CatCommand
+{
+
+ /**
+ * the logger for SvnCatCommand
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(SvnCatCommand.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ SvnCatCommand(SvnContext context, Repository repository)
+ {
+ super(context, repository);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ * @param output
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public void getCatResult(CatCommandRequest request, OutputStream output)
+ throws IOException, RepositoryException
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("try to get content for {}", request);
+ }
+
+ long revisionNumber = SvnUtil.getRevisionNumber(request.getRevision());
+
+ try
+ {
+ SVNRepository svnRepository = open();
+
+ svnRepository.getFile(request.getPath(), revisionNumber,
+ new SVNProperties(), output);
+ }
+ catch (SVNException ex)
+ {
+ logger.error("could not open repository", ex);
+ }
+ }
+}
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnContext.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnContext.java
new file mode 100644
index 0000000000..3a04ec1a2d
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnContext.java
@@ -0,0 +1,154 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.io.SVNRepository;
+import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
+
+import sonia.scm.repository.SvnUtil;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class SvnContext implements Closeable
+{
+
+ /**
+ * the logger for SvnContext
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(SvnContext.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param directory
+ */
+ public SvnContext(File directory)
+ {
+ this.directory = directory;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ */
+ @Override
+ public void close() throws IOException
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("close svn repository {}", directory);
+ }
+
+ SvnUtil.closeSession(repository);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ *
+ * @throws SVNException
+ */
+ public SVNURL createUrl() throws SVNException
+ {
+ return SVNURL.fromFile(directory);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ *
+ * @throws SVNException
+ */
+ public SVNRepository open() throws SVNException
+ {
+ if (repository == null)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("open svn repository {}", directory);
+ }
+
+ repository = SVNRepositoryFactory.create(createUrl());
+ }
+
+ return repository;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public File getDirectory()
+ {
+ return directory;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private File directory;
+
+ /** Field description */
+ private SVNRepository repository;
+}
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnDiffCommand.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnDiffCommand.java
new file mode 100644
index 0000000000..8990240223
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnDiffCommand.java
@@ -0,0 +1,157 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Preconditions;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.tmatesoft.svn.core.SVNDepth;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.wc.DefaultSVNDiffGenerator;
+import org.tmatesoft.svn.core.wc.ISVNDiffGenerator;
+import org.tmatesoft.svn.core.wc.SVNClientManager;
+import org.tmatesoft.svn.core.wc.SVNDiffClient;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.repository.SvnUtil;
+import sonia.scm.util.Util;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class SvnDiffCommand extends AbstractSvnCommand implements DiffCommand
+{
+
+ /**
+ * the logger for SvnDiffCommand
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(SvnDiffCommand.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ public SvnDiffCommand(SvnContext context, Repository repository)
+ {
+ super(context, repository);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ * @param output
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public void getDiffResult(DiffCommandRequest request, OutputStream output)
+ throws IOException, RepositoryException
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("create diff for {}", request);
+ }
+
+ Preconditions.checkNotNull(request, "request is required");
+ Preconditions.checkNotNull(output, "outputstream is required");
+
+ String path = request.getPath();
+ SVNClientManager clientManager = null;
+
+ try
+ {
+ SVNURL svnurl = context.createUrl();
+
+ if (Util.isNotEmpty(path))
+ {
+ svnurl = svnurl.appendPath(path, true);
+ }
+
+ clientManager = SVNClientManager.newInstance();
+
+ SVNDiffClient diffClient = clientManager.getDiffClient();
+ ISVNDiffGenerator diffGenerator = diffClient.getDiffGenerator();
+
+ if (diffGenerator == null)
+ {
+ diffGenerator = new DefaultSVNDiffGenerator();
+ }
+
+ diffGenerator.setDiffAdded(true);
+ diffGenerator.setDiffDeleted(true);
+ diffClient.setDiffGenerator(diffGenerator);
+
+ long currentRev = SvnUtil.getRevisionNumber(request.getRevision());
+
+ diffClient.doDiff(svnurl, SVNRevision.HEAD,
+ SVNRevision.create(currentRev - 1),
+ SVNRevision.create(currentRev), SVNDepth.INFINITY,
+ false, output);
+ }
+ catch (SVNException ex)
+ {
+ throw new RepositoryException("could not create diff", ex);
+ }
+ finally
+ {
+ SvnUtil.dispose(clientManager);
+ }
+ }
+}
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLogCommand.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLogCommand.java
new file mode 100644
index 0000000000..74b1eb5566
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLogCommand.java
@@ -0,0 +1,229 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNLogEntry;
+import org.tmatesoft.svn.core.io.SVNRepository;
+
+import sonia.scm.repository.Changeset;
+import sonia.scm.repository.ChangesetPagingResult;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.repository.SvnUtil;
+import sonia.scm.util.Util;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class SvnLogCommand extends AbstractSvnCommand implements LogCommand
+{
+
+ /**
+ * the logger for SvnLogCommand
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(SvnLogCommand.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param context
+ * @param repository
+ * @param repositoryDirectory
+ */
+ SvnLogCommand(SvnContext context, Repository repository)
+ {
+ super(context, repository);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param revision
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public Changeset getChangeset(String revision)
+ throws IOException, RepositoryException
+ {
+ Changeset changeset = null;
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("fetch changeset {}", revision);
+ }
+
+ try
+ {
+ long revisioNumber = Long.parseLong(revision);
+ SVNRepository repository = open();
+ Collection entries = repository.log(null, null,
+ revisioNumber, revisioNumber, true,
+ true);
+
+ if (Util.isNotEmpty(entries))
+ {
+ changeset = SvnUtil.createChangeset(entries.iterator().next());
+ }
+ }
+ catch (NumberFormatException ex)
+ {
+ throw new RepositoryException("could not convert revision", ex);
+ }
+ catch (SVNException ex)
+ {
+ throw new RepositoryException("could not open repository", ex);
+ }
+
+ return changeset;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public ChangesetPagingResult getChangesets(LogCommandRequest request)
+ throws IOException, RepositoryException
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("fetch changesets for {}", request);
+ }
+
+ ChangesetPagingResult changesets = null;
+ String startRevision = request.getStartChangeset();
+ String endRevision = request.getEndChangeset();
+
+ try
+ {
+ SVNRepository repository = open();
+ long startRev = repository.getLatestRevision();
+ long endRev = 0;
+ long maxRev = startRev;
+
+ if (!Strings.isNullOrEmpty(startRevision))
+ {
+ startRev = Long.parseLong(startRevision);
+ }
+
+ if (!Strings.isNullOrEmpty(endRevision))
+ {
+ endRev = Long.parseLong(endRevision);
+ }
+
+ String[] pathArray = null;
+
+ if (!Strings.isNullOrEmpty(request.getPath()))
+ {
+ pathArray = new String[] { request.getPath() };
+ }
+
+ List changesetList = Lists.newArrayList();
+ Collection entries = repository.log(pathArray, null,
+ startRev, endRev, true, true);
+
+ for (SVNLogEntry entry : entries)
+ {
+ if (entry.getRevision() <= maxRev)
+ {
+ changesetList.add(SvnUtil.createChangeset(entry));
+ }
+ }
+
+ int total = changesetList.size();
+ int start = request.getPagingStart();
+ int max = request.getPagingLimit() + start;
+ int end = total;
+
+ if (end > max)
+ {
+ end = max;
+ }
+
+ if (start < 0)
+ {
+ start = 0;
+ }
+
+ changesetList = Lists.newArrayList(changesetList.subList(start, end));
+ changesets = new ChangesetPagingResult(total, changesetList);
+ }
+ catch (NumberFormatException ex)
+ {
+ throw new RepositoryException(
+ "could not parse revision ".concat(startRevision), ex);
+ }
+ catch (SVNException ex)
+ {
+ throw new RepositoryException("could not open repository", ex);
+ }
+
+ return changesets;
+ }
+}
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java
new file mode 100644
index 0000000000..eb260209dc
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java
@@ -0,0 +1,156 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.collect.ImmutableSet;
+
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.SvnRepositoryHandler;
+import sonia.scm.repository.api.Command;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.util.Set;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class SvnRepositoryServiceProvider extends RepositoryServiceProvider
+{
+
+ /** Field description */
+ private static final Set COMMANDS = ImmutableSet.of(Command.BLAME,
+ Command.BROWSE, Command.CAT,
+ Command.DIFF, Command.LOG);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param handler
+ * @param repository
+ */
+ SvnRepositoryServiceProvider(SvnRepositoryHandler handler,
+ Repository repository)
+ {
+ this.repository = repository;
+ this.context = new SvnContext(handler.getDirectory(repository));
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public SvnBlameCommand getBlameCommand()
+ {
+ return new SvnBlameCommand(context, repository);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public SvnBrowseCommand getBrowseCommand()
+ {
+ return new SvnBrowseCommand(context, repository);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public SvnCatCommand getCatCommand()
+ {
+ return new SvnCatCommand(context, repository);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public SvnDiffCommand getDiffCommand()
+ {
+ return new SvnDiffCommand(context, repository);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public SvnLogCommand getLogCommand()
+ {
+ return new SvnLogCommand(context, repository);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public Set getSupportedCommands()
+ {
+ return COMMANDS;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private SvnContext context;
+
+ /** Field description */
+ private Repository repository;
+}
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java
new file mode 100644
index 0000000000..cf01df8f84
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceResolver.java
@@ -0,0 +1,95 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.inject.Inject;
+
+import sonia.scm.plugin.ext.Extension;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.SvnRepositoryHandler;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+@Extension
+public class SvnRepositoryServiceResolver implements RepositoryServiceResolver
+{
+
+ /** Field description */
+ public static final String TYPE = "svn";
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param handler
+ */
+ @Inject
+ public SvnRepositoryServiceResolver(SvnRepositoryHandler handler)
+ {
+ this.handler = handler;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ *
+ * @return
+ */
+ @Override
+ public SvnRepositoryServiceProvider reslove(Repository repository)
+ {
+ SvnRepositoryServiceProvider provider = null;
+
+ if (TYPE.equalsIgnoreCase(repository.getType()))
+ {
+ provider = new SvnRepositoryServiceProvider(handler, repository);
+ }
+
+ return provider;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private SvnRepositoryHandler handler;
+}
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilter.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilter.java
index 0daa5d6af8..2267673e3f 100644
--- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilter.java
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilter.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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;
//~--- non-JDK imports --------------------------------------------------------
diff --git a/scm-plugins/scm-svn-plugin/src/main/resources/sonia/scm/svn.config.js b/scm-plugins/scm-svn-plugin/src/main/resources/sonia/scm/svn.config.js
index 5cc3339c78..1359b71696 100644
--- a/scm-plugins/scm-svn-plugin/src/main/resources/sonia/scm/svn.config.js
+++ b/scm-plugins/scm-svn-plugin/src/main/resources/sonia/scm/svn.config.js
@@ -40,6 +40,8 @@ Sonia.svn.ConfigPanel = Ext.extend(Sonia.config.SimpleConfigForm, {
pre14CompatibleText: 'Pre 1.4 Compatible',
pre15CompatibleText: 'Pre 1.5 Compatible',
pre16CompatibleText: 'Pre 1.6 Compatible',
+ pre17CompatibleText: 'Pre 1.7 Compatible',
+ with17CompatibleText: 'With 1.7 Compatible',
enableGZipText: 'Enable GZip Encoding',
disabledText: 'Disabled',
@@ -80,6 +82,14 @@ Sonia.svn.ConfigPanel = Ext.extend(Sonia.config.SimpleConfigForm, {
boxLabel: this.pre16CompatibleText,
inputValue: 'PRE16',
name: 'compatibility'
+ },{
+ boxLabel: this.pre17CompatibleText,
+ inputValue: 'PRE17',
+ name: 'compatibility'
+ },{
+ boxLabel: this.with17CompatibleText,
+ inputValue: 'WITH17',
+ name: 'compatibility'
}]
},{
xtype: 'checkbox',
@@ -117,6 +127,8 @@ if ( i18n != null && i18n.country == 'de' ){
pre14CompatibleText: 'Mit Versionen vor 1.4 kompatibel',
pre15CompatibleText: 'Mit Versionen vor 1.5 kompatibel',
pre16CompatibleText: 'Mit Versionen vor 1.6 kompatibel',
+ pre17CompatibleText: 'Mit Versionen vor 1.7 kompatibel',
+ with17CompatibleText: 'Mit Version 1.7 kompatibel',
disabledText: 'Deaktivieren',
// helpTexts
diff --git a/scm-plugins/scm-svn-plugin/src/main/resources/sonia/scm/version/scm-svn-plugin b/scm-plugins/scm-svn-plugin/src/main/resources/sonia/scm/version/scm-svn-plugin
index 76ed46fd46..76fa1f0105 100644
--- a/scm-plugins/scm-svn-plugin/src/main/resources/sonia/scm/version/scm-svn-plugin
+++ b/scm-plugins/scm-svn-plugin/src/main/resources/sonia/scm/version/scm-svn-plugin
@@ -1 +1 @@
-scm-svn-plugin/${project.version} svnkit/${svnkit-dav.version}
\ No newline at end of file
+scm-svn-plugin/${project.version} svnkit/${svnkit.version}
\ No newline at end of file
diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/AbstractSvnCommandTestBase.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/AbstractSvnCommandTestBase.java
new file mode 100644
index 0000000000..81b55e5db3
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/AbstractSvnCommandTestBase.java
@@ -0,0 +1,111 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.junit.After;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class AbstractSvnCommandTestBase extends ZippedRepositoryTestBase
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ */
+ @After
+ public void close() throws IOException
+ {
+ if (context != null)
+ {
+ context.close();
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public SvnContext createContext()
+ {
+ if (context == null)
+ {
+ context = new SvnContext(repositoryDirectory);
+ }
+
+ return context;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ protected String getType()
+ {
+ return "svn";
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ protected String getZippedRepositoryResource()
+ {
+ return "sonia/scm/repository/spi/scm-svn-spi-test.zip";
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private SvnContext context;
+}
diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnBlameCommandTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnBlameCommandTest.java
new file mode 100644
index 0000000000..e320dd3251
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnBlameCommandTest.java
@@ -0,0 +1,141 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.junit.Test;
+
+import sonia.scm.repository.BlameLine;
+import sonia.scm.repository.BlameResult;
+import sonia.scm.repository.RepositoryException;
+
+import static org.junit.Assert.*;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class SvnBlameCommandTest extends AbstractSvnCommandTestBase
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetBlameResult() throws IOException, RepositoryException
+ {
+ BlameCommandRequest request = new BlameCommandRequest();
+
+ request.setPath("a.txt");
+
+ BlameResult result = createCommand().getBlameResult(request);
+
+ assertNotNull(result);
+ assertEquals(2, result.getTotal());
+
+ BlameLine line = result.getLine(0);
+
+ checkFirstLine(line);
+ line = result.getLine(1);
+ assertEquals(2, line.getLineNumber());
+ assertEquals("5", line.getRevision());
+ checkDate(line.getWhen());
+ assertEquals("line for blame test", line.getCode());
+ assertEquals("added line for blame test", line.getDescription());
+ assertEquals("zaphod", line.getAuthor().getName());
+ assertNull(line.getAuthor().getMail());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetBlameResultWithRevision()
+ throws IOException, RepositoryException
+ {
+ BlameCommandRequest request = new BlameCommandRequest();
+
+ request.setPath("a.txt");
+ request.setRevision("3");
+
+ BlameResult result = createCommand().getBlameResult(request);
+
+ assertNotNull(result);
+ assertEquals(1, result.getTotal());
+
+ BlameLine line = result.getLine(0);
+
+ checkFirstLine(line);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param line
+ */
+ private void checkFirstLine(BlameLine line)
+ {
+ assertEquals(1, line.getLineNumber());
+ assertEquals("3", line.getRevision());
+ checkDate(line.getWhen());
+ assertEquals("a and b", line.getCode());
+ assertEquals("remove b and modified a", line.getDescription());
+ assertEquals("perfect", line.getAuthor().getName());
+ assertNull(line.getAuthor().getMail());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ private SvnBlameCommand createCommand()
+ {
+ return new SvnBlameCommand(createContext(), repository);
+ }
+}
diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnBrowseCommandTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnBrowseCommandTest.java
new file mode 100644
index 0000000000..e59b878d5c
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnBrowseCommandTest.java
@@ -0,0 +1,172 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.junit.Test;
+
+import sonia.scm.repository.BrowserResult;
+import sonia.scm.repository.FileObject;
+import sonia.scm.repository.RepositoryException;
+
+import static org.junit.Assert.*;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+import java.util.List;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class SvnBrowseCommandTest extends AbstractSvnCommandTestBase
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testBrowse() throws IOException, RepositoryException
+ {
+ BrowserResult result =
+ createCommand().getBrowserResult(new BrowseCommandRequest());
+
+ assertNotNull(result);
+
+ List foList = result.getFiles();
+
+ assertNotNull(foList);
+ assertFalse(foList.isEmpty());
+ assertEquals(2, foList.size());
+
+ FileObject a = null;
+ FileObject c = null;
+
+ for (FileObject f : foList)
+ {
+ if ("a.txt".equals(f.getName()))
+ {
+ a = f;
+ }
+ else if ("c".equals(f.getName()))
+ {
+ c = f;
+ }
+ }
+
+ assertNotNull(a);
+ assertFalse(a.isDirectory());
+ assertEquals("a.txt", a.getName());
+ assertEquals("a.txt", a.getPath());
+ assertEquals("added line for blame test", a.getDescription());
+ assertTrue(a.getLength() > 0);
+ checkDate(a.getLastModified());
+ assertNotNull(c);
+ assertTrue(c.isDirectory());
+ assertEquals("c", c.getName());
+ assertEquals("c", c.getPath());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testBrowseSubDirectory() throws IOException, RepositoryException
+ {
+ BrowseCommandRequest request = new BrowseCommandRequest();
+
+ request.setPath("c");
+
+ BrowserResult result = createCommand().getBrowserResult(request);
+
+ assertNotNull(result);
+
+ List foList = result.getFiles();
+
+ assertNotNull(foList);
+ assertFalse(foList.isEmpty());
+ assertEquals(2, foList.size());
+
+ FileObject d = null;
+ FileObject e = null;
+
+ for (FileObject f : foList)
+ {
+ if ("d.txt".equals(f.getName()))
+ {
+ d = f;
+ }
+ else if ("e.txt".equals(f.getName()))
+ {
+ e = f;
+ }
+ }
+
+ assertNotNull(d);
+ assertFalse(d.isDirectory());
+ assertEquals("d.txt", d.getName());
+ assertEquals("c/d.txt", d.getPath());
+ assertEquals("added d and e in folder c", d.getDescription());
+ assertTrue(d.getLength() > 0);
+ checkDate(d.getLastModified());
+ assertNotNull(e);
+ assertFalse(e.isDirectory());
+ assertEquals("e.txt", e.getName());
+ assertEquals("c/e.txt", e.getPath());
+ assertEquals("added d and e in folder c", e.getDescription());
+ assertTrue(e.getLength() > 0);
+ checkDate(e.getLastModified());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ private SvnBrowseCommand createCommand()
+ {
+ return new SvnBrowseCommand(createContext(), repository);
+ }
+}
diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnCatCommandTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnCatCommandTest.java
new file mode 100644
index 0000000000..198a55edf3
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnCatCommandTest.java
@@ -0,0 +1,117 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.junit.Test;
+
+import sonia.scm.repository.RepositoryException;
+
+import static org.junit.Assert.*;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class SvnCatCommandTest extends AbstractSvnCommandTestBase
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testCat() throws IOException, RepositoryException
+ {
+ CatCommandRequest request = new CatCommandRequest();
+
+ request.setPath("a.txt");
+ request.setRevision("1");
+ assertEquals("a", execute(request));
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testSimpleCat() throws IOException, RepositoryException
+ {
+ CatCommandRequest request = new CatCommandRequest();
+
+ request.setPath("c/d.txt");
+ assertEquals("d", execute(request));
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ private String execute(CatCommandRequest request)
+ throws IOException, RepositoryException
+ {
+ String content = null;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ try
+ {
+ new SvnCatCommand(createContext(), repository).getCatResult(request,
+ baos);
+ }
+ finally
+ {
+ content = baos.toString().trim();
+ }
+
+ return content;
+ }
+}
diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnLogCommandTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnLogCommandTest.java
new file mode 100644
index 0000000000..a3942bd0f4
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnLogCommandTest.java
@@ -0,0 +1,231 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.junit.Test;
+
+import sonia.scm.repository.Changeset;
+import sonia.scm.repository.ChangesetPagingResult;
+import sonia.scm.repository.Modifications;
+import sonia.scm.repository.RepositoryException;
+
+import static org.junit.Assert.*;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class SvnLogCommandTest extends AbstractSvnCommandTestBase
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetAll() throws IOException, RepositoryException
+ {
+ ChangesetPagingResult result =
+ createCommand().getChangesets(new LogCommandRequest());
+
+ assertNotNull(result);
+ assertEquals(6, result.getTotal());
+ assertEquals(6, result.getChangesets().size());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetAllByPath() throws IOException, RepositoryException
+ {
+ LogCommandRequest request = new LogCommandRequest();
+
+ request.setPath("a.txt");
+
+ ChangesetPagingResult result = createCommand().getChangesets(request);
+
+ assertNotNull(result);
+ assertEquals(3, result.getTotal());
+ assertEquals(3, result.getChangesets().size());
+ assertEquals("5", result.getChangesets().get(0).getId());
+ assertEquals("3", result.getChangesets().get(1).getId());
+ assertEquals("1", result.getChangesets().get(2).getId());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetAllWithLimit() throws IOException, RepositoryException
+ {
+ LogCommandRequest request = new LogCommandRequest();
+
+ request.setPagingLimit(2);
+
+ ChangesetPagingResult result = createCommand().getChangesets(request);
+
+ assertNotNull(result);
+ assertEquals(6, result.getTotal());
+ assertEquals(2, result.getChangesets().size());
+
+ Changeset c1 = result.getChangesets().get(0);
+
+ assertNotNull(c1);
+ assertEquals("5", c1.getId());
+
+ Changeset c2 = result.getChangesets().get(1);
+
+ assertNotNull(c2);
+ assertEquals("4", c2.getId());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetAllWithPaging() throws IOException, RepositoryException
+ {
+ LogCommandRequest request = new LogCommandRequest();
+
+ request.setPagingStart(1);
+ request.setPagingLimit(2);
+
+ ChangesetPagingResult result = createCommand().getChangesets(request);
+
+ assertNotNull(result);
+ assertEquals(6, result.getTotal());
+ assertEquals(2, result.getChangesets().size());
+
+ Changeset c1 = result.getChangesets().get(0);
+
+ assertNotNull(c1);
+ assertEquals("4", c1.getId());
+
+ Changeset c2 = result.getChangesets().get(1);
+
+ assertNotNull(c2);
+ assertEquals("3", c2.getId());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetCommit() throws IOException, RepositoryException
+ {
+ Changeset c = createCommand().getChangeset("3");
+
+ assertNotNull(c);
+ assertEquals("3", c.getId());
+ assertEquals("remove b and modified a", c.getDescription());
+ checkDate(c.getDate());
+ assertEquals("perfect", c.getAuthor().getName());
+ assertNull("douglas.adams@hitchhiker.com", c.getAuthor().getMail());
+
+ Modifications mods = c.getModifications();
+
+ assertNotNull(mods);
+ assertEquals(1, mods.getModified().size());
+ assertEquals(1, mods.getRemoved().size());
+ assertTrue("added list should be empty", mods.getAdded().isEmpty());
+ assertEquals("a.txt", mods.getModified().get(0));
+ assertEquals("b.txt", mods.getRemoved().get(0));
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Test
+ public void testGetRange() throws IOException, RepositoryException
+ {
+ LogCommandRequest request = new LogCommandRequest();
+
+ request.setStartChangeset("2");
+ request.setEndChangeset("1");
+
+ ChangesetPagingResult result = createCommand().getChangesets(request);
+
+ assertNotNull(result);
+ assertEquals(2, result.getTotal());
+ assertEquals(2, result.getChangesets().size());
+
+ Changeset c1 = result.getChangesets().get(0);
+ Changeset c2 = result.getChangesets().get(1);
+
+ assertNotNull(c1);
+ assertEquals("2", c1.getId());
+ assertNotNull(c2);
+ assertEquals("1", c2.getId());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ private SvnLogCommand createCommand()
+ {
+ return new SvnLogCommand(createContext(), repository);
+ }
+}
diff --git a/scm-plugins/scm-svn-plugin/src/test/resources/sonia/scm/repository/spi/scm-svn-spi-test.zip b/scm-plugins/scm-svn-plugin/src/test/resources/sonia/scm/repository/spi/scm-svn-spi-test.zip
new file mode 100644
index 0000000000..6e27feef41
Binary files /dev/null and b/scm-plugins/scm-svn-plugin/src/test/resources/sonia/scm/repository/spi/scm-svn-spi-test.zip differ
diff --git a/scm-samples/pom.xml b/scm-samples/pom.xml
index def37d44c7..459bd98d7e 100644
--- a/scm-samples/pom.xml
+++ b/scm-samples/pom.xml
@@ -6,13 +6,13 @@
sonia.scmscm
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.samplesscm-samplespom
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-samples
diff --git a/scm-samples/scm-sample-auth/pom.xml b/scm-samples/scm-sample-auth/pom.xml
index 209ae3d930..4869d3f692 100644
--- a/scm-samples/scm-sample-auth/pom.xml
+++ b/scm-samples/scm-sample-auth/pom.xml
@@ -6,12 +6,12 @@
scm-samplessonia.scm.samples
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.samplescm-sample-auth
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-sample-authSample Authentication Pluginhttps://bitbucket.org/sdorra/scm-manager
@@ -28,7 +28,7 @@
sonia.scmscm-core
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOT
diff --git a/scm-samples/scm-sample-hello/pom.xml b/scm-samples/scm-sample-hello/pom.xml
index 8fc95b1024..26d772606f 100644
--- a/scm-samples/scm-sample-hello/pom.xml
+++ b/scm-samples/scm-sample-hello/pom.xml
@@ -6,12 +6,12 @@
scm-samplessonia.scm.samples
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.samplescm-sample-hello
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-sample-helloA simple hello world pluginhttps://bitbucket.org/sdorra/scm-manager
@@ -28,7 +28,7 @@
sonia.scmscm-core
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOT
diff --git a/scm-server/pom.xml b/scm-server/pom.xml
index 1d8862ff1c..b779966ddb 100644
--- a/scm-server/pom.xml
+++ b/scm-server/pom.xml
@@ -6,12 +6,12 @@
scmsonia.scm
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scmscm-server
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-serverjar
diff --git a/scm-test/pom.xml b/scm-test/pom.xml
index 3b8c0b9728..1c87e3e9d9 100644
--- a/scm-test/pom.xml
+++ b/scm-test/pom.xml
@@ -6,12 +6,12 @@
scmsonia.scm
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scmscm-test
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-test
@@ -25,7 +25,7 @@
sonia.scmscm-core
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOT
diff --git a/scm-test/src/main/java/sonia/scm/cache/MapCache.java b/scm-test/src/main/java/sonia/scm/cache/MapCache.java
new file mode 100644
index 0000000000..24a0d7622c
--- /dev/null
+++ b/scm-test/src/main/java/sonia/scm/cache/MapCache.java
@@ -0,0 +1,154 @@
+/**
+ * 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.cache;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.collect.Maps;
+
+import sonia.scm.Filter;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.util.Map;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ *
+ * @param
+ * @param
+ */
+public class MapCache implements Cache
+{
+
+ /**
+ * Method description
+ *
+ */
+ @Override
+ public void clear()
+ {
+ map.clear();
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ *
+ * @return
+ */
+ @Override
+ public boolean contains(K key)
+ {
+ return map.containsKey(key);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ * @param value
+ */
+ @Override
+ public void put(K key, V value)
+ {
+ map.put(key, value);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ *
+ * @return
+ */
+ @Override
+ public boolean remove(K key)
+ {
+ return map.remove(key) != null;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param filter
+ *
+ * @return
+ */
+ @Override
+ public boolean removeAll(Filter filter)
+ {
+ boolean result = false;
+
+ for (K key : map.keySet())
+ {
+ if (filter.accept(key))
+ {
+ if (remove(key))
+ {
+ result = true;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ *
+ * @return
+ */
+ @Override
+ public V get(K key)
+ {
+ return map.get(key);
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private Map map = Maps.newHashMap();
+}
diff --git a/scm-test/src/main/java/sonia/scm/cache/MapCacheManager.java b/scm-test/src/main/java/sonia/scm/cache/MapCacheManager.java
new file mode 100644
index 0000000000..afc4580f99
--- /dev/null
+++ b/scm-test/src/main/java/sonia/scm/cache/MapCacheManager.java
@@ -0,0 +1,181 @@
+/**
+ * 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.cache;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Objects;
+import com.google.common.collect.Maps;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+import java.util.Map;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.17
+ */
+public class MapCacheManager implements CacheManager
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @throws IOException
+ */
+ @Override
+ public void close() throws IOException
+ {
+
+ // do nothing
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ * @param value
+ * @param name
+ * @param
+ * @param
+ *
+ * @return
+ */
+ @Override
+ public Cache getCache(Class key, Class value, String name)
+ {
+ CacheKey cacheKey = new CacheKey(key, value, name);
+ Cache cache = cacheMap.get(cacheKey);
+
+ if (cache == null)
+ {
+ cache = new MapCache();
+ cacheMap.put(cacheKey, cache);
+ }
+
+ return cache;
+ }
+
+ //~--- inner classes --------------------------------------------------------
+
+ /**
+ * Class description
+ *
+ *
+ * @version Enter version here..., 12/06/24
+ * @author Enter your name here...
+ */
+ private static class CacheKey
+ {
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param key
+ * @param value
+ * @param name
+ */
+ public CacheKey(Class key, Class value, String name)
+ {
+ this.key = key;
+ this.value = value;
+ this.name = name;
+ }
+
+ //~--- methods ------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param obj
+ *
+ * @return
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+
+ final CacheKey other = (CacheKey) obj;
+
+ return Objects.equal(key, other.key) && Objects.equal(value, other.value)
+ && Objects.equal(name, other.name);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public int hashCode()
+ {
+ return Objects.hashCode(key, value, name);
+ }
+
+ //~--- fields -------------------------------------------------------------
+
+ /** Field description */
+ private Class key;
+
+ /** Field description */
+ private String name;
+
+ /** Field description */
+ private Class value;
+ }
+
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private Map cacheMap = Maps.newHashMap();
+}
diff --git a/scm-test/src/main/java/sonia/scm/repository/spi/ZippedRepositoryTestBase.java b/scm-test/src/main/java/sonia/scm/repository/spi/ZippedRepositoryTestBase.java
new file mode 100644
index 0000000000..f42fb0993b
--- /dev/null
+++ b/scm-test/src/main/java/sonia/scm/repository/spi/ZippedRepositoryTestBase.java
@@ -0,0 +1,216 @@
+/**
+ * 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.spi;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.io.Closeables;
+import com.google.common.io.Resources;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryTestData;
+import sonia.scm.util.IOUtil;
+
+import static org.junit.Assert.*;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.net.URL;
+
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public abstract class ZippedRepositoryTestBase
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ protected abstract String getType();
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ protected abstract String getZippedRepositoryResource();
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ */
+ @Before
+ public void before()
+ {
+ repositoryDirectory = createRepositoryDirectory();
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param date
+ */
+ protected void checkDate(Long date)
+ {
+ assertNotNull(date);
+ assertTrue("Date should not be older than current date",
+ date < System.currentTimeMillis());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ protected Repository createRepository()
+ {
+ return RepositoryTestData.createHeartOfGold(getType());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ protected File createRepositoryDirectory()
+ {
+ File folder = null;
+
+ try
+ {
+ folder = tempFolder.newFolder();
+ folder.mkdirs();
+ extract(folder);
+ }
+ catch (IOException ex)
+ {
+ fail(ex.getMessage());
+ }
+
+ return folder;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param folder
+ *
+ * @throws IOException
+ */
+ private void extract(File folder) throws IOException
+ {
+ URL url = Resources.getResource(getZippedRepositoryResource());
+ ZipInputStream zip = null;
+
+ try
+ {
+ zip = new ZipInputStream(url.openStream());
+
+ ZipEntry entry = zip.getNextEntry();
+
+ while (entry != null)
+ {
+ File file = new File(folder, entry.getName());
+ File parent = file.getParentFile();
+
+ if (!parent.exists())
+ {
+ parent.mkdirs();
+ }
+
+ if (entry.isDirectory())
+ {
+ file.mkdirs();
+ }
+ else
+ {
+ OutputStream output = null;
+
+ try
+ {
+ output = new FileOutputStream(file);
+ IOUtil.copy(zip, output);
+ }
+ finally
+ {
+ Closeables.closeQuietly(output);
+ }
+ }
+
+ zip.closeEntry();
+ entry = zip.getNextEntry();
+ }
+ }
+ finally
+ {
+ Closeables.closeQuietly(zip);
+ }
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ @Rule
+ public TemporaryFolder tempFolder = new TemporaryFolder();
+
+ /** Field description */
+ protected Repository repository = createRepository();
+
+ /** Field description */
+ protected File repositoryDirectory;
+}
diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml
index 52c456c6a8..93504d5211 100644
--- a/scm-webapp/pom.xml
+++ b/scm-webapp/pom.xml
@@ -6,13 +6,13 @@
sonia.scmscm
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scmscm-webappwar
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTscm-webapp
@@ -38,31 +38,31 @@
sonia.scmscm-core
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scmscm-dao-xml
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.pluginsscm-hg-plugin
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.pluginsscm-svn-plugin
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTsonia.scm.pluginsscm-git-plugin
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOT
@@ -221,7 +221,7 @@
sonia.scmscm-test
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOTtest
@@ -231,6 +231,20 @@
+
+ org.seleniumhq.selenium
+ selenium-java
+ 2.24.1
+ test
+
+
+
+ org.seleniumhq.selenium
+ selenium-firefox-driver
+ 2.24.1
+ test
+
+
com.jcraftjsch
@@ -373,7 +387,7 @@
sonia.scmscm-dao-orientdb
- 1.17-SNAPSHOT
+ 1.18-SNAPSHOT
@@ -435,6 +449,11 @@
org.apache.maven.pluginsmaven-failsafe-plugin2.12
+
+
+ sonia/scm/it/*ITCase.java
+
+ integration-test
@@ -499,6 +518,110 @@
+
+ selenium
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+ 2.12
+
+
+ sonia/scm/selenium/*ITCase.java
+
+
+
+
+ integration-test
+
+ integration-test
+
+
+
+ verify
+
+ verify
+
+
+
+
+
+
+ org.mortbay.jetty
+ maven-jetty-plugin
+ 6.1.26
+
+ 8086
+ STOP
+
+
+ scm.home
+ target/scm-it
+
+
+
+
+ 8082
+ 60000
+
+
+ ${project.build.javaLevel}
+ ${project.build.javaLevel}
+ ${project.build.sourceEncoding}
+ 0
+ true
+
+
+
+ start-jetty
+ pre-integration-test
+
+ deploy-war
+
+
+
+ stop-jetty
+ post-integration-test
+
+ stop
+
+
+
+
+
+
+ org.codehaus.mojo
+ selenium-maven-plugin
+ 2.3
+
+
+ start-selenium-server
+ pre-integration-test
+
+ start-server
+
+
+ true
+
+
+
+ stop-selenium-server
+ post-integration-test
+
+ stop-server
+
+
+
+
+
+
+
+
+
+
doc
diff --git a/scm-webapp/src/main/java/sonia/scm/BindingExtensionProcessor.java b/scm-webapp/src/main/java/sonia/scm/BindingExtensionProcessor.java
index c3195ff97c..666e925ddf 100644
--- a/scm-webapp/src/main/java/sonia/scm/BindingExtensionProcessor.java
+++ b/scm-webapp/src/main/java/sonia/scm/BindingExtensionProcessor.java
@@ -46,6 +46,8 @@ import sonia.scm.group.GroupListener;
import sonia.scm.io.FileSystem;
import sonia.scm.plugin.ext.Extension;
import sonia.scm.plugin.ext.ExtensionProcessor;
+import sonia.scm.repository.BlameLinePreProcessor;
+import sonia.scm.repository.BlameLinePreProcessorFactory;
import sonia.scm.repository.ChangesetPreProcessor;
import sonia.scm.repository.ChangesetPreProcessorFactory;
import sonia.scm.repository.FileObjectPreProcessor;
@@ -54,6 +56,7 @@ import sonia.scm.repository.RepositoryHandler;
import sonia.scm.repository.RepositoryHook;
import sonia.scm.repository.RepositoryListener;
import sonia.scm.repository.RepositoryRequestListener;
+import sonia.scm.repository.spi.RepositoryServiceResolver;
import sonia.scm.resources.ResourceHandler;
import sonia.scm.security.EncryptionHandler;
import sonia.scm.user.UserListener;
@@ -124,6 +127,16 @@ public class BindingExtensionProcessor implements ExtensionProcessor
Multibinder fileObjectPreProcessorFactoryBinder =
Multibinder.newSetBinder(binder, FileObjectPreProcessorFactory.class);
+ // blameline pre processor
+ Multibinder blameLinePreProcessorBinder =
+ Multibinder.newSetBinder(binder, BlameLinePreProcessor.class);
+ Multibinder blameLinePreProcessorFactoryBinder =
+ Multibinder.newSetBinder(binder, BlameLinePreProcessorFactory.class);
+
+ // repository service resolver
+ Multibinder repositoryServiceResolverBinder =
+ Multibinder.newSetBinder(binder, RepositoryServiceResolver.class);
+
// listeners
Multibinder repositoryListenerBinder =
Multibinder.newSetBinder(binder, RepositoryListener.class);
@@ -268,6 +281,27 @@ public class BindingExtensionProcessor implements ExtensionProcessor
fileObjectPreProcessorFactoryBinder.addBinding().to(extensionClass);
}
+ else if (BlameLinePreProcessor.class.isAssignableFrom(extensionClass))
+ {
+ if (logger.isInfoEnabled())
+ {
+ logger.info("bind BlameLinePreProcessor {}",
+ extensionClass.getName());
+ }
+
+ blameLinePreProcessorBinder.addBinding().to(extensionClass);
+ }
+ else if (BlameLinePreProcessorFactory.class.isAssignableFrom(
+ extensionClass))
+ {
+ if (logger.isInfoEnabled())
+ {
+ logger.info("bind BlameLinePreProcessorFactory {}",
+ extensionClass.getName());
+ }
+
+ blameLinePreProcessorFactoryBinder.addBinding().to(extensionClass);
+ }
else if (RepositoryHook.class.isAssignableFrom(extensionClass))
{
if (logger.isInfoEnabled())
@@ -297,6 +331,16 @@ public class BindingExtensionProcessor implements ExtensionProcessor
servletContextListenerBinder.addBinding().to(extensionClass);
}
+ else if (RepositoryServiceResolver.class.isAssignableFrom(extensionClass))
+ {
+ if (logger.isInfoEnabled())
+ {
+ logger.info("bind RepositoryServiceResolver {}",
+ extensionClass.getName());
+ }
+
+ repositoryServiceResolverBinder.addBinding().to(extensionClass);
+ }
else
{
if (logger.isInfoEnabled())
diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java
index 8c9847746e..7d56eef7b4 100644
--- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java
+++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java
@@ -71,6 +71,7 @@ import sonia.scm.repository.RepositoryBrowserUtil;
import sonia.scm.repository.RepositoryDAO;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.repository.RepositoryProvider;
+import sonia.scm.repository.api.RepositoryServiceFactory;
import sonia.scm.repository.xml.XmlRepositoryDAO;
import sonia.scm.resources.DefaultResourceManager;
import sonia.scm.resources.DevelopmentResourceManager;
@@ -101,6 +102,7 @@ import sonia.scm.util.DebugServlet;
import sonia.scm.util.ScmConfigurationUtil;
import sonia.scm.web.cgi.CGIExecutorFactory;
import sonia.scm.web.cgi.DefaultCGIExecutorFactory;
+import sonia.scm.web.filter.LoggingFilter;
import sonia.scm.web.security.AdministrationContext;
import sonia.scm.web.security.ApiBasicAuthenticationFilter;
import sonia.scm.web.security.AuthenticationManager;
@@ -172,6 +174,9 @@ public class ScmServletModule extends ServletModule
/** Field description */
public static final String REST_PACKAGE = "sonia.scm.api.rest";
+ /** Field description */
+ public static final String SYSTEM_PROPERTY_DEBUG_HTTP = "scm.debug.http";
+
/** Field description */
public static final String[] PATTERN_STATIC_RESOURCES = new String[] {
PATTERN_SCRIPT,
@@ -299,6 +304,15 @@ public class ScmServletModule extends ServletModule
Names.named(UrlProviderFactory.TYPE_WUI)).toProvider(
WebUIUrlProvider.class);
+ // bind repository service factory
+ bind(RepositoryServiceFactory.class);
+
+ // bind debug logging filter
+ if ("true".equalsIgnoreCase(System.getProperty(SYSTEM_PROPERTY_DEBUG_HTTP)))
+ {
+ filter(PATTERN_ALL).through(LoggingFilter.class);
+ }
+
/*
* filter(PATTERN_PAGE,
* PATTERN_STATIC_RESOURCES).through(StaticResourceFilter.class);
diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/BrowserStreamingOutput.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/BrowserStreamingOutput.java
index c9f9f5f680..5b2dcfa50b 100644
--- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/BrowserStreamingOutput.java
+++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/BrowserStreamingOutput.java
@@ -39,9 +39,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.PathNotFoundException;
-import sonia.scm.repository.RepositoryBrowser;
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.RevisionNotFoundException;
+import sonia.scm.repository.api.CatCommandBuilder;
//~--- JDK imports ------------------------------------------------------------
@@ -71,13 +71,13 @@ public class BrowserStreamingOutput implements StreamingOutput
*
* @param browser
* @param revision
+ *
+ * @param builder
* @param path
*/
- public BrowserStreamingOutput(RepositoryBrowser browser, String revision,
- String path)
+ public BrowserStreamingOutput(CatCommandBuilder builder, String path)
{
- this.browser = browser;
- this.revision = revision;
+ this.builder = builder;
this.path = path;
}
@@ -98,7 +98,7 @@ public class BrowserStreamingOutput implements StreamingOutput
{
try
{
- browser.getContent(revision, path, output);
+ builder.retriveContent(output, path);
}
catch (PathNotFoundException ex)
{
@@ -130,11 +130,8 @@ public class BrowserStreamingOutput implements StreamingOutput
//~--- fields ---------------------------------------------------------------
/** Field description */
- private RepositoryBrowser browser;
+ private CatCommandBuilder builder;
/** Field description */
private String path;
-
- /** Field description */
- private String revision;
}
diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/DiffStreamingOutput.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/DiffStreamingOutput.java
index a8f7c93ef4..ad55889c0d 100644
--- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/DiffStreamingOutput.java
+++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/DiffStreamingOutput.java
@@ -38,10 +38,10 @@ package sonia.scm.api.rest.resources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import sonia.scm.repository.DiffViewer;
import sonia.scm.repository.PathNotFoundException;
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.RevisionNotFoundException;
+import sonia.scm.repository.api.DiffCommandBuilder;
//~--- JDK imports ------------------------------------------------------------
@@ -66,19 +66,14 @@ public class DiffStreamingOutput implements StreamingOutput
//~--- constructors ---------------------------------------------------------
/**
- * Constructs ...
+ * Constructs ...
*
*
- * @param diffViewer
- * @param revision
- * @param path
+ * @param builder
*/
- public DiffStreamingOutput(DiffViewer diffViewer, String revision,
- String path)
+ public DiffStreamingOutput(DiffCommandBuilder builder)
{
- this.diffViewer = diffViewer;
- this.revision = revision;
- this.path = path;
+ this.builder = builder;
}
//~--- methods --------------------------------------------------------------
@@ -98,7 +93,7 @@ public class DiffStreamingOutput implements StreamingOutput
{
try
{
- diffViewer.getDiff(revision, path, output);
+ builder.retriveContent(output);
}
catch (PathNotFoundException ex)
{
@@ -130,11 +125,5 @@ public class DiffStreamingOutput implements StreamingOutput
//~--- fields ---------------------------------------------------------------
/** Field description */
- private DiffViewer diffViewer;
-
- /** Field description */
- private String path;
-
- /** Field description */
- private String revision;
+ private DiffCommandBuilder builder;
}
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 8880bc6a70..9fa12d452c 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
@@ -35,6 +35,8 @@ package sonia.scm.api.rest.resources;
//~--- non-JDK imports --------------------------------------------------------
+import com.google.common.base.Strings;
+import com.google.common.io.Closeables;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@@ -45,30 +47,30 @@ import org.codehaus.enunciate.modules.jersey.ExternallyManagedLifecycle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import sonia.scm.NotSupportedFeatuerException;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.repository.BlameResult;
-import sonia.scm.repository.BlameViewerUtil;
import sonia.scm.repository.BrowserResult;
import sonia.scm.repository.Changeset;
import sonia.scm.repository.ChangesetPagingResult;
-import sonia.scm.repository.ChangesetViewerUtil;
-import sonia.scm.repository.DiffViewer;
import sonia.scm.repository.Permission;
import sonia.scm.repository.PermissionType;
import sonia.scm.repository.PermissionUtil;
import sonia.scm.repository.Repository;
-import sonia.scm.repository.RepositoryBrowser;
-import sonia.scm.repository.RepositoryBrowserUtil;
import sonia.scm.repository.RepositoryException;
-import sonia.scm.repository.RepositoryHandler;
import sonia.scm.repository.RepositoryIsNotArchivedException;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.repository.RepositoryNotFoundException;
import sonia.scm.repository.RepositoryUtil;
+import sonia.scm.repository.api.BlameCommandBuilder;
+import sonia.scm.repository.api.BrowseCommandBuilder;
+import sonia.scm.repository.api.CatCommandBuilder;
+import sonia.scm.repository.api.CommandNotSupportedException;
+import sonia.scm.repository.api.DiffCommandBuilder;
+import sonia.scm.repository.api.LogCommandBuilder;
+import sonia.scm.repository.api.RepositoryService;
+import sonia.scm.repository.api.RepositoryServiceFactory;
import sonia.scm.security.ScmSecurityException;
import sonia.scm.util.AssertUtil;
-import sonia.scm.util.HttpUtil;
import sonia.scm.util.Util;
import sonia.scm.web.security.WebSecurityContext;
@@ -125,6 +127,7 @@ public class RepositoryResource
* @param configuration
* @param repositoryManager
* @param securityContextProvider
+ * @param servicefactory
* @param changesetViewerUtil
* @param repositoryBrowserUtil
* @param blameViewerUtil
@@ -133,17 +136,13 @@ public class RepositoryResource
public RepositoryResource(
ScmConfiguration configuration, RepositoryManager repositoryManager,
Provider securityContextProvider,
- ChangesetViewerUtil changesetViewerUtil,
- RepositoryBrowserUtil repositoryBrowserUtil,
- BlameViewerUtil blameViewerUtil)
+ RepositoryServiceFactory servicefactory)
{
super(repositoryManager);
this.configuration = configuration;
this.repositoryManager = repositoryManager;
+ this.servicefactory = servicefactory;
this.securityContextProvider = securityContextProvider;
- this.changesetViewerUtil = changesetViewerUtil;
- this.repositoryBrowserUtil = repositoryBrowserUtil;
- this.blameViewerUtil = blameViewerUtil;
setDisableCache(false);
}
@@ -349,13 +348,21 @@ public class RepositoryResource
throws RepositoryException, IOException
{
Response response = null;
+ RepositoryService service = null;
try
{
AssertUtil.assertIsNotNull(path);
+ service = servicefactory.create(id);
- BlameResult blamePagingResult = blameViewerUtil.getBlame(id, revision,
- path);
+ BlameCommandBuilder builder = service.getBlameCommand();
+
+ if (!Strings.isNullOrEmpty(revision))
+ {
+ builder.setRevision(revision);
+ }
+
+ BlameResult blamePagingResult = builder.getBlameResult(path);
if (blamePagingResult != null)
{
@@ -374,10 +381,14 @@ public class RepositoryResource
{
response = Response.status(Response.Status.NOT_FOUND).build();
}
- catch (NotSupportedFeatuerException ex)
+ catch (CommandNotSupportedException ex)
{
response = Response.status(Response.Status.BAD_REQUEST).build();
}
+ finally
+ {
+ Closeables.closeQuietly(service);
+ }
return response;
}
@@ -413,11 +424,25 @@ public class RepositoryResource
throws RepositoryException, IOException
{
Response response = null;
+ RepositoryService service = null;
try
{
- BrowserResult result = repositoryBrowserUtil.getResult(id, revision,
- path);
+ service = servicefactory.create(id);
+
+ BrowseCommandBuilder builder = service.getBrowseCommand();
+
+ if (!Strings.isNullOrEmpty(revision))
+ {
+ builder.setRevision(revision);
+ }
+
+ if (!Strings.isNullOrEmpty(path))
+ {
+ builder.setPath(path);
+ }
+
+ BrowserResult result = builder.getBrowserResult();
if (result != null)
{
@@ -432,10 +457,14 @@ public class RepositoryResource
{
response = Response.status(Response.Status.NOT_FOUND).build();
}
- catch (NotSupportedFeatuerException ex)
+ catch (CommandNotSupportedException ex)
{
response = Response.status(Response.Status.BAD_REQUEST).build();
}
+ finally
+ {
+ Closeables.closeQuietly(service);
+ }
return response;
}
@@ -511,9 +540,13 @@ public class RepositoryResource
if (Util.isNotEmpty(id) && Util.isNotEmpty(revision))
{
+ RepositoryService service = null;
+
try
{
- Changeset changeset = changesetViewerUtil.getChangeset(id, revision);
+ service = servicefactory.create(id);
+
+ Changeset changeset = service.getLogCommand().getChangeset(revision);
if (changeset != null)
{
@@ -528,10 +561,14 @@ public class RepositoryResource
{
response = Response.status(Response.Status.NOT_FOUND).build();
}
- catch (NotSupportedFeatuerException ex)
+ catch (CommandNotSupportedException ex)
{
response = Response.status(Response.Status.BAD_REQUEST).build();
}
+ finally
+ {
+ Closeables.closeQuietly(service);
+ }
}
else
{
@@ -581,21 +618,29 @@ public class RepositoryResource
@QueryParam("limit") int limit) throws RepositoryException, IOException
{
Response response = null;
+ RepositoryService service = null;
try
{
ChangesetPagingResult changesets = null;
- if (Util.isEmpty(path))
+ service = servicefactory.create(id);
+
+ LogCommandBuilder builder = service.getLogCommand();
+
+ if (!Strings.isNullOrEmpty(path))
{
- changesets = changesetViewerUtil.getChangesets(id, start, limit);
+ builder.setPath(path);
}
- else
+
+ if (!Strings.isNullOrEmpty(revision))
{
- changesets = changesetViewerUtil.getChangesets(id, path, revision,
- start, limit);
+ builder.setStartChangeset(revision);
}
+ changesets =
+ builder.setPagingStart(start).setPagingLimit(limit).getChangesets();
+
if (changesets != null)
{
response = Response.ok(changesets).build();
@@ -609,10 +654,14 @@ public class RepositoryResource
{
response = Response.status(Response.Status.NOT_FOUND).build();
}
- catch (NotSupportedFeatuerException ex)
+ catch (CommandNotSupportedException ex)
{
response = Response.status(Response.Status.BAD_REQUEST).build();
}
+ finally
+ {
+ Closeables.closeQuietly(service);
+ }
return response;
}
@@ -645,37 +694,43 @@ public class RepositoryResource
{
Response response = null;
StreamingOutput output = null;
- Repository repository = repositoryManager.get(id);
+ RepositoryService service = null;
- if (repository != null)
+ try
{
- try
+ service = servicefactory.create(id);
+
+ CatCommandBuilder builder = service.getCatCommand();
+
+ if (!Strings.isNullOrEmpty(revision))
{
- RepositoryBrowser browser =
- repositoryManager.getRepositoryBrowser(repository);
-
- if (browser != null)
- {
- output = new BrowserStreamingOutput(browser, revision, path);
-
- String contentDispositionName =
- getContentDispositionNameFromPath(path);
-
- response = Response.ok(output).header("Content-Disposition",
- contentDispositionName).build();
- }
- else if (logger.isWarnEnabled())
- {
- logger.warn("could not find repository browser for respository {}",
- repository.getId());
- response = Response.status(Response.Status.NOT_FOUND).build();
- }
- }
- catch (Exception ex)
- {
- logger.error("could not retrive content", ex);
- response = createErrorResonse(ex);
+ builder.setRevision(revision);
}
+
+ output = new BrowserStreamingOutput(builder, path);
+
+ String contentDispositionName = getContentDispositionNameFromPath(path);
+
+ response = Response.ok(output).header("Content-Disposition",
+ contentDispositionName).build();
+ }
+ catch (RepositoryNotFoundException ex)
+ {
+ logger.warn("could not find repository browser for respository {}", id);
+ response = Response.status(Response.Status.NOT_FOUND).build();
+ }
+ catch (CommandNotSupportedException ex)
+ {
+ response = Response.status(Response.Status.BAD_REQUEST).build();
+ }
+ catch (Exception ex)
+ {
+ logger.error("could not retrive content", ex);
+ response = createErrorResonse(ex);
+ }
+ finally
+ {
+ Closeables.closeQuietly(service);
}
return response;
@@ -714,36 +769,49 @@ public class RepositoryResource
AssertUtil.assertIsNotEmpty(id);
AssertUtil.assertIsNotEmpty(revision);
+ RepositoryService service = null;
Response response = null;
try
{
- Repository repository = repositoryManager.get(id);
+ service = servicefactory.create(id);
- if (repository != null)
+ DiffCommandBuilder builder = service.getDiffCommand();
+
+ if (!Strings.isNullOrEmpty(revision))
{
- DiffViewer diffViewer = repositoryManager.getDiffViewer(repository);
-
- if (diffViewer != null)
- {
- String name =
- repository.getName().concat("-").concat(revision).concat(".diff");
- String contentDispositionName = getContentDispositionName(name);
-
- response = Response.ok(new DiffStreamingOutput(diffViewer, revision,
- path)).header("Content-Disposition",
- contentDispositionName).build();
- }
- else
- {
- response = Response.status(Response.Status.NOT_FOUND).build();
- }
+ builder.setRevision(revision);
}
+
+ if (!Strings.isNullOrEmpty(path))
+ {
+ builder.setPath(path);
+ }
+
+ String name = service.getRepository().getName().concat("-").concat(
+ revision).concat(".diff");
+ String contentDispositionName = getContentDispositionName(name);
+
+ response = Response.ok(new DiffStreamingOutput(builder)).header(
+ "Content-Disposition", contentDispositionName).build();
}
catch (RepositoryNotFoundException ex)
{
response = Response.status(Response.Status.NOT_FOUND).build();
}
+ catch (CommandNotSupportedException ex)
+ {
+ response = Response.status(Response.Status.BAD_REQUEST).build();
+ }
+ catch (Exception ex)
+ {
+ logger.error("could not create diff", ex);
+ response = createErrorResonse(ex);
+ }
+ finally
+ {
+ Closeables.closeQuietly(service);
+ }
return response;
}
@@ -909,21 +977,15 @@ public class RepositoryResource
//~--- fields ---------------------------------------------------------------
- /** Field description */
- private BlameViewerUtil blameViewerUtil;
-
- /** Field description */
- private ChangesetViewerUtil changesetViewerUtil;
-
/** Field description */
private ScmConfiguration configuration;
- /** Field description */
- private RepositoryBrowserUtil repositoryBrowserUtil;
-
/** Field description */
private RepositoryManager repositoryManager;
/** Field description */
private Provider securityContextProvider;
+
+ /** Field description */
+ private RepositoryServiceFactory servicefactory;
}
diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java
index 9a11e74a6f..cc2b903ff3 100644
--- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java
+++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryRootResource.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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.api.rest.resources;
//~--- non-JDK imports --------------------------------------------------------
@@ -42,7 +43,6 @@ import com.google.inject.Inject;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.repository.RepositoryTypePredicate;
-import sonia.scm.repository.RepositoryUtil;
import sonia.scm.template.TemplateHandler;
import sonia.scm.url.UrlProvider;
import sonia.scm.url.UrlProviderFactory;
@@ -116,15 +116,15 @@ public class RepositoryRootResource
@PathParam("type") final String type)
throws IOException
{
- UrlProvider uiUrlProvider =
- UrlProviderFactory.createUrlProvider(HttpUtil.getCompleteUrl(request),
- UrlProviderFactory.TYPE_WUI);
+ String baseUrl = HttpUtil.getCompleteUrl(request);
+ UrlProvider uiUrlProvider = UrlProviderFactory.createUrlProvider(baseUrl,
+ UrlProviderFactory.TYPE_WUI);
//J-
Collection unsortedRepositories =
Collections2.transform(
Collections2.filter(
repositoryManager.getAll(), new RepositoryTypePredicate(type))
- , new RepositoryTransformFunction(request, repositoryManager, uiUrlProvider)
+ , new RepositoryTransformFunction(uiUrlProvider, baseUrl)
);
List repositories = Ordering.from(
@@ -160,12 +160,14 @@ public class RepositoryRootResource
*
* @param repository
* @param uiUrlProvider
+ * @param baseUrl
*/
public RepositoryTemplateElement(Repository repository,
- UrlProvider uiUrlProvider)
+ UrlProvider uiUrlProvider, String baseUrl)
{
this.repository = repository;
this.urlProvider = uiUrlProvider;
+ this.baseUrl = baseUrl;
}
//~--- get methods --------------------------------------------------------
@@ -236,11 +238,14 @@ public class RepositoryRootResource
*/
public String getUrl()
{
- return repository.getUrl();
+ return repository.createUrl(baseUrl);
}
//~--- fields -------------------------------------------------------------
+ /** Field description */
+ private String baseUrl;
+
/** Field description */
private Repository repository;
@@ -298,14 +303,12 @@ public class RepositoryRootResource
* @param request
* @param repositoryManager
* @param urlProvider
+ * @param baseUrl
*/
- public RepositoryTransformFunction(HttpServletRequest request,
- RepositoryManager repositoryManager,
- UrlProvider urlProvider)
+ public RepositoryTransformFunction(UrlProvider urlProvider, String baseUrl)
{
- this.request = request;
- this.repositoryManager = repositoryManager;
this.urlProvider = urlProvider;
+ this.baseUrl = baseUrl;
}
//~--- methods ------------------------------------------------------------
@@ -321,18 +324,13 @@ public class RepositoryRootResource
@Override
public RepositoryTemplateElement apply(Repository repository)
{
- RepositoryUtil.appendUrl(request, repositoryManager, repository);
-
- return new RepositoryTemplateElement(repository, urlProvider);
+ return new RepositoryTemplateElement(repository, urlProvider, baseUrl);
}
//~--- fields -------------------------------------------------------------
/** Field description */
- private RepositoryManager repositoryManager;
-
- /** Field description */
- private HttpServletRequest request;
+ private String baseUrl;
/** Field description */
private UrlProvider urlProvider;
diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/SupportResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/SupportResource.java
index b7a85d8c13..0fac1a6591 100644
--- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/SupportResource.java
+++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/SupportResource.java
@@ -1,27 +1,29 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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
*
@@ -38,8 +40,11 @@ import com.google.common.collect.Maps;
import com.google.inject.Inject;
import sonia.scm.SCMContextProvider;
+import sonia.scm.Type;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.plugin.PluginManager;
+import sonia.scm.repository.RepositoryHandler;
+import sonia.scm.repository.RepositoryManager;
import sonia.scm.store.StoreFactory;
import sonia.scm.template.TemplateHandler;
import sonia.scm.util.SecurityUtil;
@@ -50,18 +55,17 @@ import sonia.scm.web.security.WebSecurityContext;
import java.io.IOException;
import java.io.StringWriter;
+
import java.util.Collection;
import java.util.List;
-
+import java.util.Locale;
import java.util.Map;
+import java.util.TimeZone;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
-import sonia.scm.Type;
-import sonia.scm.repository.RepositoryHandler;
-import sonia.scm.repository.RepositoryManager;
/**
*
@@ -87,13 +91,16 @@ public class SupportResource
* @param configuration
* @param pluginManager
* @param storeFactory
+ * @param repositoryManager
*/
@Inject
public SupportResource(WebSecurityContext securityContext,
SCMContextProvider context,
TemplateHandler templateHandler,
ScmConfiguration configuration,
- PluginManager pluginManager, StoreFactory storeFactory, RepositoryManager repositoryManager )
+ PluginManager pluginManager,
+ StoreFactory storeFactory,
+ RepositoryManager repositoryManager)
{
this.securityContext = securityContext;
this.context = context;
@@ -104,8 +111,6 @@ public class SupportResource
this.repositoryManager = repositoryManager;
}
- private RepositoryManager repositoryManager;
-
//~--- get methods ----------------------------------------------------------
/**
@@ -138,15 +143,21 @@ public class SupportResource
return writer.toString();
}
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
private List getRepositoryHandlers()
{
List handlers = Lists.newArrayList();
-
- for ( Type type : repositoryManager.getConfiguredTypes() )
+
+ for (Type type : repositoryManager.getConfiguredTypes())
{
- handlers.add( repositoryManager.getHandler(type.getName()) );
+ handlers.add(repositoryManager.getHandler(type.getName()));
}
-
+
return handlers;
}
@@ -259,6 +270,8 @@ public class SupportResource
container = SystemUtil.getServletContainer().name();
java = System.getProperty("java.vendor").concat("/").concat(
System.getProperty("java.version"));
+ locale = Locale.getDefault().toString();
+ timeZone = TimeZone.getDefault().getID();
}
//~--- get methods --------------------------------------------------------
@@ -296,6 +309,17 @@ public class SupportResource
return java;
}
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public String getLocale()
+ {
+ return locale;
+ }
+
/**
* Method description
*
@@ -307,6 +331,17 @@ public class SupportResource
return os;
}
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public String getTimeZone()
+ {
+ return timeZone;
+ }
+
//~--- fields -------------------------------------------------------------
/** Field description */
@@ -318,8 +353,14 @@ public class SupportResource
/** Field description */
private String java;
+ /** Field description */
+ private String locale;
+
/** Field description */
private String os;
+
+ /** Field description */
+ private String timeZone;
}
@@ -407,6 +448,9 @@ public class SupportResource
/** Field description */
private PluginManager pluginManager;
+ /** Field description */
+ private RepositoryManager repositoryManager;
+
/** Field description */
private WebSecurityContext securityContext;
diff --git a/scm-webapp/src/main/java/sonia/scm/boot/BootstrapListener.java b/scm-webapp/src/main/java/sonia/scm/boot/BootstrapListener.java
index c6f45f2bc3..6794e2aa98 100644
--- a/scm-webapp/src/main/java/sonia/scm/boot/BootstrapListener.java
+++ b/scm-webapp/src/main/java/sonia/scm/boot/BootstrapListener.java
@@ -39,6 +39,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.SCMContext;
+import sonia.scm.SCMContextProvider;
//~--- JDK imports ------------------------------------------------------------
@@ -102,14 +103,16 @@ public class BootstrapListener implements ServletContextListener
@Override
public void contextInitialized(ServletContextEvent sce)
{
+ SCMContextProvider context = SCMContext.getContext();
+
if (logger.isInfoEnabled())
{
- logger.info("start scm-manager in stage: {}",
- SCMContext.getContext().getStage());
+ logger.info("start scm-manager {} in stage: {}", context.getVersion(),
+ context.getStage());
}
ClassLoader classLoader = null;
- File pluginDirectory = new File(SCMContext.getContext().getBaseDirectory(),
+ File pluginDirectory = new File(context.getBaseDirectory(),
PLUGIN_DIRECTORY);
if (pluginDirectory.exists())
diff --git a/scm-webapp/src/main/java/sonia/scm/net/TrustAllHostnameVerifier.java b/scm-webapp/src/main/java/sonia/scm/net/TrustAllHostnameVerifier.java
new file mode 100644
index 0000000000..2ffd2f4676
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/net/TrustAllHostnameVerifier.java
@@ -0,0 +1,61 @@
+/**
+ * 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.net;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSession;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class TrustAllHostnameVerifier implements HostnameVerifier
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param hostname
+ * @param session
+ *
+ * @return
+ */
+ @Override
+ public boolean verify(String hostname, SSLSession session)
+ {
+ return true;
+ }
+}
diff --git a/scm-webapp/src/main/java/sonia/scm/net/TrustAllTrustManager.java b/scm-webapp/src/main/java/sonia/scm/net/TrustAllTrustManager.java
new file mode 100644
index 0000000000..e4d73aed31
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/net/TrustAllTrustManager.java
@@ -0,0 +1,88 @@
+/**
+ * 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.net;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.X509TrustManager;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class TrustAllTrustManager implements X509TrustManager
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param chain
+ * @param authType
+ *
+ * @throws CertificateException
+ */
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {}
+
+ /**
+ * Method description
+ *
+ *
+ * @param chain
+ * @param authType
+ *
+ * @throws CertificateException
+ */
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {}
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public X509Certificate[] getAcceptedIssuers()
+ {
+ return null;
+ }
+}
diff --git a/scm-webapp/src/main/java/sonia/scm/net/URLHttpClient.java b/scm-webapp/src/main/java/sonia/scm/net/URLHttpClient.java
index 3fecc05d91..c2a38223d5 100644
--- a/scm-webapp/src/main/java/sonia/scm/net/URLHttpClient.java
+++ b/scm-webapp/src/main/java/sonia/scm/net/URLHttpClient.java
@@ -64,6 +64,10 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+
/**
*
* @author Sebastian Sdorra
@@ -383,6 +387,49 @@ public class URLHttpClient implements HttpClient
}
}
+ /**
+ * Method description
+ *
+ *
+ * @param request
+ * @param connection
+ */
+ private void applySSLSettings(HttpRequest request,
+ HttpsURLConnection connection)
+ {
+ if (request.isDisableCertificateValidation())
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("disable certificate validation");
+ }
+
+ try
+ {
+ TrustManager[] trustAllCerts = new TrustManager[] {
+ new TrustAllTrustManager() };
+ SSLContext sc = SSLContext.getInstance("SSL");
+
+ sc.init(null, trustAllCerts, new java.security.SecureRandom());
+ connection.setSSLSocketFactory(sc.getSocketFactory());
+ }
+ catch (Exception ex)
+ {
+ logger.error("could not disable certificate validation", ex);
+ }
+ }
+
+ if (request.isDisableHostnameValidation())
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("disable hostname validation");
+ }
+
+ connection.setHostnameVerifier(new TrustAllHostnameVerifier());
+ }
+ }
+
/**
* Method description
*
@@ -484,9 +531,15 @@ public class URLHttpClient implements HttpClient
private HttpURLConnection openConnection(HttpRequest request, URL url)
throws IOException
{
+ if (request == null)
+ {
+ // TODO improve
+ request = new HttpRequest(url.toExternalForm());
+ }
+
HttpURLConnection connection = null;
- if (configuration.isEnableProxy())
+ if (!request.isIgnoreProxySettings() && configuration.isEnableProxy())
{
if (logger.isDebugEnabled())
{
@@ -506,6 +559,11 @@ public class URLHttpClient implements HttpClient
}
else
{
+ if (request.isIgnoreProxySettings() && logger.isTraceEnabled())
+ {
+ logger.trace("ignore proxy settings");
+ }
+
if (logger.isDebugEnabled())
{
logger.debug("fetch '{}'", url.toExternalForm());
@@ -514,6 +572,11 @@ public class URLHttpClient implements HttpClient
connection = (HttpURLConnection) url.openConnection();
}
+ if (connection instanceof HttpsURLConnection)
+ {
+ applySSLSettings(request, (HttpsURLConnection) connection);
+ }
+
connection.setReadTimeout(TIMEOUT_RAED);
connection.setConnectTimeout(TIMEOUT_CONNECTION);
diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/DefaultProxySelector.java b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultProxySelector.java
index 616b5b9308..fd3ad16507 100644
--- a/scm-webapp/src/main/java/sonia/scm/plugin/DefaultProxySelector.java
+++ b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultProxySelector.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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.plugin;
//~--- non-JDK imports --------------------------------------------------------
diff --git a/scm-webapp/src/main/java/sonia/scm/web/cgi/DefaultCGIStatusCodeHandler.java b/scm-webapp/src/main/java/sonia/scm/web/cgi/DefaultCGIStatusCodeHandler.java
index 3d5eee88cd..91531d9838 100644
--- a/scm-webapp/src/main/java/sonia/scm/web/cgi/DefaultCGIStatusCodeHandler.java
+++ b/scm-webapp/src/main/java/sonia/scm/web/cgi/DefaultCGIStatusCodeHandler.java
@@ -1,34 +1,35 @@
/**
- * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ * 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 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.
+ * 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.cgi;
//~--- non-JDK imports --------------------------------------------------------
diff --git a/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java b/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java
index f17bb67494..cf1c78f97c 100644
--- a/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java
+++ b/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java
@@ -124,9 +124,16 @@ public class BasicSecurityContext implements WebSecurityContext
HttpServletResponse response, String username,
String password)
{
+ if ( logger.isTraceEnabled() ){
+ logger.trace("start authentication for user {}", username);
+ }
AuthenticationResult ar = authenticator.authenticate(request, response,
username, password);
+ if ( logger.isTraceEnabled() ){
+ logger.trace("authentication ends with {}", ar);
+ }
+
if ((ar != null) && (ar.getState() == AuthenticationState.SUCCESS))
{
authenticate(request, password, ar);
diff --git a/scm-webapp/src/main/java/sonia/scm/web/security/ChainAuthenticatonManager.java b/scm-webapp/src/main/java/sonia/scm/web/security/ChainAuthenticatonManager.java
index fcdb2a4d06..2f51ef6cfe 100644
--- a/scm-webapp/src/main/java/sonia/scm/web/security/ChainAuthenticatonManager.java
+++ b/scm-webapp/src/main/java/sonia/scm/web/security/ChainAuthenticatonManager.java
@@ -130,6 +130,12 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
if (ar == null)
{
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("no authentication result for user {} found in cache",
+ username);
+ }
+
ar = doAuthentication(request, response, username, password);
if ((ar != null) && ar.isCacheable())
@@ -157,6 +163,11 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
{
for (AuthenticationHandler authenticator : authenticationHandlerSet)
{
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("close authenticator {}", authenticator.getClass());
+ }
+
IOUtil.close(authenticator);
}
}
@@ -172,6 +183,11 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
{
for (AuthenticationHandler authenticator : authenticationHandlerSet)
{
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("initialize authenticator {}", authenticator.getClass());
+ }
+
authenticator.init(context);
}
@@ -200,8 +216,19 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
{
AuthenticationResult ar = null;
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("start authentication chain for user {}", username);
+ }
+
for (AuthenticationHandler authenticator : authenticationHandlerSet)
{
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("check authenticator {} for user {}",
+ authenticator.getClass(), username);
+ }
+
try
{
AuthenticationResult result = authenticator.authenticate(request,
diff --git a/scm-webapp/src/main/resources/config/ehcache.xml b/scm-webapp/src/main/resources/config/ehcache.xml
index 5e144a653c..beb3b7f862 100644
--- a/scm-webapp/src/main/resources/config/ehcache.xml
+++ b/scm-webapp/src/main/resources/config/ehcache.xml
@@ -161,4 +161,36 @@
diskPersistent="false"
/>
+
+
+
+
+
+
+
+
diff --git a/scm-webapp/src/main/resources/templates/support.html b/scm-webapp/src/main/resources/templates/support.html
index bd34ad2c1c..f22f902d9a 100644
--- a/scm-webapp/src/main/resources/templates/support.html
+++ b/scm-webapp/src/main/resources/templates/support.html
@@ -134,6 +134,8 @@