aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.http.test
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit.http.test')
-rw-r--r--org.eclipse.jgit.http.test/.settings/org.eclipse.jdt.ui.prefs13
-rw-r--r--org.eclipse.jgit.http.test/.settings/org.eclipse.pde.api.tools.prefs12
-rw-r--r--org.eclipse.jgit.http.test/BUILD1
-rw-r--r--org.eclipse.jgit.http.test/META-INF/MANIFEST.MF42
-rw-r--r--org.eclipse.jgit.http.test/pom.xml12
-rw-r--r--org.eclipse.jgit.http.test/src/org/eclipse/jgit/http/test/TestRepositoryResolver.java85
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java21
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java341
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java640
9 files changed, 1075 insertions, 92 deletions
diff --git a/org.eclipse.jgit.http.test/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.jgit.http.test/.settings/org.eclipse.jdt.ui.prefs
index c336cce6ed..fef3713825 100644
--- a/org.eclipse.jgit.http.test/.settings/org.eclipse.jdt.ui.prefs
+++ b/org.eclipse.jgit.http.test/.settings/org.eclipse.jdt.ui.prefs
@@ -9,21 +9,23 @@ org.eclipse.jdt.ui.staticondemandthreshold=99
org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/>
sp_cleanup.add_default_serial_version_id=true
sp_cleanup.add_generated_serial_version_id=false
-sp_cleanup.add_missing_annotations=false
+sp_cleanup.add_missing_annotations=true
sp_cleanup.add_missing_deprecated_annotations=true
sp_cleanup.add_missing_methods=false
sp_cleanup.add_missing_nls_tags=false
sp_cleanup.add_missing_override_annotations=true
-sp_cleanup.add_missing_override_annotations_interface_methods=false
+sp_cleanup.add_missing_override_annotations_interface_methods=true
sp_cleanup.add_serial_version_id=false
sp_cleanup.always_use_blocks=true
sp_cleanup.always_use_parentheses_in_expressions=false
sp_cleanup.always_use_this_for_non_static_field_access=false
sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_functional_interfaces=false
sp_cleanup.convert_to_enhanced_for_loop=false
sp_cleanup.correct_indentation=false
sp_cleanup.format_source_code=true
sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.insert_inferred_type_arguments=false
sp_cleanup.make_local_variable_final=false
sp_cleanup.make_parameters_final=false
sp_cleanup.make_private_fields_final=true
@@ -39,11 +41,12 @@ sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_type_arguments=true
sp_cleanup.remove_trailing_whitespaces=true
sp_cleanup.remove_trailing_whitespaces_all=true
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
-sp_cleanup.remove_unnecessary_casts=false
-sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
sp_cleanup.remove_unused_imports=false
sp_cleanup.remove_unused_local_variables=false
sp_cleanup.remove_unused_private_fields=true
@@ -52,8 +55,10 @@ sp_cleanup.remove_unused_private_methods=true
sp_cleanup.remove_unused_private_types=true
sp_cleanup.sort_members=false
sp_cleanup.sort_members_all=false
+sp_cleanup.use_anonymous_class_creation=false
sp_cleanup.use_blocks=false
sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=false
sp_cleanup.use_parentheses_in_expressions=false
sp_cleanup.use_this_for_non_static_field_access=false
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
diff --git a/org.eclipse.jgit.http.test/.settings/org.eclipse.pde.api.tools.prefs b/org.eclipse.jgit.http.test/.settings/org.eclipse.pde.api.tools.prefs
index cd148d9049..c0030ded71 100644
--- a/org.eclipse.jgit.http.test/.settings/org.eclipse.pde.api.tools.prefs
+++ b/org.eclipse.jgit.http.test/.settings/org.eclipse.pde.api.tools.prefs
@@ -1,4 +1,4 @@
-#Tue Oct 18 00:52:01 CEST 2011
+ANNOTATION_ELEMENT_TYPE_ADDED_FIELD=Error
ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
@@ -8,6 +8,10 @@ API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error
API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error
API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
+API_USE_SCAN_FIELD_SEVERITY=Error
+API_USE_SCAN_METHOD_SEVERITY=Error
+API_USE_SCAN_TYPE_SEVERITY=Error
+CLASS_ELEMENT_TYPE_ADDED_FIELD=Error
CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
@@ -47,6 +51,7 @@ ILLEGAL_IMPLEMENT=Warning
ILLEGAL_INSTANTIATE=Warning
ILLEGAL_OVERRIDE=Warning
ILLEGAL_REFERENCE=Warning
+INTERFACE_ELEMENT_TYPE_ADDED_DEFAULT_METHOD=Error
INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
@@ -58,6 +63,7 @@ INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error
INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+INVALID_ANNOTATION=Ignore
INVALID_JAVADOC_TAG=Ignore
INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Error
LEAK_EXTEND=Warning
@@ -75,6 +81,7 @@ METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+MISSING_EE_DESCRIPTIONS=Warning
TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
@@ -83,10 +90,13 @@ TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
UNUSED_PROBLEM_FILTERS=Warning
automatically_removed_unused_problem_filters=false
+changed_execution_env=Error
eclipse.preferences.version=1
incompatible_api_component_version=Error
incompatible_api_component_version_include_major_without_breaking_change=Disabled
incompatible_api_component_version_include_minor_without_api_change=Disabled
+incompatible_api_component_version_report_major_without_breaking_change=Warning
+incompatible_api_component_version_report_minor_without_api_change=Ignore
invalid_since_tag_version=Error
malformed_since_tag=Error
missing_since_tag=Error
diff --git a/org.eclipse.jgit.http.test/BUILD b/org.eclipse.jgit.http.test/BUILD
index ce2d6112f1..85a22422be 100644
--- a/org.eclipse.jgit.http.test/BUILD
+++ b/org.eclipse.jgit.http.test/BUILD
@@ -34,6 +34,7 @@ java_library(
srcs = glob(["src/**/*.java"]),
deps = [
"//lib:junit",
+ "//lib:servlet-api",
"//org.eclipse.jgit.http.server:jgit-servlet",
"//org.eclipse.jgit:jgit",
"//org.eclipse.jgit.junit.http:junit-http",
diff --git a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
index 811585ec69..442c4ec45c 100644
--- a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
@@ -2,12 +2,14 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %plugin_name
Bundle-SymbolicName: org.eclipse.jgit.http.test
-Bundle-Version: 4.8.1.qualifier
+Bundle-Version: 4.9.10.qualifier
Bundle-Vendor: %provider_name
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: javax.servlet;version="[2.5.0,3.2.0)",
javax.servlet.http;version="[2.5.0,3.2.0)",
+ org.apache.commons.codec;version="[1.6.0,2.0.0)",
+ org.apache.commons.codec.binary;version="[1.6.0,2.0.0)",
org.eclipse.jetty.continuation;version="[9.4.5,10.0.0)",
org.eclipse.jetty.http;version="[9.4.5,10.0.0)",
org.eclipse.jetty.io;version="[9.4.5,10.0.0)",
@@ -22,25 +24,27 @@ Import-Package: javax.servlet;version="[2.5.0,3.2.0)",
org.eclipse.jetty.util.log;version="[9.4.5,10.0.0)",
org.eclipse.jetty.util.security;version="[9.4.5,10.0.0)",
org.eclipse.jetty.util.thread;version="[9.4.5,10.0.0)",
- org.eclipse.jgit.errors;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.http.server;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.http.server.glue;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.http.server.resolver;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.internal;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.internal.storage.file;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.junit;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.junit.http;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.lib;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.nls;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.revwalk;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.storage.file;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.transport;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.transport.http;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.transport.http.apache;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.transport.resolver;version="[4.8.1,4.9.0)",
- org.eclipse.jgit.util;version="[4.8.1,4.9.0)",
+ org.eclipse.jgit.errors;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.http.server;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.http.server.glue;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.http.server.resolver;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.internal;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.internal.storage.file;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.junit;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.junit.http;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.lib;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.nls;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.revwalk;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.storage.file;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.transport;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.transport.http;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.transport.http.apache;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.transport.resolver;version="[4.9.10,4.10.0)",
+ org.eclipse.jgit.util;version="[4.9.10,4.10.0)",
org.hamcrest.core;version="[1.1.0,2.0.0)",
org.junit;version="[4.0.0,5.0.0)",
+ org.junit.rules;version="[4.0.0,5.0.0)",
org.junit.runner;version="[4.0.0,5.0.0)",
org.junit.runners;version="[4.0.0,5.0.0)"
+Require-Bundle: org.hamcrest.library;bundle-version="[1.1.0,2.0.0)"
diff --git a/org.eclipse.jgit.http.test/pom.xml b/org.eclipse.jgit.http.test/pom.xml
index 1538601cce..c76368153c 100644
--- a/org.eclipse.jgit.http.test/pom.xml
+++ b/org.eclipse.jgit.http.test/pom.xml
@@ -51,7 +51,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>4.8.1-SNAPSHOT</version>
+ <version>4.9.10-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.http.test</artifactId>
@@ -71,6 +71,13 @@
</dependency>
<dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ <version>[1.1.0,2.0.0)</version>
+ </dependency>
+
+ <dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>${project.version}</version>
@@ -87,14 +94,12 @@
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.junit.http</artifactId>
<version>${project.version}</version>
- <scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.junit</artifactId>
<version>${project.version}</version>
- <scope>test</scope>
</dependency>
<dependency>
@@ -107,7 +112,6 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
- <scope>test</scope>
</dependency>
</dependencies>
diff --git a/org.eclipse.jgit.http.test/src/org/eclipse/jgit/http/test/TestRepositoryResolver.java b/org.eclipse.jgit.http.test/src/org/eclipse/jgit/http/test/TestRepositoryResolver.java
new file mode 100644
index 0000000000..334e57c6d1
--- /dev/null
+++ b/org.eclipse.jgit.http.test/src/org/eclipse/jgit/http/test/TestRepositoryResolver.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016, 2017 Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. 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 COPYRIGHT OWNER 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.
+ */
+package org.eclipse.jgit.http.test;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.transport.resolver.RepositoryResolver;
+import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
+
+/** A simple repository resolver for tests. */
+public final class TestRepositoryResolver
+ implements RepositoryResolver<HttpServletRequest> {
+
+ private final TestRepository<Repository> repo;
+
+ private final String repoName;
+
+ /**
+ * Creates a new {@link TestRepositoryResolver} that resolves the given name to
+ * the given repository.
+ *
+ * @param repo
+ * to resolve to
+ * @param repoName
+ * to match
+ */
+ public TestRepositoryResolver(TestRepository<Repository> repo, String repoName) {
+ this.repo = repo;
+ this.repoName = repoName;
+ }
+
+ @Override
+ public Repository open(HttpServletRequest req, String name)
+ throws RepositoryNotFoundException, ServiceNotEnabledException {
+ if (!name.equals(repoName)) {
+ throw new RepositoryNotFoundException(name);
+ }
+ Repository db = repo.getRepository();
+ db.incrementOpen();
+ return db;
+ }
+}
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
index 06bfd7988b..727f9bab00 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010, Google Inc.
+ * Copyright (C) 2010, 2017 Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
@@ -60,12 +60,9 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
-import javax.servlet.http.HttpServletRequest;
-
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jgit.errors.NotSupportedException;
-import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.http.server.GitServlet;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.junit.http.AccessEvent;
@@ -84,8 +81,6 @@ import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.http.HttpConnectionFactory;
import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory;
import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory;
-import org.eclipse.jgit.transport.resolver.RepositoryResolver;
-import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -124,19 +119,7 @@ public class DumbClientSmartServerTest extends HttpTestCase {
ServletContextHandler app = server.addContext("/git");
GitServlet gs = new GitServlet();
- gs.setRepositoryResolver(new RepositoryResolver<HttpServletRequest>() {
- @Override
- public Repository open(HttpServletRequest req, String name)
- throws RepositoryNotFoundException,
- ServiceNotEnabledException {
- if (!name.equals(srcName))
- throw new RepositoryNotFoundException(name);
-
- final Repository db = src.getRepository();
- db.incrementOpen();
- return db;
- }
- });
+ gs.setRepositoryResolver(new TestRepositoryResolver(src, srcName));
app.addServlet(new ServletHolder(gs), "/*");
server.setUp();
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java
new file mode 100644
index 0000000000..7deb0d85a0
--- /dev/null
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2017 Thomas Wolf <thomas.wolf@paranor.ch>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. 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 COPYRIGHT OWNER 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.
+ */
+
+package org.eclipse.jgit.http.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.List;
+
+import javax.servlet.DispatcherType;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.errors.UnsupportedCredentialItem;
+import org.eclipse.jgit.http.server.GitServlet;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.junit.http.AccessEvent;
+import org.eclipse.jgit.junit.http.AppServer;
+import org.eclipse.jgit.junit.http.HttpTestCase;
+import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevBlob;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.transport.CredentialItem;
+import org.eclipse.jgit.transport.CredentialsProvider;
+import org.eclipse.jgit.transport.HttpTransport;
+import org.eclipse.jgit.transport.Transport;
+import org.eclipse.jgit.transport.URIish;
+import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
+import org.eclipse.jgit.transport.http.HttpConnectionFactory;
+import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory;
+import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory;
+import org.eclipse.jgit.util.HttpSupport;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class SmartClientSmartServerSslTest extends HttpTestCase {
+
+ // We run these tests with a server on localhost with a self-signed
+ // certificate. We don't do authentication tests here, so there's no need
+ // for username and password.
+ //
+ // But the server certificate will not validate. We know that Transport will
+ // ask whether we trust the server all the same. This credentials provider
+ // blindly trusts the self-signed certificate by answering "Yes" to all
+ // questions.
+ private CredentialsProvider testCredentials = new CredentialsProvider() {
+
+ @Override
+ public boolean isInteractive() {
+ return false;
+ }
+
+ @Override
+ public boolean supports(CredentialItem... items) {
+ for (CredentialItem item : items) {
+ if (item instanceof CredentialItem.InformationalMessage) {
+ continue;
+ }
+ if (item instanceof CredentialItem.YesNoType) {
+ continue;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean get(URIish uri, CredentialItem... items)
+ throws UnsupportedCredentialItem {
+ for (CredentialItem item : items) {
+ if (item instanceof CredentialItem.InformationalMessage) {
+ continue;
+ }
+ if (item instanceof CredentialItem.YesNoType) {
+ ((CredentialItem.YesNoType) item).setValue(true);
+ continue;
+ }
+ return false;
+ }
+ return true;
+ }
+ };
+
+ private URIish remoteURI;
+
+ private URIish secureURI;
+
+ private RevBlob A_txt;
+
+ private RevCommit A, B;
+
+ @Parameters
+ public static Collection<Object[]> data() {
+ // run all tests with both connection factories we have
+ return Arrays.asList(new Object[][] {
+ { new JDKHttpConnectionFactory() },
+ { new HttpClientConnectionFactory() } });
+ }
+
+ public SmartClientSmartServerSslTest(HttpConnectionFactory cf) {
+ HttpTransport.setConnectionFactory(cf);
+ }
+
+ @Override
+ protected AppServer createServer() {
+ return new AppServer(0, 0);
+ }
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ final TestRepository<Repository> src = createTestRepository();
+ final String srcName = src.getRepository().getDirectory().getName();
+ src.getRepository()
+ .getConfig()
+ .setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, true);
+
+ GitServlet gs = new GitServlet();
+
+ ServletContextHandler app = addNormalContext(gs, src, srcName);
+
+ server.setUp();
+
+ remoteURI = toURIish(app, srcName);
+ secureURI = new URIish(rewriteUrl(remoteURI.toString(), "https",
+ server.getSecurePort()));
+
+ A_txt = src.blob("A");
+ A = src.commit().add("A_txt", A_txt).create();
+ B = src.commit().parent(A).add("A_txt", "C").add("B", "B").create();
+ src.update(master, B);
+
+ src.update("refs/garbage/a/very/long/ref/name/to/compress", B);
+ }
+
+ private ServletContextHandler addNormalContext(GitServlet gs, TestRepository<Repository> src, String srcName) {
+ ServletContextHandler app = server.addContext("/git");
+ app.addFilter(new FilterHolder(new Filter() {
+
+ @Override
+ public void init(FilterConfig filterConfig)
+ throws ServletException {
+ // empty
+ }
+
+ // Redirects http to https for requests containing "/https/".
+ @Override
+ public void doFilter(ServletRequest request,
+ ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
+ final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+ final StringBuffer fullUrl = httpServletRequest.getRequestURL();
+ if (httpServletRequest.getQueryString() != null) {
+ fullUrl.append("?")
+ .append(httpServletRequest.getQueryString());
+ }
+ String urlString = rewriteUrl(fullUrl.toString(), "https",
+ server.getSecurePort());
+ httpServletResponse
+ .setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
+ httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
+ urlString.replace("/https/", "/"));
+ }
+
+ @Override
+ public void destroy() {
+ // empty
+ }
+ }), "/https/*", EnumSet.of(DispatcherType.REQUEST));
+ app.addFilter(new FilterHolder(new Filter() {
+
+ @Override
+ public void init(FilterConfig filterConfig)
+ throws ServletException {
+ // empty
+ }
+
+ // Redirects https back to http for requests containing "/back/".
+ @Override
+ public void doFilter(ServletRequest request,
+ ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
+ final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+ final StringBuffer fullUrl = httpServletRequest.getRequestURL();
+ if (httpServletRequest.getQueryString() != null) {
+ fullUrl.append("?")
+ .append(httpServletRequest.getQueryString());
+ }
+ String urlString = rewriteUrl(fullUrl.toString(), "http",
+ server.getPort());
+ httpServletResponse
+ .setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
+ httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
+ urlString.replace("/back/", "/"));
+ }
+
+ @Override
+ public void destroy() {
+ // empty
+ }
+ }), "/back/*", EnumSet.of(DispatcherType.REQUEST));
+ gs.setRepositoryResolver(new TestRepositoryResolver(src, srcName));
+ app.addServlet(new ServletHolder(gs), "/*");
+ return app;
+ }
+
+ @Test
+ public void testInitialClone_ViaHttps() throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ try (Transport t = Transport.open(dst, secureURI)) {
+ t.setCredentialsProvider(testCredentials);
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ }
+ assertTrue(dst.hasObject(A_txt));
+ assertEquals(B, dst.exactRef(master).getObjectId());
+ fsck(dst, B);
+
+ List<AccessEvent> requests = getRequests();
+ assertEquals(2, requests.size());
+ }
+
+ @Test
+ public void testInitialClone_RedirectToHttps() throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ URIish cloneFrom = extendPath(remoteURI, "/https");
+ try (Transport t = Transport.open(dst, cloneFrom)) {
+ t.setCredentialsProvider(testCredentials);
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ }
+ assertTrue(dst.hasObject(A_txt));
+ assertEquals(B, dst.exactRef(master).getObjectId());
+ fsck(dst, B);
+
+ List<AccessEvent> requests = getRequests();
+ assertEquals(3, requests.size());
+ }
+
+ @Test
+ public void testInitialClone_RedirectBackToHttp() throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ URIish cloneFrom = extendPath(secureURI, "/back");
+ try (Transport t = Transport.open(dst, cloneFrom)) {
+ t.setCredentialsProvider(testCredentials);
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ fail("Should have failed (redirect from https to http)");
+ } catch (TransportException e) {
+ assertTrue(e.getMessage().contains("not allowed"));
+ }
+ }
+
+ @Test
+ public void testInitialClone_SslFailure() throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ try (Transport t = Transport.open(dst, secureURI)) {
+ // Set a credentials provider that doesn't handle questions
+ t.setCredentialsProvider(
+ new UsernamePasswordCredentialsProvider("any", "anypwd"));
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ fail("Should have failed (SSL certificate not trusted)");
+ } catch (TransportException e) {
+ assertTrue(e.getMessage().contains("Secure connection"));
+ }
+ }
+
+}
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
index ed223c96ef..caa172e138 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010, Google Inc.
+ * Copyright (C) 2010, 2017 Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
@@ -57,17 +57,21 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
+import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
+import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
@@ -78,9 +82,10 @@ import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jgit.errors.RemoteRepositoryException;
-import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.errors.UnsupportedCredentialItem;
import org.eclipse.jgit.http.server.GitServlet;
+import org.eclipse.jgit.http.server.resolver.DefaultUploadPackFactory;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
import org.eclipse.jgit.junit.TestRepository;
@@ -101,20 +106,35 @@ import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.transport.AbstractAdvertiseRefsHook;
+import org.eclipse.jgit.transport.AdvertiseRefsHook;
+import org.eclipse.jgit.transport.CredentialItem;
+import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.FetchConnection;
import org.eclipse.jgit.transport.HttpTransport;
+import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.TransportHttp;
import org.eclipse.jgit.transport.URIish;
+import org.eclipse.jgit.transport.UploadPack;
+import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.eclipse.jgit.transport.http.HttpConnectionFactory;
import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory;
import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory;
-import org.eclipse.jgit.transport.resolver.RepositoryResolver;
+import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
+import org.eclipse.jgit.transport.resolver.UploadPackFactory;
+import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.HttpSupport;
+import org.eclipse.jgit.util.SystemReader;
+import org.hamcrest.Matchers;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@@ -123,17 +143,29 @@ import org.junit.runners.Parameterized.Parameters;
public class SmartClientSmartServerTest extends HttpTestCase {
private static final String HDR_TRANSFER_ENCODING = "Transfer-Encoding";
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ private AdvertiseRefsHook advertiseRefsHook;
+
private Repository remoteRepository;
+ private CredentialsProvider testCredentials = new UsernamePasswordCredentialsProvider(
+ AppServer.username, AppServer.password);
+
private URIish remoteURI;
private URIish brokenURI;
private URIish redirectURI;
+ private URIish authURI;
+
+ private URIish authOnPostURI;
+
private RevBlob A_txt;
- private RevCommit A, B;
+ private RevCommit A, B, unreachableCommit;
@Parameters
public static Collection<Object[]> data() {
@@ -160,12 +192,29 @@ public class SmartClientSmartServerTest extends HttpTestCase {
ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, true);
GitServlet gs = new GitServlet();
+ gs.setUploadPackFactory(new UploadPackFactory<HttpServletRequest>() {
+ @Override
+ public UploadPack create(HttpServletRequest req, Repository db)
+ throws ServiceNotEnabledException,
+ ServiceNotAuthorizedException {
+ DefaultUploadPackFactory f = new DefaultUploadPackFactory();
+ UploadPack up = f.create(req, db);
+ if (advertiseRefsHook != null) {
+ up.setAdvertiseRefsHook(advertiseRefsHook);
+ }
+ return up;
+ }
+ });
ServletContextHandler app = addNormalContext(gs, src, srcName);
ServletContextHandler broken = addBrokenContext(gs, src, srcName);
- ServletContextHandler redirect = addRedirectContext(gs, src, srcName);
+ ServletContextHandler redirect = addRedirectContext(gs);
+
+ ServletContextHandler auth = addAuthContext(gs, "auth");
+
+ ServletContextHandler authOnPost = addAuthContext(gs, "pauth", "POST");
server.setUp();
@@ -173,18 +222,67 @@ public class SmartClientSmartServerTest extends HttpTestCase {
remoteURI = toURIish(app, srcName);
brokenURI = toURIish(broken, srcName);
redirectURI = toURIish(redirect, srcName);
+ authURI = toURIish(auth, srcName);
+ authOnPostURI = toURIish(authOnPost, srcName);
A_txt = src.blob("A");
A = src.commit().add("A_txt", A_txt).create();
B = src.commit().parent(A).add("A_txt", "C").add("B", "B").create();
src.update(master, B);
+ unreachableCommit = src.commit().add("A_txt", A_txt).create();
+
src.update("refs/garbage/a/very/long/ref/name/to/compress", B);
}
private ServletContextHandler addNormalContext(GitServlet gs, TestRepository<Repository> src, String srcName) {
ServletContextHandler app = server.addContext("/git");
- gs.setRepositoryResolver(new TestRepoResolver(src, srcName));
+ app.addFilter(new FilterHolder(new Filter() {
+
+ @Override
+ public void init(FilterConfig filterConfig)
+ throws ServletException {
+ // empty
+ }
+
+ // Does an internal forward for GET requests containing "/post/",
+ // and issues a 301 redirect on POST requests for such URLs. Used
+ // in the POST redirect tests.
+ @Override
+ public void doFilter(ServletRequest request,
+ ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
+ final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+ final StringBuffer fullUrl = httpServletRequest.getRequestURL();
+ if (httpServletRequest.getQueryString() != null) {
+ fullUrl.append("?")
+ .append(httpServletRequest.getQueryString());
+ }
+ String urlString = fullUrl.toString();
+ if ("POST".equalsIgnoreCase(httpServletRequest.getMethod())) {
+ httpServletResponse.setStatus(
+ HttpServletResponse.SC_MOVED_PERMANENTLY);
+ httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
+ urlString.replace("/post/", "/"));
+ } else {
+ String path = httpServletRequest.getPathInfo();
+ path = path.replace("/post/", "/");
+ if (httpServletRequest.getQueryString() != null) {
+ path += '?' + httpServletRequest.getQueryString();
+ }
+ RequestDispatcher dispatcher = httpServletRequest
+ .getRequestDispatcher(path);
+ dispatcher.forward(httpServletRequest, httpServletResponse);
+ }
+ }
+
+ @Override
+ public void destroy() {
+ // empty
+ }
+ }), "/post/*", EnumSet.of(DispatcherType.REQUEST));
+ gs.setRepositoryResolver(new TestRepositoryResolver(src, srcName));
app.addServlet(new ServletHolder(gs), "/*");
return app;
}
@@ -222,12 +320,28 @@ public class SmartClientSmartServerTest extends HttpTestCase {
return broken;
}
- @SuppressWarnings("unused")
- private ServletContextHandler addRedirectContext(GitServlet gs,
- TestRepository<Repository> src, String srcName) {
+ private ServletContextHandler addAuthContext(GitServlet gs,
+ String contextPath, String... methods) {
+ ServletContextHandler auth = server.addContext('/' + contextPath);
+ auth.addServlet(new ServletHolder(gs), "/*");
+ return server.authBasic(auth, methods);
+ }
+
+ private ServletContextHandler addRedirectContext(GitServlet gs) {
ServletContextHandler redirect = server.addContext("/redirect");
redirect.addFilter(new FilterHolder(new Filter() {
+ // Enables tests for different codes, and for multiple redirects.
+ // First parameter is the number of redirects, second one is the
+ // redirect status code that should be used
+ private Pattern responsePattern = Pattern
+ .compile("/response/(\\d+)/(30[1237])/");
+
+ // Enables tests to specify the context that the request should be
+ // redirected to in the end. If not present, redirects got to the
+ // normal /git context.
+ private Pattern targetPattern = Pattern.compile("/target(/\\w+)/");
+
@Override
public void init(FilterConfig filterConfig)
throws ServletException {
@@ -245,10 +359,50 @@ public class SmartClientSmartServerTest extends HttpTestCase {
fullUrl.append("?")
.append(httpServletRequest.getQueryString());
}
- httpServletResponse
- .setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
+ String urlString = fullUrl.toString();
+ if (urlString.contains("/loop/")) {
+ urlString = urlString.replace("/loop/", "/loop/x/");
+ if (urlString.contains("/loop/x/x/x/x/x/x/x/x/")) {
+ // Go back to initial.
+ urlString = urlString.replace("/loop/x/x/x/x/x/x/x/x/",
+ "/loop/");
+ }
+ httpServletResponse.setStatus(
+ HttpServletResponse.SC_MOVED_TEMPORARILY);
+ httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
+ urlString);
+ return;
+ }
+ int responseCode = HttpServletResponse.SC_MOVED_PERMANENTLY;
+ int nofRedirects = 0;
+ Matcher matcher = responsePattern.matcher(urlString);
+ if (matcher.find()) {
+ nofRedirects = Integer
+ .parseUnsignedInt(matcher.group(1));
+ responseCode = Integer.parseUnsignedInt(matcher.group(2));
+ if (--nofRedirects <= 0) {
+ urlString = urlString.substring(0, matcher.start())
+ + '/' + urlString.substring(matcher.end());
+ } else {
+ urlString = urlString.substring(0, matcher.start())
+ + "/response/" + nofRedirects + "/"
+ + responseCode + '/'
+ + urlString.substring(matcher.end());
+ }
+ }
+ httpServletResponse.setStatus(responseCode);
+ if (nofRedirects <= 0) {
+ String targetContext = "/git";
+ matcher = targetPattern.matcher(urlString);
+ if (matcher.find()) {
+ urlString = urlString.substring(0, matcher.start())
+ + '/' + urlString.substring(matcher.end());
+ targetContext = matcher.group(1);
+ }
+ urlString = urlString.replace("/redirect", targetContext);
+ }
httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
- fullUrl.toString().replace("/redirect", "/git"));
+ urlString);
}
@Override
@@ -334,6 +488,56 @@ public class SmartClientSmartServerTest extends HttpTestCase {
}
@Test
+ public void testFetchBySHA1() throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ try (Transport t = Transport.open(dst, remoteURI)) {
+ t.fetch(NullProgressMonitor.INSTANCE,
+ Collections.singletonList(new RefSpec(B.name())));
+ }
+
+ assertTrue(dst.hasObject(A_txt));
+ }
+
+ @Test
+ public void testFetchBySHA1Unreachable() throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ try (Transport t = Transport.open(dst, remoteURI)) {
+ thrown.expect(TransportException.class);
+ thrown.expectMessage(Matchers.containsString(
+ "want " + unreachableCommit.name() + " not valid"));
+ t.fetch(NullProgressMonitor.INSTANCE, Collections
+ .singletonList(new RefSpec(unreachableCommit.name())));
+ }
+ }
+
+ @Test
+ public void testFetchBySHA1UnreachableByAdvertiseRefsHook()
+ throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ advertiseRefsHook = new AbstractAdvertiseRefsHook() {
+ @Override
+ protected Map<String, Ref> getAdvertisedRefs(Repository repository,
+ RevWalk revWalk) {
+ return Collections.emptyMap();
+ }
+ };
+
+ try (Transport t = Transport.open(dst, remoteURI)) {
+ thrown.expect(TransportException.class);
+ thrown.expectMessage(Matchers.containsString(
+ "want " + A.name() + " not valid"));
+ t.fetch(NullProgressMonitor.INSTANCE, Collections
+ .singletonList(new RefSpec(A.name())));
+ }
+ }
+
+ @Test
public void testInitialClone_Small() throws Exception {
Repository dst = createBareRepository();
assertFalse(dst.hasObject(A_txt));
@@ -373,13 +577,332 @@ public class SmartClientSmartServerTest extends HttpTestCase {
.getResponseHeader(HDR_CONTENT_TYPE));
}
+ private void initialClone_Redirect(int nofRedirects, int code)
+ throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ URIish cloneFrom = redirectURI;
+ if (code != 301 || nofRedirects > 1) {
+ cloneFrom = extendPath(cloneFrom,
+ "/response/" + nofRedirects + "/" + code);
+ }
+ try (Transport t = Transport.open(dst, cloneFrom)) {
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ }
+
+ assertTrue(dst.hasObject(A_txt));
+ assertEquals(B, dst.exactRef(master).getObjectId());
+ fsck(dst, B);
+
+ List<AccessEvent> requests = getRequests();
+ assertEquals(2 + nofRedirects, requests.size());
+
+ int n = 0;
+ while (n < nofRedirects) {
+ AccessEvent redirect = requests.get(n++);
+ assertEquals(code, redirect.getStatus());
+ }
+
+ AccessEvent info = requests.get(n++);
+ assertEquals("GET", info.getMethod());
+ assertEquals(join(remoteURI, "info/refs"), info.getPath());
+ assertEquals(1, info.getParameters().size());
+ assertEquals("git-upload-pack", info.getParameter("service"));
+ assertEquals(200, info.getStatus());
+ assertEquals("application/x-git-upload-pack-advertisement",
+ info.getResponseHeader(HDR_CONTENT_TYPE));
+ assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+
+ AccessEvent service = requests.get(n++);
+ assertEquals("POST", service.getMethod());
+ assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
+ assertEquals(0, service.getParameters().size());
+ assertNotNull("has content-length",
+ service.getRequestHeader(HDR_CONTENT_LENGTH));
+ assertNull("not chunked",
+ service.getRequestHeader(HDR_TRANSFER_ENCODING));
+
+ assertEquals(200, service.getStatus());
+ assertEquals("application/x-git-upload-pack-result",
+ service.getResponseHeader(HDR_CONTENT_TYPE));
+ }
+
+ @Test
+ public void testInitialClone_Redirect301Small() throws Exception {
+ initialClone_Redirect(1, 301);
+ }
+
+ @Test
+ public void testInitialClone_Redirect302Small() throws Exception {
+ initialClone_Redirect(1, 302);
+ }
+
+ @Test
+ public void testInitialClone_Redirect303Small() throws Exception {
+ initialClone_Redirect(1, 303);
+ }
+
+ @Test
+ public void testInitialClone_Redirect307Small() throws Exception {
+ initialClone_Redirect(1, 307);
+ }
+
+ @Test
+ public void testInitialClone_RedirectMultiple() throws Exception {
+ initialClone_Redirect(4, 302);
+ }
+
+ @Test
+ public void testInitialClone_RedirectMax() throws Exception {
+ FileBasedConfig userConfig = SystemReader.getInstance()
+ .openUserConfig(null, FS.DETECTED);
+ userConfig.setInt("http", null, "maxRedirects", 4);
+ userConfig.save();
+ initialClone_Redirect(4, 302);
+ }
+
+ @Test
+ public void testInitialClone_RedirectTooOften() throws Exception {
+ FileBasedConfig userConfig = SystemReader.getInstance()
+ .openUserConfig(null, FS.DETECTED);
+ userConfig.setInt("http", null, "maxRedirects", 3);
+ userConfig.save();
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ URIish cloneFrom = extendPath(redirectURI, "/response/4/302");
+ String remoteUri = cloneFrom.toString();
+ try (Transport t = Transport.open(dst, cloneFrom)) {
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ fail("Should have failed (too many redirects)");
+ } catch (TransportException e) {
+ String expectedMessageBegin = remoteUri.toString() + ": "
+ + MessageFormat.format(JGitText.get().redirectLimitExceeded,
+ "3", remoteUri.replace("/4/", "/1/") + '/', "");
+ String message = e.getMessage();
+ if (message.length() > expectedMessageBegin.length()) {
+ message = message.substring(0, expectedMessageBegin.length());
+ }
+ assertEquals(expectedMessageBegin, message);
+ }
+ }
+
+ @Test
+ public void testInitialClone_RedirectLoop() throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ URIish cloneFrom = extendPath(redirectURI, "/loop");
+ try (Transport t = Transport.open(dst, cloneFrom)) {
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ fail("Should have failed (redirect loop)");
+ } catch (TransportException e) {
+ assertTrue(e.getMessage().contains("Redirected more than"));
+ }
+ }
+
@Test
- public void testInitialClone_RedirectSmall() throws Exception {
+ public void testInitialClone_RedirectOnPostAllowed() throws Exception {
+ FileBasedConfig userConfig = SystemReader.getInstance()
+ .openUserConfig(null, FS.DETECTED);
+ userConfig.setString("http", null, "followRedirects", "true");
+ userConfig.save();
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ URIish cloneFrom = extendPath(remoteURI, "/post");
+ try (Transport t = Transport.open(dst, cloneFrom)) {
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ }
+
+ assertTrue(dst.hasObject(A_txt));
+ assertEquals(B, dst.exactRef(master).getObjectId());
+ fsck(dst, B);
+
+ List<AccessEvent> requests = getRequests();
+ assertEquals(3, requests.size());
+
+ AccessEvent info = requests.get(0);
+ assertEquals("GET", info.getMethod());
+ assertEquals(join(cloneFrom, "info/refs"), info.getPath());
+ assertEquals(1, info.getParameters().size());
+ assertEquals("git-upload-pack", info.getParameter("service"));
+ assertEquals(200, info.getStatus());
+ assertEquals("application/x-git-upload-pack-advertisement",
+ info.getResponseHeader(HDR_CONTENT_TYPE));
+ assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+
+ AccessEvent redirect = requests.get(1);
+ assertEquals("POST", redirect.getMethod());
+ assertEquals(301, redirect.getStatus());
+
+ AccessEvent service = requests.get(2);
+ assertEquals("POST", service.getMethod());
+ assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
+ assertEquals(0, service.getParameters().size());
+ assertNotNull("has content-length",
+ service.getRequestHeader(HDR_CONTENT_LENGTH));
+ assertNull("not chunked",
+ service.getRequestHeader(HDR_TRANSFER_ENCODING));
+
+ assertEquals(200, service.getStatus());
+ assertEquals("application/x-git-upload-pack-result",
+ service.getResponseHeader(HDR_CONTENT_TYPE));
+ }
+
+ @Test
+ public void testInitialClone_RedirectOnPostForbidden() throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ URIish cloneFrom = extendPath(remoteURI, "/post");
+ try (Transport t = Transport.open(dst, cloneFrom)) {
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ fail("Should have failed (redirect on POST)");
+ } catch (TransportException e) {
+ assertTrue(e.getMessage().contains("301"));
+ }
+ }
+
+ @Test
+ public void testInitialClone_RedirectForbidden() throws Exception {
+ FileBasedConfig userConfig = SystemReader.getInstance()
+ .openUserConfig(null, FS.DETECTED);
+ userConfig.setString("http", null, "followRedirects", "false");
+ userConfig.save();
+
Repository dst = createBareRepository();
assertFalse(dst.hasObject(A_txt));
try (Transport t = Transport.open(dst, redirectURI)) {
t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ fail("Should have failed (redirects forbidden)");
+ } catch (TransportException e) {
+ assertTrue(
+ e.getMessage().contains("http.followRedirects is false"));
+ }
+ }
+
+ @Test
+ public void testInitialClone_WithAuthentication() throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ try (Transport t = Transport.open(dst, authURI)) {
+ t.setCredentialsProvider(testCredentials);
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ }
+
+ assertTrue(dst.hasObject(A_txt));
+ assertEquals(B, dst.exactRef(master).getObjectId());
+ fsck(dst, B);
+
+ List<AccessEvent> requests = getRequests();
+ assertEquals(3, requests.size());
+
+ AccessEvent info = requests.get(0);
+ assertEquals("GET", info.getMethod());
+ assertEquals(401, info.getStatus());
+
+ info = requests.get(1);
+ assertEquals("GET", info.getMethod());
+ assertEquals(join(authURI, "info/refs"), info.getPath());
+ assertEquals(1, info.getParameters().size());
+ assertEquals("git-upload-pack", info.getParameter("service"));
+ assertEquals(200, info.getStatus());
+ assertEquals("application/x-git-upload-pack-advertisement",
+ info.getResponseHeader(HDR_CONTENT_TYPE));
+ assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+
+ AccessEvent service = requests.get(2);
+ assertEquals("POST", service.getMethod());
+ assertEquals(join(authURI, "git-upload-pack"), service.getPath());
+ assertEquals(0, service.getParameters().size());
+ assertNotNull("has content-length",
+ service.getRequestHeader(HDR_CONTENT_LENGTH));
+ assertNull("not chunked",
+ service.getRequestHeader(HDR_TRANSFER_ENCODING));
+
+ assertEquals(200, service.getStatus());
+ assertEquals("application/x-git-upload-pack-result",
+ service.getResponseHeader(HDR_CONTENT_TYPE));
+ }
+
+ @Test
+ public void testInitialClone_WithAuthenticationNoCredentials()
+ throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ try (Transport t = Transport.open(dst, authURI)) {
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ fail("Should not have succeeded -- no authentication");
+ } catch (TransportException e) {
+ String msg = e.getMessage();
+ assertTrue("Unexpected exception message: " + msg,
+ msg.contains("no CredentialsProvider"));
+ }
+ List<AccessEvent> requests = getRequests();
+ assertEquals(1, requests.size());
+
+ AccessEvent info = requests.get(0);
+ assertEquals("GET", info.getMethod());
+ assertEquals(401, info.getStatus());
+ }
+
+ @Test
+ public void testInitialClone_WithAuthenticationWrongCredentials()
+ throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ try (Transport t = Transport.open(dst, authURI)) {
+ t.setCredentialsProvider(new UsernamePasswordCredentialsProvider(
+ AppServer.username, "wrongpassword"));
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ fail("Should not have succeeded -- wrong password");
+ } catch (TransportException e) {
+ String msg = e.getMessage();
+ assertTrue("Unexpected exception message: " + msg,
+ msg.contains("auth"));
+ }
+ List<AccessEvent> requests = getRequests();
+ // Once without authentication plus three re-tries with authentication
+ assertEquals(4, requests.size());
+
+ for (AccessEvent event : requests) {
+ assertEquals("GET", event.getMethod());
+ assertEquals(401, event.getStatus());
+ }
+ }
+
+ @Test
+ public void testInitialClone_WithAuthenticationAfterRedirect()
+ throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ URIish cloneFrom = extendPath(redirectURI, "/target/auth");
+ CredentialsProvider uriSpecificCredentialsProvider = new UsernamePasswordCredentialsProvider(
+ "unknown", "none") {
+ @Override
+ public boolean get(URIish uri, CredentialItem... items)
+ throws UnsupportedCredentialItem {
+ // Only return the true credentials if the uri path starts with
+ // /auth. This ensures that we do provide the correct
+ // credentials only for the URi after the redirect, making the
+ // test fail if we should be asked for the credentials for the
+ // original URI.
+ if (uri.getPath().startsWith("/auth")) {
+ return testCredentials.get(uri, items);
+ }
+ return super.get(uri, items);
+ }
+ };
+ try (Transport t = Transport.open(dst, cloneFrom)) {
+ t.setCredentialsProvider(uriSpecificCredentialsProvider);
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
}
assertTrue(dst.hasObject(A_txt));
@@ -389,12 +912,19 @@ public class SmartClientSmartServerTest extends HttpTestCase {
List<AccessEvent> requests = getRequests();
assertEquals(4, requests.size());
- AccessEvent firstRedirect = requests.get(0);
- assertEquals(301, firstRedirect.getStatus());
+ AccessEvent redirect = requests.get(0);
+ assertEquals("GET", redirect.getMethod());
+ assertEquals(join(cloneFrom, "info/refs"), redirect.getPath());
+ assertEquals(301, redirect.getStatus());
AccessEvent info = requests.get(1);
assertEquals("GET", info.getMethod());
- assertEquals(join(remoteURI, "info/refs"), info.getPath());
+ assertEquals(join(authURI, "info/refs"), info.getPath());
+ assertEquals(401, info.getStatus());
+
+ info = requests.get(2);
+ assertEquals("GET", info.getMethod());
+ assertEquals(join(authURI, "info/refs"), info.getPath());
assertEquals(1, info.getParameters().size());
assertEquals("git-upload-pack", info.getParameter("service"));
assertEquals(200, info.getStatus());
@@ -402,12 +932,56 @@ public class SmartClientSmartServerTest extends HttpTestCase {
info.getResponseHeader(HDR_CONTENT_TYPE));
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
- AccessEvent secondRedirect = requests.get(2);
- assertEquals(301, secondRedirect.getStatus());
-
AccessEvent service = requests.get(3);
assertEquals("POST", service.getMethod());
- assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
+ assertEquals(join(authURI, "git-upload-pack"), service.getPath());
+ assertEquals(0, service.getParameters().size());
+ assertNotNull("has content-length",
+ service.getRequestHeader(HDR_CONTENT_LENGTH));
+ assertNull("not chunked",
+ service.getRequestHeader(HDR_TRANSFER_ENCODING));
+
+ assertEquals(200, service.getStatus());
+ assertEquals("application/x-git-upload-pack-result",
+ service.getResponseHeader(HDR_CONTENT_TYPE));
+ }
+
+ @Test
+ public void testInitialClone_WithAuthenticationOnPostOnly()
+ throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ try (Transport t = Transport.open(dst, authOnPostURI)) {
+ t.setCredentialsProvider(testCredentials);
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ }
+
+ assertTrue(dst.hasObject(A_txt));
+ assertEquals(B, dst.exactRef(master).getObjectId());
+ fsck(dst, B);
+
+ List<AccessEvent> requests = getRequests();
+ assertEquals(3, requests.size());
+
+ AccessEvent info = requests.get(0);
+ assertEquals("GET", info.getMethod());
+ assertEquals(join(authOnPostURI, "info/refs"), info.getPath());
+ assertEquals(1, info.getParameters().size());
+ assertEquals("git-upload-pack", info.getParameter("service"));
+ assertEquals(200, info.getStatus());
+ assertEquals("application/x-git-upload-pack-advertisement",
+ info.getResponseHeader(HDR_CONTENT_TYPE));
+ assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+
+ AccessEvent service = requests.get(1);
+ assertEquals("POST", service.getMethod());
+ assertEquals(join(authOnPostURI, "git-upload-pack"), service.getPath());
+ assertEquals(401, service.getStatus());
+
+ service = requests.get(2);
+ assertEquals("POST", service.getMethod());
+ assertEquals(join(authOnPostURI, "git-upload-pack"), service.getPath());
assertEquals(0, service.getParameters().size());
assertNotNull("has content-length",
service.getRequestHeader(HDR_CONTENT_LENGTH));
@@ -619,7 +1193,7 @@ public class SmartClientSmartServerTest extends HttpTestCase {
ServletContextHandler app = noRefServer.addContext("/git");
GitServlet gs = new GitServlet();
- gs.setRepositoryResolver(new TestRepoResolver(repo, repoName));
+ gs.setRepositoryResolver(new TestRepositoryResolver(repo, repoName));
app.addServlet(new ServletHolder(gs), "/*");
noRefServer.setUp();
@@ -822,28 +1396,4 @@ public class SmartClientSmartServerTest extends HttpTestCase {
cfg.save();
}
- private final class TestRepoResolver
- implements RepositoryResolver<HttpServletRequest> {
-
- private final TestRepository<Repository> repo;
-
- private final String repoName;
-
- private TestRepoResolver(TestRepository<Repository> repo,
- String repoName) {
- this.repo = repo;
- this.repoName = repoName;
- }
-
- @Override
- public Repository open(HttpServletRequest req, String name)
- throws RepositoryNotFoundException, ServiceNotEnabledException {
- if (!name.equals(repoName))
- throw new RepositoryNotFoundException(name);
-
- Repository db = repo.getRepository();
- db.incrementOpen();
- return db;
- }
- }
}