Add JUnit tests for HTTP transport
No Eclipse support for this project is provided, because the Jetty project does not publish a complete P2 repository. Change-Id: Ic5fe2e79bb216e36920fd4a70ec15dd6ccfd1468 Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This commit is contained in:
parent
d5bc8be743
commit
f5eb0d9366
|
@ -0,0 +1 @@
|
||||||
|
/target
|
|
@ -0,0 +1,108 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2009-2010, Google Inc.
|
||||||
|
Copyright (C) 2008, Imran M Yousuf <imyousuf@smartitengineering.com>
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.eclipse.jgit</groupId>
|
||||||
|
<artifactId>org.eclipse.jgit-parent</artifactId>
|
||||||
|
<version>0.6.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>org.eclipse.jgit.http.test</artifactId>
|
||||||
|
<name>JGit - HTTP Tests</name>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
Tests for the HTTP transport.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jgit</groupId>
|
||||||
|
<artifactId>org.eclipse.jgit</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>
|
||||||
|
<groupId>org.eclipse.jgit</groupId>
|
||||||
|
<artifactId>org.eclipse.jgit.http.server</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-servlet</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<testSourceDirectory>tst/</testSourceDirectory>
|
||||||
|
|
||||||
|
<testResources>
|
||||||
|
<testResource>
|
||||||
|
<directory>tst-rsrc/</directory>
|
||||||
|
</testResource>
|
||||||
|
</testResources>
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2010, 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.HttpServletRequestWrapper;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.Request;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.AsIsFileService;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotAuthorizedException;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException;
|
||||||
|
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
|
||||||
|
public class AsIsServiceTest extends LocalDiskRepositoryTestCase {
|
||||||
|
private Repository db;
|
||||||
|
|
||||||
|
private AsIsFileService service;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
db = createBareRepository();
|
||||||
|
service = new AsIsFileService();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDisabledSingleton() throws ServiceNotAuthorizedException {
|
||||||
|
service = AsIsFileService.DISABLED;
|
||||||
|
try {
|
||||||
|
service.access(new R(null, "1.2.3.4"), db);
|
||||||
|
fail("Created session for anonymous user: null");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
service.access(new R("bob", "1.2.3.4"), db);
|
||||||
|
fail("Created session for user: \"bob\"");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreate_Default() throws ServiceNotEnabledException,
|
||||||
|
ServiceNotAuthorizedException {
|
||||||
|
service.access(new R(null, "1.2.3.4"), db);
|
||||||
|
service.access(new R("bob", "1.2.3.4"), db);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreate_Disabled() throws ServiceNotAuthorizedException {
|
||||||
|
db.getConfig().setBoolean("http", null, "getanyfile", false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
service.access(new R(null, "1.2.3.4"), db);
|
||||||
|
fail("Created session for anonymous user: null");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
service.access(new R("bob", "1.2.3.4"), db);
|
||||||
|
fail("Created session for user: \"bob\"");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreate_Enabled() throws ServiceNotEnabledException,
|
||||||
|
ServiceNotAuthorizedException {
|
||||||
|
db.getConfig().setBoolean("http", null, "getanyfile", true);
|
||||||
|
service.access(new R(null, "1.2.3.4"), db);
|
||||||
|
service.access(new R("bob", "1.2.3.4"), db);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class R extends HttpServletRequestWrapper {
|
||||||
|
private final String user;
|
||||||
|
|
||||||
|
private final String host;
|
||||||
|
|
||||||
|
R(final String user, final String host) {
|
||||||
|
super(new Request() /* can't pass null, sigh */);
|
||||||
|
this.user = user;
|
||||||
|
this.host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRemoteHost() {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRemoteUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,198 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2010, 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.HttpServletRequestWrapper;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.Request;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.DefaultReceivePackFactory;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.ReceivePackFactory;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotAuthorizedException;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException;
|
||||||
|
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
|
||||||
|
import org.eclipse.jgit.lib.PersonIdent;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.transport.ReceivePack;
|
||||||
|
|
||||||
|
public class DefaultReceivePackFactoryTest extends LocalDiskRepositoryTestCase {
|
||||||
|
private Repository db;
|
||||||
|
|
||||||
|
private ReceivePackFactory factory;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
db = createBareRepository();
|
||||||
|
factory = new DefaultReceivePackFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDisabledSingleton() throws ServiceNotAuthorizedException {
|
||||||
|
factory = ReceivePackFactory.DISABLED;
|
||||||
|
|
||||||
|
try {
|
||||||
|
factory.create(new R(null, "localhost"), db);
|
||||||
|
fail("Created session for anonymous user: null");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
factory.create(new R("", "localhost"), db);
|
||||||
|
fail("Created session for anonymous user: \"\"");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
factory.create(new R("bob", "localhost"), db);
|
||||||
|
fail("Created session for user: \"bob\"");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreate_NullUser() throws ServiceNotEnabledException {
|
||||||
|
try {
|
||||||
|
factory.create(new R(null, "localhost"), db);
|
||||||
|
fail("Created session for anonymous user: null");
|
||||||
|
} catch (ServiceNotAuthorizedException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreate_EmptyStringUser() throws ServiceNotEnabledException {
|
||||||
|
try {
|
||||||
|
factory.create(new R("", "localhost"), db);
|
||||||
|
fail("Created session for anonymous user: \"\"");
|
||||||
|
} catch (ServiceNotAuthorizedException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreate_AuthUser() throws ServiceNotEnabledException,
|
||||||
|
ServiceNotAuthorizedException {
|
||||||
|
ReceivePack rp;
|
||||||
|
rp = factory.create(new R("bob", "1.2.3.4"), db);
|
||||||
|
assertNotNull("have ReceivePack", rp);
|
||||||
|
assertSame(db, rp.getRepository());
|
||||||
|
|
||||||
|
PersonIdent id = rp.getRefLogIdent();
|
||||||
|
assertNotNull(id);
|
||||||
|
assertEquals("bob", id.getName());
|
||||||
|
assertEquals("bob@1.2.3.4", id.getEmailAddress());
|
||||||
|
|
||||||
|
// Should have inherited off the current system, which is mocked
|
||||||
|
assertEquals(author.getTimeZoneOffset(), id.getTimeZoneOffset());
|
||||||
|
assertEquals(author.getWhen(), id.getWhen());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreate_Disabled() throws ServiceNotAuthorizedException {
|
||||||
|
db.getConfig().setBoolean("http", null, "receivepack", false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
factory.create(new R(null, "localhost"), db);
|
||||||
|
fail("Created session for anonymous user: null");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
factory.create(new R("", "localhost"), db);
|
||||||
|
fail("Created session for anonymous user: \"\"");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
factory.create(new R("bob", "localhost"), db);
|
||||||
|
fail("Created session for user: \"bob\"");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreate_Enabled() throws ServiceNotEnabledException,
|
||||||
|
ServiceNotAuthorizedException {
|
||||||
|
db.getConfig().setBoolean("http", null, "receivepack", true);
|
||||||
|
ReceivePack rp;
|
||||||
|
|
||||||
|
rp = factory.create(new R(null, "1.2.3.4"), db);
|
||||||
|
assertNotNull("have ReceivePack", rp);
|
||||||
|
assertSame(db, rp.getRepository());
|
||||||
|
|
||||||
|
PersonIdent id = rp.getRefLogIdent();
|
||||||
|
assertNotNull(id);
|
||||||
|
assertEquals("anonymous", id.getName());
|
||||||
|
assertEquals("anonymous@1.2.3.4", id.getEmailAddress());
|
||||||
|
|
||||||
|
// Should have inherited off the current system, which is mocked
|
||||||
|
assertEquals(author.getTimeZoneOffset(), id.getTimeZoneOffset());
|
||||||
|
assertEquals(author.getWhen(), id.getWhen());
|
||||||
|
|
||||||
|
rp = factory.create(new R("bob", "1.2.3.4"), db);
|
||||||
|
assertNotNull("have ReceivePack", rp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class R extends HttpServletRequestWrapper {
|
||||||
|
private final String user;
|
||||||
|
|
||||||
|
private final String host;
|
||||||
|
|
||||||
|
R(final String user, final String host) {
|
||||||
|
super(new Request() /* can't pass null, sigh */);
|
||||||
|
this.user = user;
|
||||||
|
this.host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRemoteHost() {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRemoteUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,160 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2010, 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.HttpServletRequestWrapper;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.Request;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.DefaultUploadPackFactory;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotAuthorizedException;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.UploadPackFactory;
|
||||||
|
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.transport.UploadPack;
|
||||||
|
|
||||||
|
public class DefaultUploadPackFactoryTest extends LocalDiskRepositoryTestCase {
|
||||||
|
private Repository db;
|
||||||
|
|
||||||
|
private UploadPackFactory factory;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
db = createBareRepository();
|
||||||
|
factory = new DefaultUploadPackFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDisabledSingleton() throws ServiceNotAuthorizedException {
|
||||||
|
factory = UploadPackFactory.DISABLED;
|
||||||
|
|
||||||
|
try {
|
||||||
|
factory.create(new R(null, "localhost"), db);
|
||||||
|
fail("Created session for anonymous user: null");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
factory.create(new R("", "localhost"), db);
|
||||||
|
fail("Created session for anonymous user: \"\"");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
factory.create(new R("bob", "localhost"), db);
|
||||||
|
fail("Created session for user: \"bob\"");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreate_Default() throws ServiceNotEnabledException,
|
||||||
|
ServiceNotAuthorizedException {
|
||||||
|
UploadPack up;
|
||||||
|
|
||||||
|
up = factory.create(new R(null, "1.2.3.4"), db);
|
||||||
|
assertNotNull("have UploadPack", up);
|
||||||
|
assertSame(db, up.getRepository());
|
||||||
|
|
||||||
|
up = factory.create(new R("bob", "1.2.3.4"), db);
|
||||||
|
assertNotNull("have UploadPack", up);
|
||||||
|
assertSame(db, up.getRepository());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreate_Disabled() throws ServiceNotAuthorizedException {
|
||||||
|
db.getConfig().setBoolean("http", null, "uploadpack", false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
factory.create(new R(null, "localhost"), db);
|
||||||
|
fail("Created session for anonymous user: null");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
factory.create(new R("bob", "localhost"), db);
|
||||||
|
fail("Created session for user: \"bob\"");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
// expected not authorized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreate_Enabled() throws ServiceNotEnabledException,
|
||||||
|
ServiceNotAuthorizedException {
|
||||||
|
db.getConfig().setBoolean("http", null, "uploadpack", true);
|
||||||
|
UploadPack up;
|
||||||
|
|
||||||
|
up = factory.create(new R(null, "1.2.3.4"), db);
|
||||||
|
assertNotNull("have UploadPack", up);
|
||||||
|
assertSame(db, up.getRepository());
|
||||||
|
|
||||||
|
up = factory.create(new R("bob", "1.2.3.4"), db);
|
||||||
|
assertNotNull("have UploadPack", up);
|
||||||
|
assertSame(db, up.getRepository());
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class R extends HttpServletRequestWrapper {
|
||||||
|
private final String user;
|
||||||
|
|
||||||
|
private final String host;
|
||||||
|
|
||||||
|
R(final String user, final String host) {
|
||||||
|
super(new Request() /* can't pass null, sigh */);
|
||||||
|
this.user = user;
|
||||||
|
this.host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRemoteHost() {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRemoteUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,246 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010, 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 static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT;
|
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_PRAGMA;
|
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_USER_AGENT;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.servlet.DefaultServlet;
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jgit.errors.NotSupportedException;
|
||||||
|
import org.eclipse.jgit.http.test.util.AccessEvent;
|
||||||
|
import org.eclipse.jgit.http.test.util.HttpTestCase;
|
||||||
|
import org.eclipse.jgit.junit.TestRepository;
|
||||||
|
import org.eclipse.jgit.lib.Constants;
|
||||||
|
import org.eclipse.jgit.lib.NullProgressMonitor;
|
||||||
|
import org.eclipse.jgit.lib.Ref;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.revwalk.RevBlob;
|
||||||
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
|
import org.eclipse.jgit.transport.FetchConnection;
|
||||||
|
import org.eclipse.jgit.transport.HttpTransport;
|
||||||
|
import org.eclipse.jgit.transport.Transport;
|
||||||
|
import org.eclipse.jgit.transport.TransportHttp;
|
||||||
|
import org.eclipse.jgit.transport.URIish;
|
||||||
|
|
||||||
|
public class DumbClientDumbServerTest extends HttpTestCase {
|
||||||
|
private Repository remoteRepository;
|
||||||
|
|
||||||
|
private URIish remoteURI;
|
||||||
|
|
||||||
|
private RevBlob A_txt;
|
||||||
|
|
||||||
|
private RevCommit A, B;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
final TestRepository src = createTestRepository();
|
||||||
|
final File srcGit = src.getRepository().getDirectory();
|
||||||
|
final URI base = srcGit.getParentFile().toURI();
|
||||||
|
|
||||||
|
ServletContextHandler app = server.addContext("/git");
|
||||||
|
app.setResourceBase(base.toString());
|
||||||
|
app.addServlet(DefaultServlet.class, "/");
|
||||||
|
|
||||||
|
server.setUp();
|
||||||
|
|
||||||
|
remoteRepository = src.getRepository();
|
||||||
|
remoteURI = toURIish(app, srcGit.getName());
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListRemote() throws IOException {
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
|
||||||
|
assertEquals("http", remoteURI.getScheme());
|
||||||
|
|
||||||
|
Map<String, Ref> map;
|
||||||
|
Transport t = Transport.open(dst, remoteURI);
|
||||||
|
try {
|
||||||
|
// I didn't make up these public interface names, I just
|
||||||
|
// approved them for inclusion into the code base. Sorry.
|
||||||
|
// --spearce
|
||||||
|
//
|
||||||
|
assertTrue("isa TransportHttp", t instanceof TransportHttp);
|
||||||
|
assertTrue("isa HttpTransport", t instanceof HttpTransport);
|
||||||
|
|
||||||
|
FetchConnection c = t.openFetch();
|
||||||
|
try {
|
||||||
|
map = c.getRefsMap();
|
||||||
|
} finally {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull("have map of refs", map);
|
||||||
|
assertEquals(2, map.size());
|
||||||
|
|
||||||
|
assertNotNull("has " + master, map.get(master));
|
||||||
|
assertEquals(B, map.get(master).getObjectId());
|
||||||
|
|
||||||
|
assertNotNull("has " + Constants.HEAD, map.get(Constants.HEAD));
|
||||||
|
assertEquals(B, map.get(Constants.HEAD).getObjectId());
|
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests();
|
||||||
|
assertEquals(2, requests.size());
|
||||||
|
assertEquals(0, getRequests(remoteURI, "git-upload-pack").size());
|
||||||
|
|
||||||
|
AccessEvent info = requests.get(0);
|
||||||
|
assertEquals("GET", info.getMethod());
|
||||||
|
assertEquals(join(remoteURI, "info/refs"), info.getPath());
|
||||||
|
assertEquals(1, info.getParameters().size());
|
||||||
|
assertEquals("git-upload-pack", info.getParameter("service"));
|
||||||
|
assertEquals("no-cache", info.getRequestHeader(HDR_PRAGMA));
|
||||||
|
assertNotNull("has user-agent", info.getRequestHeader(HDR_USER_AGENT));
|
||||||
|
assertTrue("is jgit agent", info.getRequestHeader(HDR_USER_AGENT)
|
||||||
|
.startsWith("JGit/"));
|
||||||
|
assertEquals("application/x-git-upload-pack-advertisement, */*", info
|
||||||
|
.getRequestHeader(HDR_ACCEPT));
|
||||||
|
assertEquals(200, info.getStatus());
|
||||||
|
|
||||||
|
AccessEvent head = requests.get(1);
|
||||||
|
assertEquals("GET", head.getMethod());
|
||||||
|
assertEquals(join(remoteURI, "HEAD"), head.getPath());
|
||||||
|
assertEquals(0, head.getParameters().size());
|
||||||
|
assertEquals("no-cache", head.getRequestHeader(HDR_PRAGMA));
|
||||||
|
assertNotNull("has user-agent", head.getRequestHeader(HDR_USER_AGENT));
|
||||||
|
assertTrue("is jgit agent", head.getRequestHeader(HDR_USER_AGENT)
|
||||||
|
.startsWith("JGit/"));
|
||||||
|
assertEquals(200, head.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInitialClone_Loose() throws Exception {
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
assertFalse(dst.hasObject(A_txt));
|
||||||
|
|
||||||
|
Transport t = Transport.open(dst, remoteURI);
|
||||||
|
try {
|
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(dst.hasObject(A_txt));
|
||||||
|
assertEquals(B, dst.getRef(master).getObjectId());
|
||||||
|
fsck(dst, B);
|
||||||
|
|
||||||
|
List<AccessEvent> loose = getRequests(loose(remoteURI, A_txt));
|
||||||
|
assertEquals(1, loose.size());
|
||||||
|
assertEquals("GET", loose.get(0).getMethod());
|
||||||
|
assertEquals(0, loose.get(0).getParameters().size());
|
||||||
|
assertEquals(200, loose.get(0).getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInitialClone_Packed() throws Exception {
|
||||||
|
new TestRepository(remoteRepository).packAndPrune();
|
||||||
|
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
assertFalse(dst.hasObject(A_txt));
|
||||||
|
|
||||||
|
Transport t = Transport.open(dst, remoteURI);
|
||||||
|
try {
|
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(dst.hasObject(A_txt));
|
||||||
|
assertEquals(B, dst.getRef(master).getObjectId());
|
||||||
|
fsck(dst, B);
|
||||||
|
|
||||||
|
List<AccessEvent> req;
|
||||||
|
AccessEvent event;
|
||||||
|
|
||||||
|
req = getRequests(loose(remoteURI, B));
|
||||||
|
assertEquals(1, req.size());
|
||||||
|
event = req.get(0);
|
||||||
|
assertEquals("GET", event.getMethod());
|
||||||
|
assertEquals(0, event.getParameters().size());
|
||||||
|
assertEquals(404, event.getStatus());
|
||||||
|
|
||||||
|
req = getRequests(join(remoteURI, "objects/info/packs"));
|
||||||
|
assertEquals(1, req.size());
|
||||||
|
event = req.get(0);
|
||||||
|
assertEquals("GET", event.getMethod());
|
||||||
|
assertEquals(0, event.getParameters().size());
|
||||||
|
assertEquals("no-cache", event.getRequestHeader(HDR_PRAGMA));
|
||||||
|
assertNotNull("has user-agent", event.getRequestHeader(HDR_USER_AGENT));
|
||||||
|
assertTrue("is jgit agent", event.getRequestHeader(HDR_USER_AGENT)
|
||||||
|
.startsWith("JGit/"));
|
||||||
|
assertEquals(200, event.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPushNotSupported() throws Exception {
|
||||||
|
final TestRepository src = createTestRepository();
|
||||||
|
final RevCommit Q = src.commit().create();
|
||||||
|
final Repository db = src.getRepository();
|
||||||
|
|
||||||
|
Transport t = Transport.open(db, remoteURI);
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
t.push(NullProgressMonitor.INSTANCE, push(src, Q));
|
||||||
|
fail("push incorrectly completed against a dumb server");
|
||||||
|
} catch (NotSupportedException nse) {
|
||||||
|
String exp = "remote does not support smart HTTP push";
|
||||||
|
assertEquals(exp, nse.getMessage());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,261 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010, 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 static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT;
|
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_TYPE;
|
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_PRAGMA;
|
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_USER_AGENT;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
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.http.server.resolver.RepositoryResolver;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException;
|
||||||
|
import org.eclipse.jgit.http.test.util.AccessEvent;
|
||||||
|
import org.eclipse.jgit.http.test.util.HttpTestCase;
|
||||||
|
import org.eclipse.jgit.junit.TestRepository;
|
||||||
|
import org.eclipse.jgit.lib.Constants;
|
||||||
|
import org.eclipse.jgit.lib.NullProgressMonitor;
|
||||||
|
import org.eclipse.jgit.lib.Ref;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.revwalk.RevBlob;
|
||||||
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
|
import org.eclipse.jgit.transport.FetchConnection;
|
||||||
|
import org.eclipse.jgit.transport.HttpTransport;
|
||||||
|
import org.eclipse.jgit.transport.Transport;
|
||||||
|
import org.eclipse.jgit.transport.TransportHttp;
|
||||||
|
import org.eclipse.jgit.transport.URIish;
|
||||||
|
|
||||||
|
public class DumbClientSmartServerTest extends HttpTestCase {
|
||||||
|
private Repository remoteRepository;
|
||||||
|
|
||||||
|
private URIish remoteURI;
|
||||||
|
|
||||||
|
private RevBlob A_txt;
|
||||||
|
|
||||||
|
private RevCommit A, B;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
final TestRepository src = createTestRepository();
|
||||||
|
final String srcName = src.getRepository().getDirectory().getName();
|
||||||
|
|
||||||
|
ServletContextHandler app = server.addContext("/git");
|
||||||
|
GitServlet gs = new GitServlet();
|
||||||
|
gs.setRepositoryResolver(new RepositoryResolver() {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
app.addServlet(new ServletHolder(gs), "/*");
|
||||||
|
|
||||||
|
server.setUp();
|
||||||
|
|
||||||
|
remoteRepository = src.getRepository();
|
||||||
|
remoteURI = toURIish(app, 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListRemote() throws IOException {
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
|
||||||
|
assertEquals("http", remoteURI.getScheme());
|
||||||
|
|
||||||
|
Map<String, Ref> map;
|
||||||
|
Transport t = Transport.open(dst, remoteURI);
|
||||||
|
((TransportHttp) t).setUseSmartHttp(false);
|
||||||
|
try {
|
||||||
|
// I didn't make up these public interface names, I just
|
||||||
|
// approved them for inclusion into the code base. Sorry.
|
||||||
|
// --spearce
|
||||||
|
//
|
||||||
|
assertTrue("isa TransportHttp", t instanceof TransportHttp);
|
||||||
|
assertTrue("isa HttpTransport", t instanceof HttpTransport);
|
||||||
|
|
||||||
|
FetchConnection c = t.openFetch();
|
||||||
|
try {
|
||||||
|
map = c.getRefsMap();
|
||||||
|
} finally {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull("have map of refs", map);
|
||||||
|
assertEquals(2, map.size());
|
||||||
|
|
||||||
|
assertNotNull("has " + master, map.get(master));
|
||||||
|
assertEquals(B, map.get(master).getObjectId());
|
||||||
|
|
||||||
|
assertNotNull("has " + Constants.HEAD, map.get(Constants.HEAD));
|
||||||
|
assertEquals(B, map.get(Constants.HEAD).getObjectId());
|
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests();
|
||||||
|
assertEquals(2, requests.size());
|
||||||
|
assertEquals(0, getRequests(remoteURI, "git-upload-pack").size());
|
||||||
|
|
||||||
|
AccessEvent info = requests.get(0);
|
||||||
|
assertEquals("GET", info.getMethod());
|
||||||
|
assertEquals(join(remoteURI, "info/refs"), info.getPath());
|
||||||
|
assertEquals(0, info.getParameters().size());
|
||||||
|
assertNull("no service parameter", info.getParameter("service"));
|
||||||
|
assertEquals("no-cache", info.getRequestHeader(HDR_PRAGMA));
|
||||||
|
assertNotNull("has user-agent", info.getRequestHeader(HDR_USER_AGENT));
|
||||||
|
assertTrue("is jgit agent", info.getRequestHeader(HDR_USER_AGENT)
|
||||||
|
.startsWith("JGit/"));
|
||||||
|
assertEquals("*/*", info.getRequestHeader(HDR_ACCEPT));
|
||||||
|
assertEquals(200, info.getStatus());
|
||||||
|
assertEquals("text/plain;charset=UTF-8", info
|
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE));
|
||||||
|
|
||||||
|
AccessEvent head = requests.get(1);
|
||||||
|
assertEquals("GET", head.getMethod());
|
||||||
|
assertEquals(join(remoteURI, "HEAD"), head.getPath());
|
||||||
|
assertEquals(0, head.getParameters().size());
|
||||||
|
assertEquals(200, head.getStatus());
|
||||||
|
assertEquals("text/plain", head.getResponseHeader(HDR_CONTENT_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInitialClone_Small() throws Exception {
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
assertFalse(dst.hasObject(A_txt));
|
||||||
|
|
||||||
|
Transport t = Transport.open(dst, remoteURI);
|
||||||
|
((TransportHttp) t).setUseSmartHttp(false);
|
||||||
|
try {
|
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(dst.hasObject(A_txt));
|
||||||
|
assertEquals(B, dst.getRef(master).getObjectId());
|
||||||
|
fsck(dst, B);
|
||||||
|
|
||||||
|
List<AccessEvent> loose = getRequests(loose(remoteURI, A_txt));
|
||||||
|
assertEquals(1, loose.size());
|
||||||
|
assertEquals("GET", loose.get(0).getMethod());
|
||||||
|
assertEquals(0, loose.get(0).getParameters().size());
|
||||||
|
assertEquals(200, loose.get(0).getStatus());
|
||||||
|
assertEquals("application/x-git-loose-object", loose.get(0)
|
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInitialClone_Packed() throws Exception {
|
||||||
|
new TestRepository(remoteRepository).packAndPrune();
|
||||||
|
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
assertFalse(dst.hasObject(A_txt));
|
||||||
|
|
||||||
|
Transport t = Transport.open(dst, remoteURI);
|
||||||
|
((TransportHttp) t).setUseSmartHttp(false);
|
||||||
|
try {
|
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(dst.hasObject(A_txt));
|
||||||
|
assertEquals(B, dst.getRef(master).getObjectId());
|
||||||
|
fsck(dst, B);
|
||||||
|
|
||||||
|
List<AccessEvent> req;
|
||||||
|
|
||||||
|
req = getRequests(loose(remoteURI, B));
|
||||||
|
assertEquals(1, req.size());
|
||||||
|
assertEquals("GET", req.get(0).getMethod());
|
||||||
|
assertEquals(0, req.get(0).getParameters().size());
|
||||||
|
assertEquals(404, req.get(0).getStatus());
|
||||||
|
|
||||||
|
req = getRequests(join(remoteURI, "objects/info/packs"));
|
||||||
|
assertEquals(1, req.size());
|
||||||
|
assertEquals("GET", req.get(0).getMethod());
|
||||||
|
assertEquals(0, req.get(0).getParameters().size());
|
||||||
|
assertEquals(200, req.get(0).getStatus());
|
||||||
|
assertEquals("text/plain;charset=UTF-8", req.get(0).getResponseHeader(
|
||||||
|
HDR_CONTENT_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPushNotSupported() throws Exception {
|
||||||
|
final TestRepository src = createTestRepository();
|
||||||
|
final RevCommit Q = src.commit().create();
|
||||||
|
final Repository db = src.getRepository();
|
||||||
|
|
||||||
|
Transport t = Transport.open(db, remoteURI);
|
||||||
|
((TransportHttp) t).setUseSmartHttp(false);
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
t.push(NullProgressMonitor.INSTANCE, push(src, Q));
|
||||||
|
fail("push incorrectly completed against a smart server");
|
||||||
|
} catch (NotSupportedException nse) {
|
||||||
|
String exp = "smart HTTP push disabled";
|
||||||
|
assertEquals(exp, nse.getMessage());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2010, 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 java.net.HttpURLConnection;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.eclipse.jgit.http.server.glue.ErrorServlet;
|
||||||
|
import org.eclipse.jgit.http.test.util.AppServer;
|
||||||
|
|
||||||
|
public class ErrorServletTest extends TestCase {
|
||||||
|
private AppServer server;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
server = new AppServer();
|
||||||
|
|
||||||
|
ServletContextHandler ctx = server.addContext("/");
|
||||||
|
ctx.addServlet(new ServletHolder(new ErrorServlet(404)), "/404");
|
||||||
|
ctx.addServlet(new ServletHolder(new ErrorServlet(500)), "/500");
|
||||||
|
|
||||||
|
server.setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void tearDown() throws Exception {
|
||||||
|
if (server != null) {
|
||||||
|
server.tearDown();
|
||||||
|
}
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testHandler() throws Exception {
|
||||||
|
final URI uri = server.getURI();
|
||||||
|
assertEquals(404, ((HttpURLConnection) uri.resolve("/404").toURL()
|
||||||
|
.openConnection()).getResponseCode());
|
||||||
|
assertEquals(500, ((HttpURLConnection) uri.resolve("/500").toURL()
|
||||||
|
.openConnection()).getResponseCode());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010, 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 java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.FileResolver;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException;
|
||||||
|
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
|
||||||
|
public class FileResolverTest extends LocalDiskRepositoryTestCase {
|
||||||
|
public void testUnreasonableNames() throws ServiceNotEnabledException {
|
||||||
|
assertUnreasonable("");
|
||||||
|
assertUnreasonable("a\\b");
|
||||||
|
assertUnreasonable("../b");
|
||||||
|
assertUnreasonable("a/../b");
|
||||||
|
assertUnreasonable("a/./b");
|
||||||
|
assertUnreasonable("a//b");
|
||||||
|
|
||||||
|
if (new File("/foo").isAbsolute())
|
||||||
|
assertUnreasonable("/foo");
|
||||||
|
|
||||||
|
if (new File("//server/share").isAbsolute())
|
||||||
|
assertUnreasonable("//server/share");
|
||||||
|
|
||||||
|
if (new File("C:/windows").isAbsolute())
|
||||||
|
assertUnreasonable("C:/windows");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertUnreasonable(String name)
|
||||||
|
throws ServiceNotEnabledException {
|
||||||
|
FileResolver r = new FileResolver(new File("."), false);
|
||||||
|
try {
|
||||||
|
r.open(null, name);
|
||||||
|
fail("Opened unreasonable name \"" + name + "\"");
|
||||||
|
} catch (RepositoryNotFoundException e) {
|
||||||
|
assertEquals("repository not found: " + name, e.getMessage());
|
||||||
|
assertNull("has no cause", e.getCause());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testExportOk() throws IOException {
|
||||||
|
final Repository a = createBareRepository();
|
||||||
|
final String name = a.getDirectory().getName();
|
||||||
|
final File base = a.getDirectory().getParentFile();
|
||||||
|
final File export = new File(a.getDirectory(), "git-daemon-export-ok");
|
||||||
|
FileResolver resolver;
|
||||||
|
|
||||||
|
assertFalse("no git-daemon-export-ok", export.exists());
|
||||||
|
resolver = new FileResolver(base, false /* require flag */);
|
||||||
|
try {
|
||||||
|
resolver.open(null, name);
|
||||||
|
fail("opened non-exported repository");
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
assertEquals("Service not enabled", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
resolver = new FileResolver(base, true /* export all */);
|
||||||
|
try {
|
||||||
|
resolver.open(null, name).close();
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
fail("did not honor export-all flag");
|
||||||
|
}
|
||||||
|
|
||||||
|
export.createNewFile();
|
||||||
|
assertTrue("has git-daemon-export-ok", export.exists());
|
||||||
|
resolver = new FileResolver(base, false /* require flag */);
|
||||||
|
try {
|
||||||
|
resolver.open(null, name).close();
|
||||||
|
} catch (ServiceNotEnabledException e) {
|
||||||
|
fail("did not honor git-daemon-export-ok");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNotAGitRepository() throws IOException,
|
||||||
|
ServiceNotEnabledException {
|
||||||
|
final Repository a = createBareRepository();
|
||||||
|
final String name = a.getDirectory().getName() + "-not-a-git";
|
||||||
|
final File base = a.getDirectory().getParentFile();
|
||||||
|
FileResolver resolver = new FileResolver(base, false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
resolver.open(null, name);
|
||||||
|
} catch (RepositoryNotFoundException e) {
|
||||||
|
assertEquals("repository not found: " + name, e.getMessage());
|
||||||
|
|
||||||
|
Throwable why = e.getCause();
|
||||||
|
assertNotNull("has cause", why);
|
||||||
|
assertEquals("repository not found: "
|
||||||
|
+ new File(base, name).getAbsolutePath(), why.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010, 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 java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.eclipse.jgit.http.server.GitServlet;
|
||||||
|
import org.eclipse.jgit.http.test.util.AppServer;
|
||||||
|
import org.eclipse.jgit.http.test.util.MockServletConfig;
|
||||||
|
import org.eclipse.jgit.http.test.util.RecordingLogger;
|
||||||
|
|
||||||
|
public class GitServletInitTest extends TestCase {
|
||||||
|
private AppServer server;
|
||||||
|
|
||||||
|
protected void tearDown() throws Exception {
|
||||||
|
if (server != null) {
|
||||||
|
server.tearDown();
|
||||||
|
server = null;
|
||||||
|
}
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDefaultConstructor_NoBasePath() throws Exception {
|
||||||
|
GitServlet s = new GitServlet();
|
||||||
|
try {
|
||||||
|
s.init(new MockServletConfig());
|
||||||
|
fail("Init did not crash due to missing parameter");
|
||||||
|
} catch (ServletException e) {
|
||||||
|
assertTrue(e.getMessage().contains("base-path"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDefaultConstructor_WithBasePath() throws Exception {
|
||||||
|
MockServletConfig c = new MockServletConfig();
|
||||||
|
c.setInitParameter("base-path", ".");
|
||||||
|
c.setInitParameter("export-all", "false");
|
||||||
|
|
||||||
|
GitServlet s = new GitServlet();
|
||||||
|
s.init(c);
|
||||||
|
s.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInitUnderContainer_NoBasePath() throws Exception {
|
||||||
|
server = new AppServer();
|
||||||
|
|
||||||
|
ServletContextHandler app = server.addContext("/");
|
||||||
|
ServletHolder s = app.addServlet(GitServlet.class, "/git");
|
||||||
|
s.setInitOrder(1);
|
||||||
|
|
||||||
|
server.setUp();
|
||||||
|
|
||||||
|
List<RecordingLogger.Warning> events = RecordingLogger.getWarnings();
|
||||||
|
assertFalse("Servlet started without base-path", events.isEmpty());
|
||||||
|
|
||||||
|
Throwable why = events.get(0).getCause();
|
||||||
|
assertTrue("Caught ServletException", why instanceof ServletException);
|
||||||
|
assertTrue("Wanted base-path", why.getMessage().contains("base-path"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInitUnderContainer_WithBasePath() throws Exception {
|
||||||
|
server = new AppServer();
|
||||||
|
|
||||||
|
ServletContextHandler app = server.addContext("/");
|
||||||
|
ServletHolder s = app.addServlet(GitServlet.class, "/git");
|
||||||
|
s.setInitOrder(1);
|
||||||
|
s.setInitParameter("base-path", ".");
|
||||||
|
s.setInitParameter("export-all", "true");
|
||||||
|
|
||||||
|
server.setUp();
|
||||||
|
assertTrue("no warnings", RecordingLogger.getWarnings().isEmpty());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,328 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2010, 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 java.io.File;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.servlet.DefaultServlet;
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.eclipse.jgit.errors.NoRemoteRepositoryException;
|
||||||
|
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||||
|
import org.eclipse.jgit.errors.TransportException;
|
||||||
|
import org.eclipse.jgit.http.server.GitServlet;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.RepositoryResolver;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException;
|
||||||
|
import org.eclipse.jgit.http.test.util.AccessEvent;
|
||||||
|
import org.eclipse.jgit.http.test.util.HttpTestCase;
|
||||||
|
import org.eclipse.jgit.junit.TestRepository;
|
||||||
|
import org.eclipse.jgit.lib.Constants;
|
||||||
|
import org.eclipse.jgit.lib.Ref;
|
||||||
|
import org.eclipse.jgit.lib.RefUpdate;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
|
import org.eclipse.jgit.transport.FetchConnection;
|
||||||
|
import org.eclipse.jgit.transport.Transport;
|
||||||
|
import org.eclipse.jgit.transport.URIish;
|
||||||
|
|
||||||
|
public class HttpClientTests extends HttpTestCase {
|
||||||
|
private TestRepository remoteRepository;
|
||||||
|
|
||||||
|
private URIish dumbAuthNoneURI;
|
||||||
|
|
||||||
|
private URIish dumbAuthBasicURI;
|
||||||
|
|
||||||
|
private URIish smartAuthNoneURI;
|
||||||
|
|
||||||
|
private URIish smartAuthBasicURI;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
remoteRepository = createTestRepository();
|
||||||
|
remoteRepository.update(master, remoteRepository.commit().create());
|
||||||
|
|
||||||
|
ServletContextHandler dNone = dumb("/dnone");
|
||||||
|
ServletContextHandler dBasic = server.authBasic(dumb("/dbasic"));
|
||||||
|
|
||||||
|
ServletContextHandler sNone = smart("/snone");
|
||||||
|
ServletContextHandler sBasic = server.authBasic(smart("/sbasic"));
|
||||||
|
|
||||||
|
server.setUp();
|
||||||
|
|
||||||
|
final String srcName = nameOf(remoteRepository);
|
||||||
|
dumbAuthNoneURI = toURIish(dNone, srcName);
|
||||||
|
dumbAuthBasicURI = toURIish(dBasic, srcName);
|
||||||
|
|
||||||
|
smartAuthNoneURI = toURIish(sNone, srcName);
|
||||||
|
smartAuthBasicURI = toURIish(sBasic, srcName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ServletContextHandler dumb(final String path) {
|
||||||
|
final File srcGit = remoteRepository.getRepository().getDirectory();
|
||||||
|
final URI base = srcGit.getParentFile().toURI();
|
||||||
|
|
||||||
|
ServletContextHandler ctx = server.addContext(path);
|
||||||
|
ctx.setResourceBase(base.toString());
|
||||||
|
ctx.addServlet(DefaultServlet.class, "/");
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ServletContextHandler smart(final String path) {
|
||||||
|
GitServlet gs = new GitServlet();
|
||||||
|
gs.setRepositoryResolver(new RepositoryResolver() {
|
||||||
|
public Repository open(HttpServletRequest req, String name)
|
||||||
|
throws RepositoryNotFoundException,
|
||||||
|
ServiceNotEnabledException {
|
||||||
|
if (!name.equals(nameOf(remoteRepository)))
|
||||||
|
throw new RepositoryNotFoundException(name);
|
||||||
|
|
||||||
|
final Repository db = remoteRepository.getRepository();
|
||||||
|
db.incrementOpen();
|
||||||
|
return db;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ServletContextHandler ctx = server.addContext(path);
|
||||||
|
ctx.addServlet(new ServletHolder(gs), "/*");
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String nameOf(final TestRepository db) {
|
||||||
|
return db.getRepository().getDirectory().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRepositoryNotFound_Dumb() throws Exception {
|
||||||
|
URIish uri = toURIish("/dumb.none/not-found");
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
Transport t = Transport.open(dst, uri);
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
t.openFetch();
|
||||||
|
fail("connection opened to not found repository");
|
||||||
|
} catch (NoRemoteRepositoryException err) {
|
||||||
|
String exp = uri + ": " + uri
|
||||||
|
+ "/info/refs?service=git-upload-pack not found";
|
||||||
|
assertEquals(exp, err.getMessage());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRepositoryNotFound_Smart() throws Exception {
|
||||||
|
URIish uri = toURIish("/smart.none/not-found");
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
Transport t = Transport.open(dst, uri);
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
t.openFetch();
|
||||||
|
fail("connection opened to not found repository");
|
||||||
|
} catch (NoRemoteRepositoryException err) {
|
||||||
|
String exp = uri + ": " + uri
|
||||||
|
+ "/info/refs?service=git-upload-pack not found";
|
||||||
|
assertEquals(exp, err.getMessage());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListRemote_Dumb_DetachedHEAD() throws Exception {
|
||||||
|
Repository src = remoteRepository.getRepository();
|
||||||
|
RefUpdate u = src.updateRef(Constants.HEAD, true);
|
||||||
|
RevCommit Q = remoteRepository.commit().message("Q").create();
|
||||||
|
u.setNewObjectId(Q);
|
||||||
|
assertEquals(RefUpdate.Result.FORCED, u.forceUpdate());
|
||||||
|
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
Ref head;
|
||||||
|
Transport t = Transport.open(dst, dumbAuthNoneURI);
|
||||||
|
try {
|
||||||
|
FetchConnection c = t.openFetch();
|
||||||
|
try {
|
||||||
|
head = c.getRef(Constants.HEAD);
|
||||||
|
} finally {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
assertNotNull("has " + Constants.HEAD, head);
|
||||||
|
assertEquals(Q, head.getObjectId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListRemote_Dumb_NoHEAD() throws Exception {
|
||||||
|
Repository src = remoteRepository.getRepository();
|
||||||
|
File headref = new File(src.getDirectory(), Constants.HEAD);
|
||||||
|
assertTrue("HEAD used to be present", headref.delete());
|
||||||
|
assertFalse("HEAD is gone", headref.exists());
|
||||||
|
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
Ref head;
|
||||||
|
Transport t = Transport.open(dst, dumbAuthNoneURI);
|
||||||
|
try {
|
||||||
|
FetchConnection c = t.openFetch();
|
||||||
|
try {
|
||||||
|
head = c.getRef(Constants.HEAD);
|
||||||
|
} finally {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
assertNull("has no " + Constants.HEAD, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListRemote_Smart_DetachedHEAD() throws Exception {
|
||||||
|
Repository src = remoteRepository.getRepository();
|
||||||
|
RefUpdate u = src.updateRef(Constants.HEAD, true);
|
||||||
|
RevCommit Q = remoteRepository.commit().message("Q").create();
|
||||||
|
u.setNewObjectId(Q);
|
||||||
|
assertEquals(RefUpdate.Result.FORCED, u.forceUpdate());
|
||||||
|
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
Ref head;
|
||||||
|
Transport t = Transport.open(dst, smartAuthNoneURI);
|
||||||
|
try {
|
||||||
|
FetchConnection c = t.openFetch();
|
||||||
|
try {
|
||||||
|
head = c.getRef(Constants.HEAD);
|
||||||
|
} finally {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
assertNotNull("has " + Constants.HEAD, head);
|
||||||
|
assertEquals(Q, head.getObjectId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListRemote_Smart_WithQueryParameters() throws Exception {
|
||||||
|
URIish myURI = toURIish("/snone/do?r=1&p=test.git");
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
Transport t = Transport.open(dst, myURI);
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
t.openFetch();
|
||||||
|
fail("test did not fail to find repository as expected");
|
||||||
|
} catch (NoRemoteRepositoryException err) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests();
|
||||||
|
assertEquals(1, requests.size());
|
||||||
|
|
||||||
|
AccessEvent info = requests.get(0);
|
||||||
|
assertEquals("GET", info.getMethod());
|
||||||
|
assertEquals("/snone/do", info.getPath());
|
||||||
|
assertEquals(3, info.getParameters().size());
|
||||||
|
assertEquals("1", info.getParameter("r"));
|
||||||
|
assertEquals("test.git/info/refs", info.getParameter("p"));
|
||||||
|
assertEquals("git-upload-pack", info.getParameter("service"));
|
||||||
|
assertEquals(404, info.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListRemote_Dumb_NeedsAuth() throws Exception {
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
Transport t = Transport.open(dst, dumbAuthBasicURI);
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
t.openFetch();
|
||||||
|
fail("connection opened even info/refs needs auth basic");
|
||||||
|
} catch (TransportException err) {
|
||||||
|
String status = "401 Unauthorized";
|
||||||
|
String exp = dumbAuthBasicURI + ": " + status;
|
||||||
|
assertEquals(exp, err.getMessage());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListRemote_Smart_UploadPackNeedsAuth() throws Exception {
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
Transport t = Transport.open(dst, smartAuthBasicURI);
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
t.openFetch();
|
||||||
|
fail("connection opened even though service disabled");
|
||||||
|
} catch (TransportException err) {
|
||||||
|
String status = "401 Unauthorized";
|
||||||
|
String exp = smartAuthBasicURI + ": " + status;
|
||||||
|
assertEquals(exp, err.getMessage());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListRemote_Smart_UploadPackDisabled() throws Exception {
|
||||||
|
Repository src = remoteRepository.getRepository();
|
||||||
|
src.getConfig().setBoolean("http", null, "uploadpack", false);
|
||||||
|
src.getConfig().save();
|
||||||
|
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
Transport t = Transport.open(dst, smartAuthNoneURI);
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
t.openFetch();
|
||||||
|
fail("connection opened even though service disabled");
|
||||||
|
} catch (TransportException err) {
|
||||||
|
String exp = smartAuthNoneURI
|
||||||
|
+ ": git-upload-pack not permitted";
|
||||||
|
assertEquals(exp, err.getMessage());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,556 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2010, 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 static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_ENCODING;
|
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_LENGTH;
|
||||||
|
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_TYPE;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
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.FilterMapping;
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||||
|
import org.eclipse.jgit.errors.TransportException;
|
||||||
|
import org.eclipse.jgit.http.server.GitServlet;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.RepositoryResolver;
|
||||||
|
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException;
|
||||||
|
import org.eclipse.jgit.http.test.util.AccessEvent;
|
||||||
|
import org.eclipse.jgit.http.test.util.HttpTestCase;
|
||||||
|
import org.eclipse.jgit.junit.TestRepository;
|
||||||
|
import org.eclipse.jgit.junit.TestRng;
|
||||||
|
import org.eclipse.jgit.lib.Constants;
|
||||||
|
import org.eclipse.jgit.lib.NullProgressMonitor;
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.eclipse.jgit.lib.Ref;
|
||||||
|
import org.eclipse.jgit.lib.ReflogReader;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.lib.RepositoryConfig;
|
||||||
|
import org.eclipse.jgit.revwalk.RevBlob;
|
||||||
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
|
import org.eclipse.jgit.transport.FetchConnection;
|
||||||
|
import org.eclipse.jgit.transport.HttpTransport;
|
||||||
|
import org.eclipse.jgit.transport.RemoteRefUpdate;
|
||||||
|
import org.eclipse.jgit.transport.Transport;
|
||||||
|
import org.eclipse.jgit.transport.TransportHttp;
|
||||||
|
import org.eclipse.jgit.transport.URIish;
|
||||||
|
|
||||||
|
public class SmartClientSmartServerTest extends HttpTestCase {
|
||||||
|
private static final String HDR_TRANSFER_ENCODING = "Transfer-Encoding";
|
||||||
|
|
||||||
|
private Repository remoteRepository;
|
||||||
|
|
||||||
|
private URIish remoteURI;
|
||||||
|
|
||||||
|
private URIish brokenURI;
|
||||||
|
|
||||||
|
private RevBlob A_txt;
|
||||||
|
|
||||||
|
private RevCommit A, B;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
final TestRepository src = createTestRepository();
|
||||||
|
final String srcName = src.getRepository().getDirectory().getName();
|
||||||
|
|
||||||
|
ServletContextHandler app = server.addContext("/git");
|
||||||
|
GitServlet gs = new GitServlet();
|
||||||
|
gs.setRepositoryResolver(new RepositoryResolver() {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
app.addServlet(new ServletHolder(gs), "/*");
|
||||||
|
|
||||||
|
ServletContextHandler broken = server.addContext("/bad");
|
||||||
|
broken.addFilter(new FilterHolder(new Filter() {
|
||||||
|
public void doFilter(ServletRequest request,
|
||||||
|
ServletResponse response, FilterChain chain)
|
||||||
|
throws IOException, ServletException {
|
||||||
|
final HttpServletResponse r = (HttpServletResponse) response;
|
||||||
|
r.setContentType("text/plain");
|
||||||
|
r.setCharacterEncoding("UTF-8");
|
||||||
|
PrintWriter w = r.getWriter();
|
||||||
|
w.print("OK");
|
||||||
|
w.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(FilterConfig filterConfig) throws ServletException {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}), "/" + srcName + "/git-upload-pack", FilterMapping.DEFAULT);
|
||||||
|
broken.addServlet(new ServletHolder(gs), "/*");
|
||||||
|
|
||||||
|
server.setUp();
|
||||||
|
|
||||||
|
remoteRepository = src.getRepository();
|
||||||
|
remoteURI = toURIish(app, srcName);
|
||||||
|
brokenURI = toURIish(broken, 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);
|
||||||
|
|
||||||
|
src.update("refs/garbage/a/very/long/ref/name/to/compress", B);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListRemote() throws IOException {
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
|
||||||
|
assertEquals("http", remoteURI.getScheme());
|
||||||
|
|
||||||
|
Map<String, Ref> map;
|
||||||
|
Transport t = Transport.open(dst, remoteURI);
|
||||||
|
try {
|
||||||
|
// I didn't make up these public interface names, I just
|
||||||
|
// approved them for inclusion into the code base. Sorry.
|
||||||
|
// --spearce
|
||||||
|
//
|
||||||
|
assertTrue("isa TransportHttp", t instanceof TransportHttp);
|
||||||
|
assertTrue("isa HttpTransport", t instanceof HttpTransport);
|
||||||
|
|
||||||
|
FetchConnection c = t.openFetch();
|
||||||
|
try {
|
||||||
|
map = c.getRefsMap();
|
||||||
|
} finally {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull("have map of refs", map);
|
||||||
|
assertEquals(3, map.size());
|
||||||
|
|
||||||
|
assertNotNull("has " + master, map.get(master));
|
||||||
|
assertEquals(B, map.get(master).getObjectId());
|
||||||
|
|
||||||
|
assertNotNull("has " + Constants.HEAD, map.get(Constants.HEAD));
|
||||||
|
assertEquals(B, map.get(Constants.HEAD).getObjectId());
|
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests();
|
||||||
|
assertEquals(1, requests.size());
|
||||||
|
|
||||||
|
AccessEvent info = requests.get(0);
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInitialClone_Small() throws Exception {
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
assertFalse(dst.hasObject(A_txt));
|
||||||
|
|
||||||
|
Transport t = Transport.open(dst, remoteURI);
|
||||||
|
try {
|
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(dst.hasObject(A_txt));
|
||||||
|
assertEquals(B, dst.getRef(master).getObjectId());
|
||||||
|
fsck(dst, B);
|
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests();
|
||||||
|
assertEquals(2, requests.size());
|
||||||
|
|
||||||
|
AccessEvent info = requests.get(0);
|
||||||
|
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(1);
|
||||||
|
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));
|
||||||
|
assertNull("no compression (too small)", service
|
||||||
|
.getRequestHeader(HDR_CONTENT_ENCODING));
|
||||||
|
|
||||||
|
assertEquals(200, service.getStatus());
|
||||||
|
assertEquals("application/x-git-upload-pack-result", service
|
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE));
|
||||||
|
assertNull("no compression (never compressed)", service
|
||||||
|
.getResponseHeader(HDR_CONTENT_ENCODING));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFetchUpdateExisting() throws Exception {
|
||||||
|
// Bootstrap by doing the clone.
|
||||||
|
//
|
||||||
|
TestRepository dst = createTestRepository();
|
||||||
|
Transport t = Transport.open(dst.getRepository(), remoteURI);
|
||||||
|
try {
|
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
assertEquals(B, dst.getRepository().getRef(master).getObjectId());
|
||||||
|
List<AccessEvent> cloneRequests = getRequests();
|
||||||
|
|
||||||
|
// Force enough into the local client that enumeration will
|
||||||
|
// need multiple packets, but not too many to overflow and
|
||||||
|
// not pick up the ACK_COMMON message.
|
||||||
|
//
|
||||||
|
TestRepository.BranchBuilder b = dst.branch(master);
|
||||||
|
for (int i = 0; i < 32 - 1; i++)
|
||||||
|
b.commit().tick(3600 /* 1 hour */).message("c" + i).create();
|
||||||
|
|
||||||
|
// Create a new commit on the remote.
|
||||||
|
//
|
||||||
|
b = new TestRepository(remoteRepository).branch(master);
|
||||||
|
RevCommit Z = b.commit().message("Z").create();
|
||||||
|
|
||||||
|
// Now incrementally update.
|
||||||
|
//
|
||||||
|
t = Transport.open(dst.getRepository(), remoteURI);
|
||||||
|
try {
|
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
assertEquals(Z, dst.getRepository().getRef(master).getObjectId());
|
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests();
|
||||||
|
requests.removeAll(cloneRequests);
|
||||||
|
assertEquals(3, requests.size());
|
||||||
|
|
||||||
|
AccessEvent info = requests.get(0);
|
||||||
|
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));
|
||||||
|
|
||||||
|
// We should have needed two requests to perform the fetch
|
||||||
|
// due to the high number of local unknown commits.
|
||||||
|
//
|
||||||
|
AccessEvent service = requests.get(1);
|
||||||
|
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));
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInitialClone_BrokenServer() throws Exception {
|
||||||
|
Repository dst = createBareRepository();
|
||||||
|
assertFalse(dst.hasObject(A_txt));
|
||||||
|
|
||||||
|
Transport t = Transport.open(dst, brokenURI);
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
|
||||||
|
fail("fetch completed despite upload-pack being broken");
|
||||||
|
} catch (TransportException err) {
|
||||||
|
String exp = brokenURI + ": expected"
|
||||||
|
+ " Content-Type application/x-git-upload-pack-result;"
|
||||||
|
+ " received Content-Type text/plain;charset=UTF-8";
|
||||||
|
assertEquals(exp, err.getMessage());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests();
|
||||||
|
assertEquals(2, requests.size());
|
||||||
|
|
||||||
|
AccessEvent info = requests.get(0);
|
||||||
|
assertEquals("GET", info.getMethod());
|
||||||
|
assertEquals(join(brokenURI, "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));
|
||||||
|
|
||||||
|
AccessEvent service = requests.get(1);
|
||||||
|
assertEquals("POST", service.getMethod());
|
||||||
|
assertEquals(join(brokenURI, "git-upload-pack"), service.getPath());
|
||||||
|
assertEquals(0, service.getParameters().size());
|
||||||
|
assertEquals(200, service.getStatus());
|
||||||
|
assertEquals("text/plain;charset=UTF-8", service
|
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPush_NotAuthorized() throws Exception {
|
||||||
|
final TestRepository src = createTestRepository();
|
||||||
|
final RevBlob Q_txt = src.blob("new text");
|
||||||
|
final RevCommit Q = src.commit().add("Q", Q_txt).create();
|
||||||
|
final Repository db = src.getRepository();
|
||||||
|
final String dstName = Constants.R_HEADS + "new.branch";
|
||||||
|
Transport t;
|
||||||
|
|
||||||
|
// push anonymous shouldn't be allowed.
|
||||||
|
//
|
||||||
|
t = Transport.open(db, remoteURI);
|
||||||
|
try {
|
||||||
|
final String srcExpr = Q.name();
|
||||||
|
final boolean forceUpdate = false;
|
||||||
|
final String localName = null;
|
||||||
|
final ObjectId oldId = null;
|
||||||
|
|
||||||
|
RemoteRefUpdate u = new RemoteRefUpdate(src.getRepository(),
|
||||||
|
srcExpr, dstName, forceUpdate, localName, oldId);
|
||||||
|
try {
|
||||||
|
t.push(NullProgressMonitor.INSTANCE, Collections.singleton(u));
|
||||||
|
fail("anonymous push incorrectly accepted without error");
|
||||||
|
} catch (TransportException e) {
|
||||||
|
final String status = "401 Unauthorized";
|
||||||
|
final String exp = remoteURI.toString() + ": " + status;
|
||||||
|
assertEquals(exp, e.getMessage());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests();
|
||||||
|
assertEquals(1, requests.size());
|
||||||
|
|
||||||
|
AccessEvent info = requests.get(0);
|
||||||
|
assertEquals("GET", info.getMethod());
|
||||||
|
assertEquals(join(remoteURI, "info/refs"), info.getPath());
|
||||||
|
assertEquals(1, info.getParameters().size());
|
||||||
|
assertEquals("git-receive-pack", info.getParameter("service"));
|
||||||
|
assertEquals(401, info.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPush_CreateBranch() throws Exception {
|
||||||
|
final TestRepository src = createTestRepository();
|
||||||
|
final RevBlob Q_txt = src.blob("new text");
|
||||||
|
final RevCommit Q = src.commit().add("Q", Q_txt).create();
|
||||||
|
final Repository db = src.getRepository();
|
||||||
|
final String dstName = Constants.R_HEADS + "new.branch";
|
||||||
|
Transport t;
|
||||||
|
|
||||||
|
enableReceivePack();
|
||||||
|
|
||||||
|
t = Transport.open(db, remoteURI);
|
||||||
|
try {
|
||||||
|
final String srcExpr = Q.name();
|
||||||
|
final boolean forceUpdate = false;
|
||||||
|
final String localName = null;
|
||||||
|
final ObjectId oldId = null;
|
||||||
|
|
||||||
|
RemoteRefUpdate u = new RemoteRefUpdate(src.getRepository(),
|
||||||
|
srcExpr, dstName, forceUpdate, localName, oldId);
|
||||||
|
t.push(NullProgressMonitor.INSTANCE, Collections.singleton(u));
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(remoteRepository.hasObject(Q_txt));
|
||||||
|
assertNotNull("has " + dstName, remoteRepository.getRef(dstName));
|
||||||
|
assertEquals(Q, remoteRepository.getRef(dstName).getObjectId());
|
||||||
|
fsck(remoteRepository, Q);
|
||||||
|
|
||||||
|
final ReflogReader log = remoteRepository.getReflogReader(dstName);
|
||||||
|
assertNotNull("has log for " + dstName);
|
||||||
|
|
||||||
|
final ReflogReader.Entry last = log.getLastEntry();
|
||||||
|
assertNotNull("has last entry", last);
|
||||||
|
assertEquals(ObjectId.zeroId(), last.getOldId());
|
||||||
|
assertEquals(Q, last.getNewId());
|
||||||
|
assertEquals("anonymous", last.getWho().getName());
|
||||||
|
|
||||||
|
// Assumption: The host name we use to contact the server should
|
||||||
|
// be the server's own host name, because it should be the loopback
|
||||||
|
// network interface.
|
||||||
|
//
|
||||||
|
final String clientHost = remoteURI.getHost();
|
||||||
|
assertEquals("anonymous@" + clientHost, last.getWho().getEmailAddress());
|
||||||
|
assertEquals("push: created", last.getComment());
|
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests();
|
||||||
|
assertEquals(2, requests.size());
|
||||||
|
|
||||||
|
AccessEvent info = requests.get(0);
|
||||||
|
assertEquals("GET", info.getMethod());
|
||||||
|
assertEquals(join(remoteURI, "info/refs"), info.getPath());
|
||||||
|
assertEquals(1, info.getParameters().size());
|
||||||
|
assertEquals("git-receive-pack", info.getParameter("service"));
|
||||||
|
assertEquals(200, info.getStatus());
|
||||||
|
assertEquals("application/x-git-receive-pack-advertisement", info
|
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE));
|
||||||
|
|
||||||
|
AccessEvent service = requests.get(1);
|
||||||
|
assertEquals("POST", service.getMethod());
|
||||||
|
assertEquals(join(remoteURI, "git-receive-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-receive-pack-result", service
|
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPush_ChunkedEncoding() throws Exception {
|
||||||
|
final TestRepository src = createTestRepository();
|
||||||
|
final RevBlob Q_bin = src.blob(new TestRng("Q").nextBytes(128 * 1024));
|
||||||
|
final RevCommit Q = src.commit().add("Q", Q_bin).create();
|
||||||
|
final Repository db = src.getRepository();
|
||||||
|
final String dstName = Constants.R_HEADS + "new.branch";
|
||||||
|
Transport t;
|
||||||
|
|
||||||
|
enableReceivePack();
|
||||||
|
|
||||||
|
db.getConfig().setInt("core", null, "compression", 0);
|
||||||
|
db.getConfig().setInt("http", null, "postbuffer", 8 * 1024);
|
||||||
|
db.getConfig().save();
|
||||||
|
|
||||||
|
t = Transport.open(db, remoteURI);
|
||||||
|
try {
|
||||||
|
final String srcExpr = Q.name();
|
||||||
|
final boolean forceUpdate = false;
|
||||||
|
final String localName = null;
|
||||||
|
final ObjectId oldId = null;
|
||||||
|
|
||||||
|
RemoteRefUpdate u = new RemoteRefUpdate(src.getRepository(),
|
||||||
|
srcExpr, dstName, forceUpdate, localName, oldId);
|
||||||
|
t.push(NullProgressMonitor.INSTANCE, Collections.singleton(u));
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(remoteRepository.hasObject(Q_bin));
|
||||||
|
assertNotNull("has " + dstName, remoteRepository.getRef(dstName));
|
||||||
|
assertEquals(Q, remoteRepository.getRef(dstName).getObjectId());
|
||||||
|
fsck(remoteRepository, Q);
|
||||||
|
|
||||||
|
List<AccessEvent> requests = getRequests();
|
||||||
|
assertEquals(2, requests.size());
|
||||||
|
|
||||||
|
AccessEvent info = requests.get(0);
|
||||||
|
assertEquals("GET", info.getMethod());
|
||||||
|
assertEquals(join(remoteURI, "info/refs"), info.getPath());
|
||||||
|
assertEquals(1, info.getParameters().size());
|
||||||
|
assertEquals("git-receive-pack", info.getParameter("service"));
|
||||||
|
assertEquals(200, info.getStatus());
|
||||||
|
assertEquals("application/x-git-receive-pack-advertisement", info
|
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE));
|
||||||
|
|
||||||
|
AccessEvent service = requests.get(1);
|
||||||
|
assertEquals("POST", service.getMethod());
|
||||||
|
assertEquals(join(remoteURI, "git-receive-pack"), service.getPath());
|
||||||
|
assertEquals(0, service.getParameters().size());
|
||||||
|
assertNull("no content-length", service
|
||||||
|
.getRequestHeader(HDR_CONTENT_LENGTH));
|
||||||
|
assertEquals("chunked", service.getRequestHeader(HDR_TRANSFER_ENCODING));
|
||||||
|
|
||||||
|
assertEquals(200, service.getStatus());
|
||||||
|
assertEquals("application/x-git-receive-pack-result", service
|
||||||
|
.getResponseHeader(HDR_CONTENT_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enableReceivePack() throws IOException {
|
||||||
|
final RepositoryConfig cfg = remoteRepository.getConfig();
|
||||||
|
cfg.setBoolean("http", null, "receivepack", true);
|
||||||
|
cfg.save();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,181 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010, 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.util;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.Request;
|
||||||
|
import org.eclipse.jetty.server.Response;
|
||||||
|
|
||||||
|
/** A single request made through {@link AppServer}. */
|
||||||
|
public class AccessEvent {
|
||||||
|
private final String method;
|
||||||
|
|
||||||
|
private final String uri;
|
||||||
|
|
||||||
|
private final Map<String, String> requestHeaders;
|
||||||
|
|
||||||
|
private final Map<String, String[]> parameters;
|
||||||
|
|
||||||
|
private final int status;
|
||||||
|
|
||||||
|
private final Map<String, String> responseHeaders;
|
||||||
|
|
||||||
|
AccessEvent(final Request req, final Response rsp) {
|
||||||
|
method = req.getMethod();
|
||||||
|
uri = req.getRequestURI();
|
||||||
|
requestHeaders = cloneHeaders(req);
|
||||||
|
parameters = clone(req.getParameterMap());
|
||||||
|
|
||||||
|
status = rsp.getStatus();
|
||||||
|
responseHeaders = cloneHeaders(rsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> cloneHeaders(final Request req) {
|
||||||
|
Map<String, String> r = new TreeMap<String, String>();
|
||||||
|
Enumeration hn = req.getHeaderNames();
|
||||||
|
while (hn.hasMoreElements()) {
|
||||||
|
String key = (String) hn.nextElement();
|
||||||
|
if (!r.containsKey(key)) {
|
||||||
|
r.put(key, req.getHeader(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableMap(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> cloneHeaders(final Response rsp) {
|
||||||
|
Map<String, String> r = new TreeMap<String, String>();
|
||||||
|
Enumeration<String> hn = rsp.getHttpFields().getFieldNames();
|
||||||
|
while (hn.hasMoreElements()) {
|
||||||
|
String key = hn.nextElement();
|
||||||
|
if (!r.containsKey(key)) {
|
||||||
|
Enumeration<String> v = rsp.getHttpFields().getValues(key);
|
||||||
|
r.put(key, v.nextElement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableMap(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static Map<String, String[]> clone(Map parameterMap) {
|
||||||
|
return new TreeMap<String, String[]>(parameterMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return {@code "GET"} or {@code "POST"} */
|
||||||
|
public String getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return path of the file on the server, e.g. {@code /git/HEAD}. */
|
||||||
|
public String getPath() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* name of the request header to read.
|
||||||
|
* @return first value of the request header; null if not sent.
|
||||||
|
*/
|
||||||
|
public String getRequestHeader(String name) {
|
||||||
|
return requestHeaders.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* name of the request parameter to read.
|
||||||
|
* @return first value of the request parameter; null if not sent.
|
||||||
|
*/
|
||||||
|
public String getParameter(String name) {
|
||||||
|
String[] r = parameters.get(name);
|
||||||
|
return r != null && 1 <= r.length ? r[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return all parameters in the request. */
|
||||||
|
public Map<String, String[]> getParameters() {
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return HTTP status code of the response, e.g. 200, 403, 500. */
|
||||||
|
public int getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* name of the response header to read.
|
||||||
|
* @return first value of the response header; null if not sent.
|
||||||
|
*/
|
||||||
|
public String getResponseHeader(String name) {
|
||||||
|
return responseHeaders.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
b.append(method);
|
||||||
|
b.append(' ');
|
||||||
|
b.append(uri);
|
||||||
|
if (!parameters.isEmpty()) {
|
||||||
|
b.append('?');
|
||||||
|
boolean first = true;
|
||||||
|
for (Map.Entry<String, String[]> e : parameters.entrySet()) {
|
||||||
|
for (String val : e.getValue()) {
|
||||||
|
if (!first) {
|
||||||
|
b.append('&');
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
b.append(e.getKey());
|
||||||
|
b.append('=');
|
||||||
|
b.append(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.append(' ');
|
||||||
|
b.append(status);
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,295 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010, 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.util;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.security.Constraint;
|
||||||
|
import org.eclipse.jetty.http.security.Password;
|
||||||
|
import org.eclipse.jetty.security.Authenticator;
|
||||||
|
import org.eclipse.jetty.security.ConstraintMapping;
|
||||||
|
import org.eclipse.jetty.security.ConstraintSecurityHandler;
|
||||||
|
import org.eclipse.jetty.security.MappedLoginService;
|
||||||
|
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
|
||||||
|
import org.eclipse.jetty.server.Connector;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.server.UserIdentity;
|
||||||
|
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||||
|
import org.eclipse.jetty.server.handler.RequestLogHandler;
|
||||||
|
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||||
|
import org.eclipse.jgit.transport.URIish;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tiny web application server for unit testing.
|
||||||
|
* <p>
|
||||||
|
* Tests should start the server in their {@code setUp()} method and stop the
|
||||||
|
* server in their {@code tearDown()} method. Only while started the server's
|
||||||
|
* URL and/or port number can be obtained.
|
||||||
|
*/
|
||||||
|
public class AppServer {
|
||||||
|
/** Realm name for the secure access areas. */
|
||||||
|
public static final String realm = "Secure Area";
|
||||||
|
|
||||||
|
/** Username for secured access areas. */
|
||||||
|
public static final String username = "agitter";
|
||||||
|
|
||||||
|
/** Password for {@link #username} in secured access areas. */
|
||||||
|
public static final String password = "letmein";
|
||||||
|
|
||||||
|
static {
|
||||||
|
// Install a logger that throws warning messages.
|
||||||
|
//
|
||||||
|
final String prop = "org.eclipse.jetty.util.log.class";
|
||||||
|
System.setProperty(prop, RecordingLogger.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Server server;
|
||||||
|
|
||||||
|
private final Connector connector;
|
||||||
|
|
||||||
|
private final ContextHandlerCollection contexts;
|
||||||
|
|
||||||
|
private final TestRequestLog log;
|
||||||
|
|
||||||
|
public AppServer() {
|
||||||
|
connector = new SelectChannelConnector();
|
||||||
|
connector.setPort(0);
|
||||||
|
try {
|
||||||
|
final InetAddress me = InetAddress.getByName("localhost");
|
||||||
|
connector.setHost(me.getHostAddress());
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
throw new RuntimeException("Cannot find localhost", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need a handful of threads in the thread pool, otherwise
|
||||||
|
// our tests will deadlock when they can't open enough requests.
|
||||||
|
// In theory we only need 1 concurrent connection at a time, but
|
||||||
|
// I suspect the JRE isn't doing request pipelining on existing
|
||||||
|
// connections like we want it to.
|
||||||
|
//
|
||||||
|
final QueuedThreadPool pool = new QueuedThreadPool();
|
||||||
|
pool.setMinThreads(1);
|
||||||
|
pool.setMaxThreads(4);
|
||||||
|
pool.setMaxQueued(8);
|
||||||
|
|
||||||
|
contexts = new ContextHandlerCollection();
|
||||||
|
|
||||||
|
log = new TestRequestLog();
|
||||||
|
|
||||||
|
final RequestLogHandler logHandler = new RequestLogHandler();
|
||||||
|
logHandler.setHandler(contexts);
|
||||||
|
logHandler.setRequestLog(log);
|
||||||
|
|
||||||
|
server = new Server();
|
||||||
|
server.setConnectors(new Connector[] { connector });
|
||||||
|
server.setThreadPool(pool);
|
||||||
|
server.setHandler(logHandler);
|
||||||
|
|
||||||
|
server.setStopAtShutdown(false);
|
||||||
|
server.setGracefulShutdown(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new servlet context within the server.
|
||||||
|
* <p>
|
||||||
|
* This method should be invoked before the server is started, once for each
|
||||||
|
* context the caller wants to register.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* path of the context; use "/" for the root context if binding
|
||||||
|
* to the root is desired.
|
||||||
|
* @return the context to add servlets into.
|
||||||
|
*/
|
||||||
|
public ServletContextHandler addContext(String path) {
|
||||||
|
assertNotYetSetUp();
|
||||||
|
if ("".equals(path))
|
||||||
|
path = "/";
|
||||||
|
|
||||||
|
ServletContextHandler ctx = new ServletContextHandler();
|
||||||
|
ctx.setContextPath(path);
|
||||||
|
contexts.addHandler(ctx);
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServletContextHandler authBasic(ServletContextHandler ctx) {
|
||||||
|
assertNotYetSetUp();
|
||||||
|
auth(ctx, new BasicAuthenticator());
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void auth(ServletContextHandler ctx, Authenticator authType) {
|
||||||
|
final String role = "can-access";
|
||||||
|
|
||||||
|
MappedLoginService users = new MappedLoginService() {
|
||||||
|
@Override
|
||||||
|
protected UserIdentity loadUser(String who) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void loadUsers() throws IOException {
|
||||||
|
putUser(username, new Password(password), new String[] { role });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ConstraintMapping cm = new ConstraintMapping();
|
||||||
|
cm.setConstraint(new Constraint());
|
||||||
|
cm.getConstraint().setAuthenticate(true);
|
||||||
|
cm.getConstraint().setDataConstraint(Constraint.DC_NONE);
|
||||||
|
cm.getConstraint().setRoles(new String[] { role });
|
||||||
|
cm.setPathSpec("/*");
|
||||||
|
|
||||||
|
ConstraintSecurityHandler sec = new ConstraintSecurityHandler();
|
||||||
|
sec.setStrict(false);
|
||||||
|
sec.setRealmName(realm);
|
||||||
|
sec.setAuthenticator(authType);
|
||||||
|
sec.setLoginService(users);
|
||||||
|
sec.setConstraintMappings(new ConstraintMapping[] { cm });
|
||||||
|
sec.setHandler(ctx);
|
||||||
|
|
||||||
|
contexts.removeHandler(ctx);
|
||||||
|
contexts.addHandler(sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the server on a random local port.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
* the server cannot be started, testing is not possible.
|
||||||
|
*/
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
RecordingLogger.clear();
|
||||||
|
log.clear();
|
||||||
|
server.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown the server.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
* the server refuses to halt, or wasn't running.
|
||||||
|
*/
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
RecordingLogger.clear();
|
||||||
|
log.clear();
|
||||||
|
server.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the URI to reference this server.
|
||||||
|
* <p>
|
||||||
|
* The returned URI includes the proper host name and port number, but does
|
||||||
|
* not contain a path.
|
||||||
|
*
|
||||||
|
* @return URI to reference this server's root context.
|
||||||
|
*/
|
||||||
|
public URI getURI() {
|
||||||
|
assertAlreadySetUp();
|
||||||
|
String host = connector.getHost();
|
||||||
|
if (host.contains(":") && !host.startsWith("["))
|
||||||
|
host = "[" + host + "]";
|
||||||
|
final String uri = "http://" + host + ":" + getPort();
|
||||||
|
try {
|
||||||
|
return new URI(uri);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
throw new RuntimeException("Unexpected URI error on " + uri, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the local port number the server is listening on. */
|
||||||
|
public int getPort() {
|
||||||
|
assertAlreadySetUp();
|
||||||
|
return ((SelectChannelConnector) connector).getLocalPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return all requests since the server was started. */
|
||||||
|
public List<AccessEvent> getRequests() {
|
||||||
|
return new ArrayList<AccessEvent>(log.getEvents());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param base
|
||||||
|
* base URI used to access the server.
|
||||||
|
* @param path
|
||||||
|
* the path to locate requests for, relative to {@code base}.
|
||||||
|
* @return all requests which match the given path.
|
||||||
|
*/
|
||||||
|
public List<AccessEvent> getRequests(URIish base, String path) {
|
||||||
|
return getRequests(HttpTestCase.join(base, path));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param path
|
||||||
|
* the path to locate requests for.
|
||||||
|
* @return all requests which match the given path.
|
||||||
|
*/
|
||||||
|
public List<AccessEvent> getRequests(String path) {
|
||||||
|
ArrayList<AccessEvent> r = new ArrayList<AccessEvent>();
|
||||||
|
for (AccessEvent event : log.getEvents()) {
|
||||||
|
if (event.getPath().equals(path)) {
|
||||||
|
r.add(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertNotYetSetUp() {
|
||||||
|
Assert.assertFalse("server is not running", server.isRunning());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertAlreadySetUp() {
|
||||||
|
Assert.assertTrue("server is running", server.isRunning());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2010, 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.util;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
|
||||||
|
import org.eclipse.jgit.junit.TestRepository;
|
||||||
|
import org.eclipse.jgit.lib.AnyObjectId;
|
||||||
|
import org.eclipse.jgit.lib.Constants;
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
|
import org.eclipse.jgit.revwalk.RevObject;
|
||||||
|
import org.eclipse.jgit.transport.RefSpec;
|
||||||
|
import org.eclipse.jgit.transport.RemoteRefUpdate;
|
||||||
|
import org.eclipse.jgit.transport.URIish;
|
||||||
|
|
||||||
|
/** Base class for HTTP related transport testing. */
|
||||||
|
public abstract class HttpTestCase extends LocalDiskRepositoryTestCase {
|
||||||
|
protected static final String master = Constants.R_HEADS + Constants.MASTER;
|
||||||
|
|
||||||
|
/** In-memory application server; subclass must start. */
|
||||||
|
protected AppServer server;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
server = new AppServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void tearDown() throws Exception {
|
||||||
|
server.tearDown();
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TestRepository createTestRepository() throws Exception {
|
||||||
|
return new TestRepository(createBareRepository());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected URIish toURIish(String path) throws URISyntaxException {
|
||||||
|
URI u = server.getURI().resolve(path);
|
||||||
|
return new URIish(u.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected URIish toURIish(ServletContextHandler app, String name)
|
||||||
|
throws URISyntaxException {
|
||||||
|
String p = app.getContextPath();
|
||||||
|
if (!p.endsWith("/") && !name.startsWith("/"))
|
||||||
|
p += "/";
|
||||||
|
p += name;
|
||||||
|
return toURIish(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<AccessEvent> getRequests() {
|
||||||
|
return server.getRequests();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<AccessEvent> getRequests(URIish base, String path) {
|
||||||
|
return server.getRequests(base, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<AccessEvent> getRequests(String path) {
|
||||||
|
return server.getRequests(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void fsck(Repository db, RevObject... tips)
|
||||||
|
throws Exception {
|
||||||
|
new TestRepository(db).fsck(tips);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Set<RefSpec> mirror(String... refs) {
|
||||||
|
HashSet<RefSpec> r = new HashSet<RefSpec>();
|
||||||
|
for (String name : refs) {
|
||||||
|
RefSpec rs = new RefSpec(name);
|
||||||
|
rs = rs.setDestination(name);
|
||||||
|
rs = rs.setForceUpdate(true);
|
||||||
|
r.add(rs);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Collection<RemoteRefUpdate> push(TestRepository from,
|
||||||
|
RevCommit q) throws IOException {
|
||||||
|
final Repository db = from.getRepository();
|
||||||
|
final String srcExpr = q.name();
|
||||||
|
final String dstName = master;
|
||||||
|
final boolean forceUpdate = true;
|
||||||
|
final String localName = null;
|
||||||
|
final ObjectId oldId = null;
|
||||||
|
|
||||||
|
RemoteRefUpdate u = new RemoteRefUpdate(db, srcExpr, dstName,
|
||||||
|
forceUpdate, localName, oldId);
|
||||||
|
return Collections.singleton(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String loose(URIish base, AnyObjectId id) {
|
||||||
|
final String objectName = id.name();
|
||||||
|
final String d = objectName.substring(0, 2);
|
||||||
|
final String f = objectName.substring(2);
|
||||||
|
return join(base, "objects/" + d + "/" + f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String join(URIish base, String path) {
|
||||||
|
if (path.startsWith("/"))
|
||||||
|
fail("Cannot join absolute path " + path + " to URIish " + base);
|
||||||
|
|
||||||
|
String dir = base.getPath();
|
||||||
|
if (!dir.endsWith("/"))
|
||||||
|
dir += "/";
|
||||||
|
return dir + path;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010, 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.util;
|
||||||
|
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.ServletConfig;
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
public class MockServletConfig implements ServletConfig {
|
||||||
|
private final Map<String, String> parameters = new HashMap<String, String>();
|
||||||
|
|
||||||
|
public void setInitParameter(String name, String value) {
|
||||||
|
parameters.put(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInitParameter(String name) {
|
||||||
|
return parameters.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Enumeration getInitParameterNames() {
|
||||||
|
final Iterator<String> i = parameters.keySet().iterator();
|
||||||
|
return new Enumeration<String>() {
|
||||||
|
public boolean hasMoreElements() {
|
||||||
|
return i.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String nextElement() {
|
||||||
|
return i.next();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServletName() {
|
||||||
|
return "MOCK_SERVLET";
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServletContext getServletContext() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010, 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.util;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
|
||||||
|
/** Logs warnings into an array for later inspection. */
|
||||||
|
public class RecordingLogger implements Logger {
|
||||||
|
private static List<Warning> warnings = new ArrayList<Warning>();
|
||||||
|
|
||||||
|
/** Clear the warnings, automatically done by {@link AppServer#setUp()} */
|
||||||
|
public static void clear() {
|
||||||
|
synchronized (warnings) {
|
||||||
|
warnings.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the warnings (if any) from the last execution */
|
||||||
|
public static List<Warning> getWarnings() {
|
||||||
|
synchronized (warnings) {
|
||||||
|
ArrayList<Warning> copy = new ArrayList<Warning>(warnings);
|
||||||
|
return Collections.unmodifiableList(copy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public static class Warning extends Exception {
|
||||||
|
public Warning(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Warning(String msg, Throwable cause) {
|
||||||
|
super(msg, cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public RecordingLogger() {
|
||||||
|
this("");
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecordingLogger(final String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger getLogger(@SuppressWarnings("hiding") String name) {
|
||||||
|
return new RecordingLogger(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void warn(String msg, Object arg0, Object arg1) {
|
||||||
|
synchronized (warnings) {
|
||||||
|
warnings.add(new Warning(MessageFormat.format(msg, arg0, arg1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void warn(String msg, Throwable th) {
|
||||||
|
synchronized (warnings) {
|
||||||
|
warnings.add(new Warning(msg, th));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void warn(String msg) {
|
||||||
|
synchronized (warnings) {
|
||||||
|
warnings.add(new Warning(msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void debug(String msg, Object arg0, Object arg1) {
|
||||||
|
// Ignore (not relevant to test failures)
|
||||||
|
}
|
||||||
|
|
||||||
|
public void debug(String msg, Throwable th) {
|
||||||
|
// Ignore (not relevant to test failures)
|
||||||
|
}
|
||||||
|
|
||||||
|
public void debug(String msg) {
|
||||||
|
// Ignore (not relevant to test failures)
|
||||||
|
}
|
||||||
|
|
||||||
|
public void info(String msg, Object arg0, Object arg1) {
|
||||||
|
// Ignore (not relevant to test failures)
|
||||||
|
}
|
||||||
|
|
||||||
|
public void info(String msg) {
|
||||||
|
// Ignore (not relevant to test failures)
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDebugEnabled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDebugEnabled(boolean enabled) {
|
||||||
|
// Ignore (not relevant to test failures)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010, 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.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.Request;
|
||||||
|
import org.eclipse.jetty.server.RequestLog;
|
||||||
|
import org.eclipse.jetty.server.Response;
|
||||||
|
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||||
|
|
||||||
|
/** Logs request made through {@link AppServer}. */
|
||||||
|
class TestRequestLog extends AbstractLifeCycle implements RequestLog {
|
||||||
|
private final List<AccessEvent> events = new ArrayList<AccessEvent>();
|
||||||
|
|
||||||
|
/** Reset the log back to its original empty state. */
|
||||||
|
synchronized void clear() {
|
||||||
|
events.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return all of the events made since the last clear. */
|
||||||
|
synchronized List<AccessEvent> getEvents() {
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void log(Request request, Response response) {
|
||||||
|
events.add(new AccessEvent(request, response));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2009, Google Inc.
|
* Copyright (C) 2009-2010, Google Inc.
|
||||||
* Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
|
* Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
|
||||||
* Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
|
* Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
|
||||||
* and other copyright owners as documented in the project's IP log.
|
* and other copyright owners as documented in the project's IP log.
|
||||||
|
@ -57,8 +57,10 @@
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.AnyObjectId;
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
import org.eclipse.jgit.lib.FileBasedConfig;
|
import org.eclipse.jgit.lib.FileBasedConfig;
|
||||||
import org.eclipse.jgit.lib.PersonIdent;
|
import org.eclipse.jgit.lib.PersonIdent;
|
||||||
|
@ -404,6 +406,14 @@ protected String read(final File f) throws IOException {
|
||||||
return new String(body, 0, body.length, "UTF-8");
|
return new String(body, 0, body.length, "UTF-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static void assertEquals(AnyObjectId exp, AnyObjectId act) {
|
||||||
|
if (exp != null)
|
||||||
|
exp = exp.copy();
|
||||||
|
if (act != null)
|
||||||
|
act = act.copy();
|
||||||
|
Assert.assertEquals(exp, act);
|
||||||
|
}
|
||||||
|
|
||||||
private static String[] toEnvArray(final Map<String, String> env) {
|
private static String[] toEnvArray(final Map<String, String> env) {
|
||||||
final String[] envp = new String[env.size()];
|
final String[] envp = new String[env.size()];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
|
@ -44,11 +44,15 @@
|
||||||
package org.eclipse.jgit.junit;
|
package org.eclipse.jgit.junit;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.MessageDigest;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
import junit.framework.AssertionFailedError;
|
import junit.framework.AssertionFailedError;
|
||||||
|
@ -60,21 +64,30 @@
|
||||||
import org.eclipse.jgit.dircache.DirCacheEditor.DeletePath;
|
import org.eclipse.jgit.dircache.DirCacheEditor.DeletePath;
|
||||||
import org.eclipse.jgit.dircache.DirCacheEditor.DeleteTree;
|
import org.eclipse.jgit.dircache.DirCacheEditor.DeleteTree;
|
||||||
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
|
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
|
||||||
|
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
||||||
|
import org.eclipse.jgit.errors.MissingObjectException;
|
||||||
import org.eclipse.jgit.errors.ObjectWritingException;
|
import org.eclipse.jgit.errors.ObjectWritingException;
|
||||||
import org.eclipse.jgit.lib.AnyObjectId;
|
import org.eclipse.jgit.lib.AnyObjectId;
|
||||||
import org.eclipse.jgit.lib.Commit;
|
import org.eclipse.jgit.lib.Commit;
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
import org.eclipse.jgit.lib.FileMode;
|
import org.eclipse.jgit.lib.FileMode;
|
||||||
import org.eclipse.jgit.lib.LockFile;
|
import org.eclipse.jgit.lib.LockFile;
|
||||||
|
import org.eclipse.jgit.lib.NullProgressMonitor;
|
||||||
|
import org.eclipse.jgit.lib.ObjectChecker;
|
||||||
|
import org.eclipse.jgit.lib.ObjectDatabase;
|
||||||
import org.eclipse.jgit.lib.ObjectDirectory;
|
import org.eclipse.jgit.lib.ObjectDirectory;
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
import org.eclipse.jgit.lib.ObjectWriter;
|
import org.eclipse.jgit.lib.ObjectWriter;
|
||||||
|
import org.eclipse.jgit.lib.PackFile;
|
||||||
|
import org.eclipse.jgit.lib.PackWriter;
|
||||||
import org.eclipse.jgit.lib.PersonIdent;
|
import org.eclipse.jgit.lib.PersonIdent;
|
||||||
import org.eclipse.jgit.lib.Ref;
|
import org.eclipse.jgit.lib.Ref;
|
||||||
import org.eclipse.jgit.lib.RefUpdate;
|
import org.eclipse.jgit.lib.RefUpdate;
|
||||||
import org.eclipse.jgit.lib.RefWriter;
|
import org.eclipse.jgit.lib.RefWriter;
|
||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
import org.eclipse.jgit.lib.Tag;
|
import org.eclipse.jgit.lib.Tag;
|
||||||
|
import org.eclipse.jgit.lib.PackIndex.MutableEntry;
|
||||||
|
import org.eclipse.jgit.revwalk.ObjectWalk;
|
||||||
import org.eclipse.jgit.revwalk.RevBlob;
|
import org.eclipse.jgit.revwalk.RevBlob;
|
||||||
import org.eclipse.jgit.revwalk.RevCommit;
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
import org.eclipse.jgit.revwalk.RevObject;
|
import org.eclipse.jgit.revwalk.RevObject;
|
||||||
|
@ -428,26 +441,25 @@ public <T extends AnyObjectId> T update(String ref, T obj) throws Exception {
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public void updateServerInfo() throws Exception {
|
public void updateServerInfo() throws Exception {
|
||||||
if (db.getObjectDatabase() instanceof ObjectDirectory) {
|
final ObjectDatabase odb = db.getObjectDatabase();
|
||||||
|
if (odb instanceof ObjectDirectory) {
|
||||||
RefWriter rw = new RefWriter(db.getAllRefs().values()) {
|
RefWriter rw = new RefWriter(db.getAllRefs().values()) {
|
||||||
@Override
|
@Override
|
||||||
protected void writeFile(final String name, final byte[] bin)
|
protected void writeFile(final String name, final byte[] bin)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final File p = new File(db.getDirectory(), name);
|
TestRepository.this.writeFile(name, bin);
|
||||||
final LockFile lck = new LockFile(p);
|
|
||||||
if (!lck.lock())
|
|
||||||
throw new ObjectWritingException("Can't write " + p);
|
|
||||||
try {
|
|
||||||
lck.write(bin);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new ObjectWritingException("Can't write " + p);
|
|
||||||
}
|
|
||||||
if (!lck.commit())
|
|
||||||
throw new ObjectWritingException("Can't write " + p);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
rw.writePackedRefs();
|
rw.writePackedRefs();
|
||||||
rw.writeInfoRefs();
|
rw.writeInfoRefs();
|
||||||
|
|
||||||
|
final StringBuilder w = new StringBuilder();
|
||||||
|
for (PackFile p : ((ObjectDirectory) odb).getPacks()) {
|
||||||
|
w.append("P ");
|
||||||
|
w.append(p.getPackFile().getName());
|
||||||
|
w.append('\n');
|
||||||
|
}
|
||||||
|
writeFile("objects/info/packs", Constants.encodeASCII(w.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,6 +496,132 @@ public BranchBuilder branch(String ref) {
|
||||||
return new BranchBuilder(ref);
|
return new BranchBuilder(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run consistency checks against the object database.
|
||||||
|
* <p>
|
||||||
|
* This method completes silently if the checks pass. A temporary revision
|
||||||
|
* pool is constructed during the checking.
|
||||||
|
*
|
||||||
|
* @param tips
|
||||||
|
* the tips to start checking from; if not supplied the refs of
|
||||||
|
* the repository are used instead.
|
||||||
|
* @throws MissingObjectException
|
||||||
|
* @throws IncorrectObjectTypeException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void fsck(RevObject... tips) throws MissingObjectException,
|
||||||
|
IncorrectObjectTypeException, IOException {
|
||||||
|
ObjectWalk ow = new ObjectWalk(db);
|
||||||
|
if (tips.length != 0) {
|
||||||
|
for (RevObject o : tips)
|
||||||
|
ow.markStart(ow.parseAny(o));
|
||||||
|
} else {
|
||||||
|
for (Ref r : db.getAllRefs().values())
|
||||||
|
ow.markStart(ow.parseAny(r.getObjectId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectChecker oc = new ObjectChecker();
|
||||||
|
for (;;) {
|
||||||
|
final RevCommit o = ow.next();
|
||||||
|
if (o == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
final byte[] bin = db.openObject(o).getCachedBytes();
|
||||||
|
oc.checkCommit(bin);
|
||||||
|
assertHash(o, bin);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
final RevObject o = ow.nextObject();
|
||||||
|
if (o == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
final byte[] bin = db.openObject(o).getCachedBytes();
|
||||||
|
oc.check(o.getType(), bin);
|
||||||
|
assertHash(o, bin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assertHash(RevObject id, byte[] bin) {
|
||||||
|
MessageDigest md = Constants.newMessageDigest();
|
||||||
|
md.update(Constants.encodedTypeString(id.getType()));
|
||||||
|
md.update((byte) ' ');
|
||||||
|
md.update(Constants.encodeASCII(bin.length));
|
||||||
|
md.update((byte) 0);
|
||||||
|
md.update(bin);
|
||||||
|
Assert.assertEquals(id.copy(), ObjectId.fromRaw(md.digest()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pack all reachable objects in the repository into a single pack file.
|
||||||
|
* <p>
|
||||||
|
* All loose objects are automatically pruned. Existing packs however are
|
||||||
|
* not removed.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void packAndPrune() throws Exception {
|
||||||
|
final ObjectDirectory odb = (ObjectDirectory) db.getObjectDatabase();
|
||||||
|
final PackWriter pw = new PackWriter(db, NullProgressMonitor.INSTANCE);
|
||||||
|
|
||||||
|
Set<ObjectId> all = new HashSet<ObjectId>();
|
||||||
|
for (Ref r : db.getAllRefs().values())
|
||||||
|
all.add(r.getObjectId());
|
||||||
|
pw.preparePack(all, Collections.<ObjectId> emptySet());
|
||||||
|
|
||||||
|
final ObjectId name = pw.computeName();
|
||||||
|
FileOutputStream out;
|
||||||
|
|
||||||
|
final File pack = nameFor(odb, name, ".pack");
|
||||||
|
out = new FileOutputStream(pack);
|
||||||
|
try {
|
||||||
|
pw.writePack(out);
|
||||||
|
} finally {
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
pack.setReadOnly();
|
||||||
|
|
||||||
|
final File idx = nameFor(odb, name, ".idx");
|
||||||
|
out = new FileOutputStream(idx);
|
||||||
|
try {
|
||||||
|
pw.writeIndex(out);
|
||||||
|
} finally {
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
idx.setReadOnly();
|
||||||
|
|
||||||
|
odb.openPack(pack, idx);
|
||||||
|
updateServerInfo();
|
||||||
|
prunePacked(odb);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prunePacked(ObjectDirectory odb) {
|
||||||
|
for (PackFile p : odb.getPacks()) {
|
||||||
|
for (MutableEntry e : p)
|
||||||
|
odb.fileFor(e.toObjectId()).delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static File nameFor(ObjectDirectory odb, ObjectId name, String t) {
|
||||||
|
File packdir = new File(odb.getDirectory(), "pack");
|
||||||
|
return new File(packdir, "pack-" + name.name() + t);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeFile(final String name, final byte[] bin)
|
||||||
|
throws IOException, ObjectWritingException {
|
||||||
|
final File p = new File(db.getDirectory(), name);
|
||||||
|
final LockFile lck = new LockFile(p);
|
||||||
|
if (!lck.lock())
|
||||||
|
throw new ObjectWritingException("Can't write " + p);
|
||||||
|
try {
|
||||||
|
lck.write(bin);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new ObjectWritingException("Can't write " + p);
|
||||||
|
}
|
||||||
|
if (!lck.commit())
|
||||||
|
throw new ObjectWritingException("Can't write " + p);
|
||||||
|
}
|
||||||
|
|
||||||
/** Helper to build a branch with one or more commits */
|
/** Helper to build a branch with one or more commits */
|
||||||
public class BranchBuilder {
|
public class BranchBuilder {
|
||||||
private final String ref;
|
private final String ref;
|
||||||
|
|
|
@ -155,6 +155,8 @@ private static class HttpConfig {
|
||||||
|
|
||||||
private final ProxySelector proxySelector;
|
private final ProxySelector proxySelector;
|
||||||
|
|
||||||
|
private boolean useSmartHttp = true;
|
||||||
|
|
||||||
TransportHttp(final Repository local, final URIish uri)
|
TransportHttp(final Repository local, final URIish uri)
|
||||||
throws NotSupportedException {
|
throws NotSupportedException {
|
||||||
super(local, uri);
|
super(local, uri);
|
||||||
|
@ -171,6 +173,20 @@ private static class HttpConfig {
|
||||||
proxySelector = ProxySelector.getDefault();
|
proxySelector = ProxySelector.getDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle whether or not smart HTTP transport should be used.
|
||||||
|
* <p>
|
||||||
|
* This flag exists primarily to support backwards compatibility testing
|
||||||
|
* within a testing framework, there is no need to modify it in most
|
||||||
|
* applications.
|
||||||
|
*
|
||||||
|
* @param on
|
||||||
|
* if {@code true} (default), smart HTTP is enabled.
|
||||||
|
*/
|
||||||
|
public void setUseSmartHttp(final boolean on) {
|
||||||
|
useSmartHttp = on;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FetchConnection openFetch() throws TransportException,
|
public FetchConnection openFetch() throws TransportException,
|
||||||
NotSupportedException {
|
NotSupportedException {
|
||||||
|
@ -271,6 +287,10 @@ public PushConnection openPush() throws NotSupportedException,
|
||||||
readSmartHeaders(in, service);
|
readSmartHeaders(in, service);
|
||||||
return new SmartHttpPushConnection(in);
|
return new SmartHttpPushConnection(in);
|
||||||
|
|
||||||
|
} else if (!useSmartHttp) {
|
||||||
|
final String msg = "smart HTTP push disabled";
|
||||||
|
throw new NotSupportedException(msg);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
final String msg = "remote does not support smart HTTP push";
|
final String msg = "remote does not support smart HTTP push";
|
||||||
throw new NotSupportedException(msg);
|
throw new NotSupportedException(msg);
|
||||||
|
@ -303,9 +323,11 @@ private HttpURLConnection connect(final String service)
|
||||||
b.append('/');
|
b.append('/');
|
||||||
b.append(Constants.INFO_REFS);
|
b.append(Constants.INFO_REFS);
|
||||||
|
|
||||||
b.append(b.indexOf("?") < 0 ? '?' : '&');
|
if (useSmartHttp) {
|
||||||
b.append("service=");
|
b.append(b.indexOf("?") < 0 ? '?' : '&');
|
||||||
b.append(service);
|
b.append("service=");
|
||||||
|
b.append(service);
|
||||||
|
}
|
||||||
|
|
||||||
u = new URL(b.toString());
|
u = new URL(b.toString());
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
|
@ -314,8 +336,12 @@ private HttpURLConnection connect(final String service)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final HttpURLConnection conn = httpOpen(u);
|
final HttpURLConnection conn = httpOpen(u);
|
||||||
String expType = "application/x-" + service + "-advertisement";
|
if (useSmartHttp) {
|
||||||
conn.setRequestProperty(HDR_ACCEPT, expType + ", */*");
|
String expType = "application/x-" + service + "-advertisement";
|
||||||
|
conn.setRequestProperty(HDR_ACCEPT, expType + ", */*");
|
||||||
|
} else {
|
||||||
|
conn.setRequestProperty(HDR_ACCEPT, "*/*");
|
||||||
|
}
|
||||||
final int status = HttpSupport.response(conn);
|
final int status = HttpSupport.response(conn);
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case HttpURLConnection.HTTP_OK:
|
case HttpURLConnection.HTTP_OK:
|
||||||
|
|
10
pom.xml
10
pom.xml
|
@ -138,6 +138,8 @@
|
||||||
|
|
||||||
<servlet-api-CQ>CQ 3565</servlet-api-CQ>
|
<servlet-api-CQ>CQ 3565</servlet-api-CQ>
|
||||||
<servlet-api-version>2.5</servlet-api-version>
|
<servlet-api-version>2.5</servlet-api-version>
|
||||||
|
|
||||||
|
<jetty-version>7.0.1.v20091125</jetty-version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -265,6 +267,12 @@
|
||||||
<artifactId>servlet-api</artifactId>
|
<artifactId>servlet-api</artifactId>
|
||||||
<version>${servlet-api-version}</version>
|
<version>${servlet-api-version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-servlet</artifactId>
|
||||||
|
<version>${jetty-version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
@ -298,6 +306,8 @@
|
||||||
<module>org.eclipse.jgit.http.server</module>
|
<module>org.eclipse.jgit.http.server</module>
|
||||||
<module>org.eclipse.jgit.pgm</module>
|
<module>org.eclipse.jgit.pgm</module>
|
||||||
<module>org.eclipse.jgit.junit</module>
|
<module>org.eclipse.jgit.junit</module>
|
||||||
|
|
||||||
<module>org.eclipse.jgit.test</module>
|
<module>org.eclipse.jgit.test</module>
|
||||||
|
<module>org.eclipse.jgit.http.test</module>
|
||||||
</modules>
|
</modules>
|
||||||
</project>
|
</project>
|
||||||
|
|
Loading…
Reference in New Issue