Browse Source

Revert "Client-side protocol V2 support for fetching"

This reverts commit f802f06e7f.

I had misunderstood how protocol V2 works. This implementation only
works if the negotiation during fetch is done in one round.

Fixing this is substantial work in BasePackFetchConnection. Basically
I think I'd have to change back negotiate to the V0 version, and have
a doFetch() that does

  if protocol V2
    doFetchV2()
  else
    doFetchV0()

with doFetchV0 the old code, and doFetchV2 completely new.

Plus there would need to be a HTTP test case requiring several
negotiation rounds.

This is a couple of days work at least, and I don't know when I will
have the time to revisit this. So although the rest of the code is
fine I prefer to back this out completely and not leave a only half
working implementation in the code for an indeterminate time.

Bug: 553083
Change-Id: Icbbbb09882b3b83f9897deac4a06d5f8dc99d84e
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
tags/v5.10.0.202011041322-m2
Thomas Wolf 3 years ago
parent
commit
d69fb4d4ac
25 changed files with 220 additions and 1301 deletions
  1. 0
    99
      org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AllProtocolsHttpTestCase.java
  2. 4
    6
      org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientDumbServerTest.java
  3. 4
    6
      org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
  4. 7
    10
      org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java
  5. 72
    181
      org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
  6. 0
    24
      org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshProtocol2Test.java
  7. 4
    13
      org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSession.java
  8. 0
    26
      org.eclipse.jgit.ssh.jsch.test/tst/org/eclipse/jgit/transport/JSchSshProtocol2Test.java
  9. 4
    21
      org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschSession.java
  10. 0
    1
      org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
  11. 1
    1
      org.eclipse.jgit/src/org/eclipse/jgit/api/LsRemoteCommand.java
  12. 0
    1
      org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
  13. 52
    307
      org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java
  14. 16
    171
      org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
  15. 3
    26
      org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java
  16. 0
    68
      org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java
  17. 2
    18
      org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineIn.java
  18. 2
    6
      org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java
  19. 0
    45
      org.eclipse.jgit/src/org/eclipse/jgit/transport/RemoteSession2.java
  20. 0
    43
      org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
  21. 4
    29
      org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitAnon.java
  22. 10
    55
      org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
  23. 25
    92
      org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
  24. 6
    44
      org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
  25. 4
    8
      org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java

+ 0
- 99
org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/AllProtocolsHttpTestCase.java View File

@@ -1,99 +0,0 @@
/*
* Copyright (C) 2020, Thomas Wolf <thomas.wolf@paranor.ch> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
* https://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
package org.eclipse.jgit.http.test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.jgit.junit.http.HttpTestCase;
import org.eclipse.jgit.transport.HttpTransport;
import org.eclipse.jgit.transport.http.HttpConnectionFactory;
import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory;
import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/**
* Abstract test base class for running HTTP-related tests with all connection
* factories provided in JGit and with both protocol V0 and V2.
*/
@Ignore
@RunWith(Parameterized.class)
public abstract class AllProtocolsHttpTestCase extends HttpTestCase {

protected static class TestParameters {

public final HttpConnectionFactory factory;

public final boolean enableProtocolV2;

public TestParameters(HttpConnectionFactory factory,
boolean enableProtocolV2) {
this.factory = factory;
this.enableProtocolV2 = enableProtocolV2;
}

@Override
public String toString() {
return factory.toString() + " protocol "
+ (enableProtocolV2 ? "V2" : "V0");
}
}

@Parameters(name = "{0}")
public static Collection<TestParameters> data() {
// run all tests with both connection factories we have
HttpConnectionFactory[] factories = new HttpConnectionFactory[] {
new JDKHttpConnectionFactory() {

@Override
public String toString() {
return this.getClass().getSuperclass().getName();
}
}, new HttpClientConnectionFactory() {

@Override
public String toString() {
return this.getClass().getSuperclass().getName();
}
} };
List<TestParameters> result = new ArrayList<>();
for (HttpConnectionFactory factory : factories) {
result.add(new TestParameters(factory, false));
result.add(new TestParameters(factory, true));
}
return result;
}

protected final boolean enableProtocolV2;

protected AllProtocolsHttpTestCase(TestParameters params) {
HttpTransport.setConnectionFactory(params.factory);
enableProtocolV2 = params.enableProtocolV2;
}

private static HttpConnectionFactory originalFactory;

@BeforeClass
public static void saveConnectionFactory() {
originalFactory = HttpTransport.getConnectionFactory();
}

@AfterClass
public static void restoreConnectionFactory() {
HttpTransport.setConnectionFactory(originalFactory);
}

}

+ 4
- 6
org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientDumbServerTest.java View File

@@ -42,10 +42,11 @@ import org.eclipse.jgit.transport.HttpTransport;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.TransportHttp;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.http.HttpConnectionFactory;
import org.junit.Before;
import org.junit.Test;

public class DumbClientDumbServerTest extends AllProtocolsHttpTestCase {
public class DumbClientDumbServerTest extends AllFactoriesHttpTestCase {
private Repository remoteRepository;

private URIish remoteURI;
@@ -54,8 +55,8 @@ public class DumbClientDumbServerTest extends AllProtocolsHttpTestCase {

private RevCommit A, B;

public DumbClientDumbServerTest(TestParameters params) {
super(params);
public DumbClientDumbServerTest(HttpConnectionFactory cf) {
super(cf);
}

@Override
@@ -76,9 +77,6 @@ public class DumbClientDumbServerTest extends AllProtocolsHttpTestCase {

remoteRepository = src.getRepository();
remoteURI = toURIish(app, srcGit.getName());
if (enableProtocolV2) {
remoteRepository.getConfig().setInt("protocol", null, "version", 2);
}

A_txt = src.blob("A");
A = src.commit().add("A_txt", A_txt).create();

+ 4
- 6
org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java View File

@@ -42,10 +42,11 @@ import org.eclipse.jgit.transport.HttpTransport;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.TransportHttp;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.http.HttpConnectionFactory;
import org.junit.Before;
import org.junit.Test;

public class DumbClientSmartServerTest extends AllProtocolsHttpTestCase {
public class DumbClientSmartServerTest extends AllFactoriesHttpTestCase {
private Repository remoteRepository;

private URIish remoteURI;
@@ -54,8 +55,8 @@ public class DumbClientSmartServerTest extends AllProtocolsHttpTestCase {

private RevCommit A, B;

public DumbClientSmartServerTest(TestParameters params) {
super(params);
public DumbClientSmartServerTest(HttpConnectionFactory cf) {
super(cf);
}

@Override
@@ -75,9 +76,6 @@ public class DumbClientSmartServerTest extends AllProtocolsHttpTestCase {

remoteRepository = src.getRepository();
remoteURI = toURIish(app, srcName);
if (enableProtocolV2) {
remoteRepository.getConfig().setInt("protocol", null, "version", 2);
}

A_txt = src.blob("A");
A = src.commit().add("A_txt", A_txt).create();

+ 7
- 10
org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017, 2020 Thomas Wolf <thomas.wolf@paranor.ch> and others
* Copyright (C) 2017 Thomas Wolf <thomas.wolf@paranor.ch> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -48,6 +48,7 @@ import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.eclipse.jgit.transport.http.HttpConnectionFactory;
import org.eclipse.jgit.util.HttpSupport;
import org.junit.Before;
import org.junit.Test;
@@ -55,7 +56,7 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class SmartClientSmartServerSslTest extends AllProtocolsHttpTestCase {
public class SmartClientSmartServerSslTest extends AllFactoriesHttpTestCase {

// We run these tests with a server on localhost with a self-signed
// certificate. We don't do authentication tests here, so there's no need
@@ -111,8 +112,8 @@ public class SmartClientSmartServerSslTest extends AllProtocolsHttpTestCase {

private RevCommit A, B;

public SmartClientSmartServerSslTest(TestParameters params) {
super(params);
public SmartClientSmartServerSslTest(HttpConnectionFactory cf) {
super(cf);
}

@Override
@@ -131,10 +132,6 @@ public class SmartClientSmartServerSslTest extends AllProtocolsHttpTestCase {
.getConfig()
.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, true);
if (enableProtocolV2) {
src.getRepository().getConfig().setInt("protocol", null, "version",
2);
}

GitServlet gs = new GitServlet();

@@ -241,7 +238,7 @@ public class SmartClientSmartServerSslTest extends AllProtocolsHttpTestCase {
fsck(dst, B);

List<AccessEvent> requests = getRequests();
assertEquals(enableProtocolV2 ? 3 : 2, requests.size());
assertEquals(2, requests.size());
}

@Test
@@ -259,7 +256,7 @@ public class SmartClientSmartServerSslTest extends AllProtocolsHttpTestCase {
fsck(dst, B);

List<AccessEvent> requests = getRequests();
assertEquals(enableProtocolV2 ? 4 : 3, requests.size());
assertEquals(3, requests.size());
}

@Test

+ 72
- 181
org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2010, 2020 Google Inc. and others
* Copyright (C) 2010, 2017 Google Inc. and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -86,12 +86,13 @@ import org.eclipse.jgit.transport.TransportHttp;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.UploadPack;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.eclipse.jgit.transport.http.HttpConnectionFactory;
import org.eclipse.jgit.util.HttpSupport;
import org.eclipse.jgit.util.SystemReader;
import org.junit.Before;
import org.junit.Test;

public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
public class SmartClientSmartServerTest extends AllFactoriesHttpTestCase {
private static final String HDR_TRANSFER_ENCODING = "Transfer-Encoding";

private AdvertiseRefsHook advertiseRefsHook;
@@ -119,8 +120,8 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {

private RevCommit A, B, unreachableCommit;

public SmartClientSmartServerTest(TestParameters params) {
super(params);
public SmartClientSmartServerTest(HttpConnectionFactory cf) {
super(cf);
}

@Override
@@ -131,12 +132,9 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
final TestRepository<Repository> src = createTestRepository();
final String srcName = src.getRepository().getDirectory().getName();
src.getRepository()
.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION,
null, ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES,
true);
if (enableProtocolV2) {
src.getRepository().getConfig().setInt("protocol", null, "version", 2);
}
.getConfig()
.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, true);

GitServlet gs = new GitServlet();
gs.setUploadPackFactory((HttpServletRequest req, Repository db) -> {
@@ -450,7 +448,7 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
assertEquals(B, map.get(Constants.HEAD).getObjectId());

List<AccessEvent> requests = getRequests();
assertEquals(enableProtocolV2 ? 2 : 1, requests.size());
assertEquals(1, requests.size());

AccessEvent info = requests.get(0);
assertEquals("GET", info.getMethod());
@@ -460,22 +458,7 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
assertEquals(200, info.getStatus());
assertEquals("application/x-git-upload-pack-advertisement", info
.getResponseHeader(HDR_CONTENT_TYPE));
if (!enableProtocolV2) {
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
} else {
AccessEvent lsRefs = requests.get(1);
assertEquals("POST", lsRefs.getMethod());
assertEquals(join(remoteURI, "git-upload-pack"), lsRefs.getPath());
assertEquals(0, lsRefs.getParameters().size());
assertNotNull("has content-length",
lsRefs.getRequestHeader(HDR_CONTENT_LENGTH));
assertNull("not chunked",
lsRefs.getRequestHeader(HDR_TRANSFER_ENCODING));
assertEquals("version=2", lsRefs.getRequestHeader("Git-Protocol"));
assertEquals(200, lsRefs.getStatus());
assertEquals("application/x-git-upload-pack-result",
lsRefs.getResponseHeader(HDR_CONTENT_TYPE));
}
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
}

@Test
@@ -593,10 +576,9 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
}

List<AccessEvent> requests = getRequests();
assertEquals(enableProtocolV2 ? 3 : 2, requests.size());
assertEquals(2, requests.size());

int requestNumber = 0;
AccessEvent info = requests.get(requestNumber++);
AccessEvent info = requests.get(0);
assertEquals("GET", info.getMethod());
assertEquals(join(remoteURI, "info/refs"), info.getPath());
assertEquals(1, info.getParameters().size());
@@ -604,24 +586,9 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
assertEquals(200, info.getStatus());
assertEquals("application/x-git-upload-pack-advertisement", info
.getResponseHeader(HDR_CONTENT_TYPE));
if (!enableProtocolV2) {
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
} else {
AccessEvent lsRefs = requests.get(requestNumber++);
assertEquals("POST", lsRefs.getMethod());
assertEquals(join(remoteURI, "git-upload-pack"), lsRefs.getPath());
assertEquals(0, lsRefs.getParameters().size());
assertNotNull("has content-length",
lsRefs.getRequestHeader(HDR_CONTENT_LENGTH));
assertNull("not chunked",
lsRefs.getRequestHeader(HDR_TRANSFER_ENCODING));
assertEquals("version=2", lsRefs.getRequestHeader("Git-Protocol"));
assertEquals(200, lsRefs.getStatus());
assertEquals("application/x-git-upload-pack-result",
lsRefs.getResponseHeader(HDR_CONTENT_TYPE));
}
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));

AccessEvent service = requests.get(requestNumber);
AccessEvent service = requests.get(1);
assertEquals("POST", service.getMethod());
assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
assertEquals(0, service.getParameters().size());
@@ -661,8 +628,7 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
}

List<AccessEvent> requests = getRequests();
assertEquals((enableProtocolV2 ? 3 : 2) + nofRedirects,
requests.size());
assertEquals(2 + nofRedirects, requests.size());

int n = 0;
while (n < nofRedirects) {
@@ -678,22 +644,7 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
assertEquals(200, info.getStatus());
assertEquals("application/x-git-upload-pack-advertisement",
info.getResponseHeader(HDR_CONTENT_TYPE));
if (!enableProtocolV2) {
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
} else {
AccessEvent lsRefs = requests.get(n++);
assertEquals("POST", lsRefs.getMethod());
assertEquals(join(remoteURI, "git-upload-pack"), lsRefs.getPath());
assertEquals(0, lsRefs.getParameters().size());
assertNotNull("has content-length",
lsRefs.getRequestHeader(HDR_CONTENT_LENGTH));
assertNull("not chunked",
lsRefs.getRequestHeader(HDR_TRANSFER_ENCODING));
assertEquals("version=2", lsRefs.getRequestHeader("Git-Protocol"));
assertEquals(200, lsRefs.getStatus());
assertEquals("application/x-git-upload-pack-result",
lsRefs.getResponseHeader(HDR_CONTENT_TYPE));
}
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));

AccessEvent service = requests.get(n++);
assertEquals("POST", service.getMethod());
@@ -805,7 +756,7 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
}

List<AccessEvent> requests = getRequests();
assertEquals(enableProtocolV2 ? 4 : 3, requests.size());
assertEquals(3, requests.size());

AccessEvent info = requests.get(0);
assertEquals("GET", info.getMethod());
@@ -815,27 +766,24 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
assertEquals(200, info.getStatus());
assertEquals("application/x-git-upload-pack-advertisement",
info.getResponseHeader(HDR_CONTENT_TYPE));
if (!enableProtocolV2) {
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
}
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));

AccessEvent redirect = requests.get(1);
assertEquals("POST", redirect.getMethod());
assertEquals(301, redirect.getStatus());

for (int i = 2; i < requests.size(); i++) {
AccessEvent service = requests.get(i);
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));
}
AccessEvent service = requests.get(2);
assertEquals("POST", service.getMethod());
assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
assertEquals(0, service.getParameters().size());
assertNotNull("has content-length",
service.getRequestHeader(HDR_CONTENT_LENGTH));
assertNull("not chunked",
service.getRequestHeader(HDR_TRANSFER_ENCODING));

assertEquals(200, service.getStatus());
assertEquals("application/x-git-upload-pack-result",
service.getResponseHeader(HDR_CONTENT_TYPE));
}

@Test
@@ -882,7 +830,7 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
}

List<AccessEvent> requests = getRequests();
assertEquals(enableProtocolV2 ? 4 : 3, requests.size());
assertEquals(3, requests.size());

AccessEvent info = requests.get(0);
assertEquals("GET", info.getMethod());
@@ -896,24 +844,20 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
assertEquals(200, info.getStatus());
assertEquals("application/x-git-upload-pack-advertisement",
info.getResponseHeader(HDR_CONTENT_TYPE));
if (!enableProtocolV2) {
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
}
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));

for (int i = 2; i < requests.size(); i++) {
AccessEvent service = requests.get(i);
assertEquals("POST", service.getMethod());
assertEquals(join(authURI, "git-upload-pack"), service.getPath());
assertEquals(0, service.getParameters().size());
assertNotNull("has content-length",
service.getRequestHeader(HDR_CONTENT_LENGTH));
assertNull("not chunked",
service.getRequestHeader(HDR_TRANSFER_ENCODING));

assertEquals(200, service.getStatus());
assertEquals("application/x-git-upload-pack-result",
service.getResponseHeader(HDR_CONTENT_TYPE));
}
AccessEvent service = requests.get(2);
assertEquals("POST", service.getMethod());
assertEquals(join(authURI, "git-upload-pack"), service.getPath());
assertEquals(0, service.getParameters().size());
assertNotNull("has content-length",
service.getRequestHeader(HDR_CONTENT_LENGTH));
assertNull("not chunked",
service.getRequestHeader(HDR_TRANSFER_ENCODING));

assertEquals(200, service.getStatus());
assertEquals("application/x-git-upload-pack-result",
service.getResponseHeader(HDR_CONTENT_TYPE));
}

@Test
@@ -993,20 +937,19 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
}

List<AccessEvent> requests = getRequests();
assertEquals(enableProtocolV2 ? 5 : 4, requests.size());
assertEquals(4, requests.size());

int requestNumber = 0;
AccessEvent redirect = requests.get(requestNumber++);
AccessEvent redirect = requests.get(0);
assertEquals("GET", redirect.getMethod());
assertEquals(join(cloneFrom, "info/refs"), redirect.getPath());
assertEquals(301, redirect.getStatus());

AccessEvent info = requests.get(requestNumber++);
AccessEvent info = requests.get(1);
assertEquals("GET", info.getMethod());
assertEquals(join(authURI, "info/refs"), info.getPath());
assertEquals(401, info.getStatus());

info = requests.get(requestNumber++);
info = requests.get(2);
assertEquals("GET", info.getMethod());
assertEquals(join(authURI, "info/refs"), info.getPath());
assertEquals(1, info.getParameters().size());
@@ -1014,24 +957,9 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
assertEquals(200, info.getStatus());
assertEquals("application/x-git-upload-pack-advertisement",
info.getResponseHeader(HDR_CONTENT_TYPE));
if (!enableProtocolV2) {
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
} else {
AccessEvent lsRefs = requests.get(requestNumber++);
assertEquals("POST", lsRefs.getMethod());
assertEquals(join(authURI, "git-upload-pack"), lsRefs.getPath());
assertEquals(0, lsRefs.getParameters().size());
assertNotNull("has content-length",
lsRefs.getRequestHeader(HDR_CONTENT_LENGTH));
assertNull("not chunked",
lsRefs.getRequestHeader(HDR_TRANSFER_ENCODING));
assertEquals("version=2", lsRefs.getRequestHeader("Git-Protocol"));
assertEquals(200, lsRefs.getStatus());
assertEquals("application/x-git-upload-pack-result",
lsRefs.getResponseHeader(HDR_CONTENT_TYPE));
}
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));

AccessEvent service = requests.get(requestNumber);
AccessEvent service = requests.get(3);
assertEquals("POST", service.getMethod());
assertEquals(join(authURI, "git-upload-pack"), service.getPath());
assertEquals(0, service.getParameters().size());
@@ -1059,7 +987,7 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
}

List<AccessEvent> requests = getRequests();
assertEquals(enableProtocolV2 ? 4 : 3, requests.size());
assertEquals(3, requests.size());

AccessEvent info = requests.get(0);
assertEquals("GET", info.getMethod());
@@ -1069,30 +997,25 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
assertEquals(200, info.getStatus());
assertEquals("application/x-git-upload-pack-advertisement",
info.getResponseHeader(HDR_CONTENT_TYPE));
if (!enableProtocolV2) {
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
}
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));

AccessEvent service = requests.get(1);
assertEquals("POST", service.getMethod());
assertEquals(join(authOnPostURI, "git-upload-pack"), service.getPath());
assertEquals(401, service.getStatus());

for (int i = 2; i < requests.size(); i++) {
service = requests.get(i);
assertEquals("POST", service.getMethod());
assertEquals(join(authOnPostURI, "git-upload-pack"),
service.getPath());
assertEquals(0, service.getParameters().size());
assertNotNull("has content-length",
service.getRequestHeader(HDR_CONTENT_LENGTH));
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(authOnPostURI, "git-upload-pack"), service.getPath());
assertEquals(0, service.getParameters().size());
assertNotNull("has content-length",
service.getRequestHeader(HDR_CONTENT_LENGTH));
assertNull("not chunked",
service.getRequestHeader(HDR_TRANSFER_ENCODING));

assertEquals(200, service.getStatus());
assertEquals("application/x-git-upload-pack-result",
service.getResponseHeader(HDR_CONTENT_TYPE));
}

@Test
@@ -1129,11 +1052,9 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {

List<AccessEvent> requests = getRequests();
requests.removeAll(cloneRequests);
assertEquals(2, requests.size());

assertEquals(enableProtocolV2 ? 3 : 2, requests.size());

int requestNumber = 0;
AccessEvent info = requests.get(requestNumber++);
AccessEvent info = requests.get(0);
assertEquals("GET", info.getMethod());
assertEquals(join(remoteURI, "info/refs"), info.getPath());
assertEquals(1, info.getParameters().size());
@@ -1142,24 +1063,9 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
assertEquals("application/x-git-upload-pack-advertisement",
info.getResponseHeader(HDR_CONTENT_TYPE));

if (enableProtocolV2) {
AccessEvent lsRefs = requests.get(requestNumber++);
assertEquals("POST", lsRefs.getMethod());
assertEquals(join(remoteURI, "git-upload-pack"), lsRefs.getPath());
assertEquals(0, lsRefs.getParameters().size());
assertNotNull("has content-length",
lsRefs.getRequestHeader(HDR_CONTENT_LENGTH));
assertNull("not chunked",
lsRefs.getRequestHeader(HDR_TRANSFER_ENCODING));
assertEquals("version=2", lsRefs.getRequestHeader("Git-Protocol"));
assertEquals(200, lsRefs.getStatus());
assertEquals("application/x-git-upload-pack-result",
lsRefs.getResponseHeader(HDR_CONTENT_TYPE));
}

// We should have needed one request to perform the fetch.
//
AccessEvent service = requests.get(requestNumber);
AccessEvent service = requests.get(1);
assertEquals("POST", service.getMethod());
assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
assertEquals(0, service.getParameters().size());
@@ -1210,10 +1116,9 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {

List<AccessEvent> requests = getRequests();
requests.removeAll(cloneRequests);
assertEquals(enableProtocolV2 ? 4 : 3, requests.size());
assertEquals(3, requests.size());

int requestNumber = 0;
AccessEvent info = requests.get(requestNumber++);
AccessEvent info = requests.get(0);
assertEquals("GET", info.getMethod());
assertEquals(join(remoteURI, "info/refs"), info.getPath());
assertEquals(1, info.getParameters().size());
@@ -1222,25 +1127,10 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
assertEquals("application/x-git-upload-pack-advertisement", info
.getResponseHeader(HDR_CONTENT_TYPE));

if (enableProtocolV2) {
AccessEvent lsRefs = requests.get(requestNumber++);
assertEquals("POST", lsRefs.getMethod());
assertEquals(join(remoteURI, "git-upload-pack"), lsRefs.getPath());
assertEquals(0, lsRefs.getParameters().size());
assertNotNull("has content-length",
lsRefs.getRequestHeader(HDR_CONTENT_LENGTH));
assertNull("not chunked",
lsRefs.getRequestHeader(HDR_TRANSFER_ENCODING));
assertEquals("version=2", lsRefs.getRequestHeader("Git-Protocol"));
assertEquals(200, lsRefs.getStatus());
assertEquals("application/x-git-upload-pack-result",
lsRefs.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(requestNumber++);
AccessEvent service = requests.get(1);
assertEquals("POST", service.getMethod());
assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
assertEquals(0, service.getParameters().size());
@@ -1253,7 +1143,7 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
assertEquals("application/x-git-upload-pack-result", service
.getResponseHeader(HDR_CONTENT_TYPE));

service = requests.get(requestNumber);
service = requests.get(2);
assertEquals("POST", service.getMethod());
assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
assertEquals(0, service.getParameters().size());
@@ -1539,4 +1429,5 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
cfg.setBoolean("http", null, "receivepack", true);
cfg.save();
}

}

+ 0
- 24
org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshProtocol2Test.java View File

@@ -1,24 +0,0 @@
/*
* Copyright (C) 2020 Thomas Wolf <thomas.wolf@paranor.ch> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
* https://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
package org.eclipse.jgit.transport.sshd;

import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;

public class ApacheSshProtocol2Test extends ApacheSshTest {

@Override
public void setUp() throws Exception {
super.setUp();
StoredConfig config = ((Repository) db).getConfig();
config.setInt("protocol", null, "version", 2);
config.save();
}
}

+ 4
- 13
org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSession.java View File

@@ -24,7 +24,6 @@ import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@@ -54,7 +53,7 @@ import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.internal.transport.sshd.JGitSshClient;
import org.eclipse.jgit.internal.transport.sshd.SshdText;
import org.eclipse.jgit.transport.FtpChannel;
import org.eclipse.jgit.transport.RemoteSession2;
import org.eclipse.jgit.transport.RemoteSession;
import org.eclipse.jgit.transport.SshConstants;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.util.StringUtils;
@@ -62,12 +61,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* An implementation of {@link org.eclipse.jgit.transport.RemoteSession
* RemoteSession} based on Apache MINA sshd.
* An implementation of {@link RemoteSession} based on Apache MINA sshd.
*
* @since 5.2
*/
public class SshdSession implements RemoteSession2 {
public class SshdSession implements RemoteSession {

private static final Logger LOG = LoggerFactory
.getLogger(SshdSession.class);
@@ -292,15 +290,8 @@ public class SshdSession implements RemoteSession2 {

@Override
public Process exec(String commandName, int timeout) throws IOException {
return exec(commandName, Collections.emptyMap(), timeout);
}

@Override
public Process exec(String commandName, Map<String, String> environment,
int timeout) throws IOException {
@SuppressWarnings("resource")
ChannelExec exec = session.createExecChannel(commandName, null,
environment);
ChannelExec exec = session.createExecChannel(commandName);
if (timeout <= 0) {
try {
exec.open().verify();

+ 0
- 26
org.eclipse.jgit.ssh.jsch.test/tst/org/eclipse/jgit/transport/JSchSshProtocol2Test.java View File

@@ -1,26 +0,0 @@
/*
* Copyright (C) 2020 Thomas Wolf <thomas.wolf@paranor.ch> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
* https://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

//TODO(ms): move to org.eclipse.jgit.ssh.jsch in 6.0
package org.eclipse.jgit.transport;

import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;

public class JSchSshProtocol2Test extends JSchSshTest {

@Override
public void setUp() throws Exception {
super.setUp();
StoredConfig config = ((Repository) db).getConfig();
config.setInt("protocol", null, "version", 2);
config.save();
}
}

+ 4
- 21
org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschSession.java View File

@@ -22,9 +22,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

@@ -46,7 +44,7 @@ import com.jcraft.jsch.SftpException;
* {@link org.eclipse.jgit.transport.JschConfigSessionFactory} is used to create
* the actual session passed to the constructor.
*/
public class JschSession implements RemoteSession2 {
public class JschSession implements RemoteSession {
final Session sock;
final URIish uri;

@@ -67,14 +65,7 @@ public class JschSession implements RemoteSession2 {
/** {@inheritDoc} */
@Override
public Process exec(String command, int timeout) throws IOException {
return exec(command, Collections.emptyMap(), timeout);
}

/** {@inheritDoc} */
@Override
public Process exec(String command, Map<String, String> environment,
int timeout) throws IOException {
return new JschProcess(command, environment, timeout);
return new JschProcess(command, timeout);
}

/** {@inheritDoc} */
@@ -133,8 +124,6 @@ public class JschSession implements RemoteSession2 {
*
* @param commandName
* the command to execute
* @param environment
* environment variables to pass on
* @param tms
* the timeout value, in seconds, for the command.
* @throws TransportException
@@ -143,17 +132,11 @@ public class JschSession implements RemoteSession2 {
* @throws IOException
* on problems opening streams
*/
JschProcess(String commandName, Map<String, String> environment,
int tms) throws TransportException, IOException {
JschProcess(String commandName, int tms)
throws TransportException, IOException {
timeout = tms;
try {
channel = (ChannelExec) sock.openChannel("exec"); //$NON-NLS-1$
if (environment != null) {
for (Map.Entry<String, String> envVar : environment
.entrySet()) {
channel.setEnv(envVar.getKey(), envVar.getValue());
}
}
channel.setCommand(commandName);
setupStreams();
channel.connect(timeout > 0 ? timeout * 1000 : 0);

+ 0
- 1
org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties View File

@@ -232,7 +232,6 @@ downloadCancelled=Download cancelled
downloadCancelledDuringIndexing=Download cancelled during indexing
duplicateAdvertisementsOf=duplicate advertisements of {0}
duplicateRef=Duplicate ref: {0}
duplicateRefAttribute=Duplicate ref attribute: {0}
duplicateRemoteRefUpdateIsIllegal=Duplicate remote ref update is illegal. Affected remote name: {0}
duplicateStagesNotAllowed=Duplicate stages not allowed
eitherGitDirOrWorkTreeRequired=One of setGitDir or setWorkTree must be called.

+ 1
- 1
org.eclipse.jgit/src/org/eclipse/jgit/api/LsRemoteCommand.java View File

@@ -164,7 +164,7 @@ public class LsRemoteCommand extends
refSpecs.add(new RefSpec("refs/heads/*:refs/remotes/origin/*")); //$NON-NLS-1$
Collection<Ref> refs;
Map<String, Ref> refmap = new HashMap<>();
try (FetchConnection fc = transport.openFetch(refSpecs)) {
try (FetchConnection fc = transport.openFetch()) {
refs = fc.getRefs();
if (refSpecs.isEmpty())
for (Ref r : refs)

+ 0
- 1
org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java View File

@@ -260,7 +260,6 @@ public class JGitText extends TranslationBundle {
/***/ public String downloadCancelledDuringIndexing;
/***/ public String duplicateAdvertisementsOf;
/***/ public String duplicateRef;
/***/ public String duplicateRefAttribute;
/***/ public String duplicateRemoteRefUpdateIsIllegal;
/***/ public String duplicateStagesNotAllowed;
/***/ public String eitherGitDirOrWorkTreeRequired;

+ 52
- 307
org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java View File

@@ -13,12 +13,7 @@

package org.eclipse.jgit.transport;

import static org.eclipse.jgit.transport.GitProtocolConstants.COMMAND_LS_REFS;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT;
import static org.eclipse.jgit.transport.GitProtocolConstants.REF_ATTR_PEELED;
import static org.eclipse.jgit.transport.GitProtocolConstants.REF_ATTR_SYMREF_TARGET;
import static org.eclipse.jgit.transport.GitProtocolConstants.VERSION_1;
import static org.eclipse.jgit.transport.GitProtocolConstants.VERSION_2;

import java.io.EOFException;
import java.io.IOException;
@@ -26,28 +21,20 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.errors.InvalidObjectIdException;
import org.eclipse.jgit.errors.NoRemoteRepositoryException;
import org.eclipse.jgit.errors.PackProtocolException;
import org.eclipse.jgit.errors.RemoteRepositoryException;
import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.util.TemporaryBuffer;
import org.eclipse.jgit.util.io.InterruptTimer;
import org.eclipse.jgit.util.io.TimeoutInputStream;
import org.eclipse.jgit.util.io.TimeoutOutputStream;
@@ -99,27 +86,17 @@ abstract class BasePackConnection extends BaseConnection {
protected boolean statelessRPC;

/** Capability tokens advertised by the remote side. */
private final Map<String, String> remoteCapabilities = new HashMap<>();
private final Set<String> remoteCapablities = new HashSet<>();

/** Extra objects the remote has, but which aren't offered as refs. */
protected final Set<ObjectId> additionalHaves = new HashSet<>();

private TransferConfig.ProtocolVersion protocol = TransferConfig.ProtocolVersion.V0;

BasePackConnection(PackTransport packTransport) {
transport = (Transport) packTransport;
local = transport.local;
uri = transport.uri;
}

TransferConfig.ProtocolVersion getProtocolVersion() {
return protocol;
}

void setProtocolVersion(@NonNull TransferConfig.ProtocolVersion protocol) {
this.protocol = protocol;
}

/**
* Configure this connection with the directional pipes.
*
@@ -164,15 +141,12 @@ abstract class BasePackConnection extends BaseConnection {
* {@link #close()} and the exception is wrapped (if necessary) and thrown
* as a {@link org.eclipse.jgit.errors.TransportException}.
*
* @return {@code true} if the refs were read; {@code false} otherwise
* indicating that {@link #lsRefs} must be called
*
* @throws org.eclipse.jgit.errors.TransportException
* the reference list could not be scanned.
*/
protected boolean readAdvertisedRefs() throws TransportException {
protected void readAdvertisedRefs() throws TransportException {
try {
return readAdvertisedRefsImpl();
readAdvertisedRefsImpl();
} catch (TransportException err) {
close();
throw err;
@@ -182,66 +156,35 @@ abstract class BasePackConnection extends BaseConnection {
}
}

private String readLine() throws IOException {
String line = pckIn.readString();
if (PacketLineIn.isEnd(line)) {
return null;
}
if (line.startsWith("ERR ")) { //$NON-NLS-1$
// This is a customized remote service error.
// Users should be informed about it.
throw new RemoteRepositoryException(uri, line.substring(4));
}
return line;
}

private boolean readAdvertisedRefsImpl() throws IOException {
private void readAdvertisedRefsImpl() throws IOException {
final LinkedHashMap<String, Ref> avail = new LinkedHashMap<>();
for (boolean first = true;; first = false) {
for (;;) {
String line;

if (first) {
boolean isV1 = false;
try {
line = readLine();
} catch (EOFException e) {
try {
line = pckIn.readString();
} catch (EOFException eof) {
if (avail.isEmpty())
throw noRepository();
}
if (line != null && VERSION_1.equals(line)) {
// Same as V0, except for this extra line. We shouldn't get
// it since we never request V1.
setProtocolVersion(TransferConfig.ProtocolVersion.V0);
isV1 = true;
line = readLine();
}
if (line == null) {
break;
}
throw eof;
}
if (PacketLineIn.isEnd(line))
break;

if (line.startsWith("ERR ")) { //$NON-NLS-1$
// This is a customized remote service error.
// Users should be informed about it.
throw new RemoteRepositoryException(uri, line.substring(4));
}

if (avail.isEmpty()) {
final int nul = line.indexOf('\0');
if (nul >= 0) {
// Protocol V0: The first line (if any) may contain
// "hidden" capability values after a NUL byte.
for (String capability : line.substring(nul + 1)
.split(" ")) { //$NON-NLS-1$
addCapability(capability);
}
// The first line (if any) may contain "hidden"
// capability values after a NUL byte.
remoteCapablities.addAll(
Arrays.asList(line.substring(nul + 1).split(" "))); //$NON-NLS-1$
line = line.substring(0, nul);
setProtocolVersion(TransferConfig.ProtocolVersion.V0);
} else if (!isV1 && VERSION_2.equals(line)) {
// Protocol V2: remaining lines are capabilities as
// key=value pairs
setProtocolVersion(TransferConfig.ProtocolVersion.V2);
readCapabilitiesV2();
// Break out here so that stateless RPC transports get a
// chance to set up the output stream.
return false;
} else {
setProtocolVersion(TransferConfig.ProtocolVersion.V0);
}
} else {
line = readLine();
if (line == null) {
break;
}
}

@@ -250,230 +193,44 @@ abstract class BasePackConnection extends BaseConnection {
throw invalidRefAdvertisementLine(line);
}
String name = line.substring(41, line.length());
if (first && name.equals("capabilities^{}")) { //$NON-NLS-1$
// special line from git-receive-pack (protocol V0) to show
if (avail.isEmpty() && name.equals("capabilities^{}")) { //$NON-NLS-1$
// special line from git-receive-pack to show
// capabilities when there are no refs to advertise
// TODO: throw error if protocol version is >= V2?
continue;
}

final ObjectId id = toId(line, line.substring(0, 40));
final ObjectId id;
try {
id = ObjectId.fromString(line.substring(0, 40));
} catch (InvalidObjectIdException e) {
PackProtocolException ppe = invalidRefAdvertisementLine(line);
ppe.initCause(e);
throw ppe;
}
if (name.equals(".have")) { //$NON-NLS-1$
additionalHaves.add(id);
} else {
processLineV1(name, id, avail);
}
}
available(avail);
return true;
}
} else if (name.endsWith("^{}")) { //$NON-NLS-1$
name = name.substring(0, name.length() - 3);
final Ref prior = avail.get(name);
if (prior == null)
throw new PackProtocolException(uri, MessageFormat.format(
JGitText.get().advertisementCameBefore, name, name));

/**
* Issue a protocol V2 ls-refs command and read its response.
*
* @param refSpecs
* to produce ref prefixes from if the server supports git
* protocol V2
* @param additionalPatterns
* to use for ref prefixes if the server supports git protocol V2
* @throws TransportException
* if the command could not be run or its output not be read
*/
protected void lsRefs(Collection<RefSpec> refSpecs,
String... additionalPatterns) throws TransportException {
try {
lsRefsImpl(refSpecs, additionalPatterns);
} catch (TransportException err) {
close();
throw err;
} catch (IOException | RuntimeException err) {
close();
throw new TransportException(err.getMessage(), err);
}
}
if (prior.getPeeledObjectId() != null)
throw duplicateAdvertisement(name + "^{}"); //$NON-NLS-1$

private void lsRefsImpl(Collection<RefSpec> refSpecs,
String... additionalPatterns) throws IOException {
TemporaryBuffer state = null;
PacketLineOut pckState = null;
PacketLineOut output = pckOut;
if (statelessRPC) {
state = new TemporaryBuffer.Heap(Integer.MAX_VALUE);
pckState = new PacketLineOut(state);
output = pckState;
}
output.writeString("command=" + COMMAND_LS_REFS); //$NON-NLS-1$
// Add the user-agent
String agent = UserAgent.get();
if (agent != null && isCapableOf(OPTION_AGENT)) {
output.writeString(OPTION_AGENT + '=' + agent);
}
output.writeDelim();
output.writeString("peel"); //$NON-NLS-1$
for (String refPrefix : getRefPrefixes(refSpecs, additionalPatterns)) {
output.writeString("ref-prefix " + refPrefix); //$NON-NLS-1$
}
output.end();
output.flush();
if (state != null) {
state.writeTo(out, null);
out.flush();
state = null;
pckState = null;
}
final LinkedHashMap<String, Ref> avail = new LinkedHashMap<>();
for (;;) {
String line = readLine();
if (line == null) {
break;
}
// Expecting to get a line in the form "sha1 refname"
if (line.length() < 41 || line.charAt(40) != ' ') {
throw invalidRefAdvertisementLine(line);
}
String name = line.substring(41, line.length());
final ObjectId id = toId(line, line.substring(0, 40));
if (name.equals(".have")) { //$NON-NLS-1$
additionalHaves.add(id);
avail.put(name, new ObjectIdRef.PeeledTag(
Ref.Storage.NETWORK, name, prior.getObjectId(), id));
} else {
processLineV2(line, id, name, avail);
final Ref prior = avail.put(name, new ObjectIdRef.PeeledNonTag(
Ref.Storage.NETWORK, name, id));
if (prior != null)
throw duplicateAdvertisement(name);
}
}
available(avail);
}

private Collection<String> getRefPrefixes(Collection<RefSpec> refSpecs,
String... additionalPatterns) {
if (refSpecs.isEmpty() && (additionalPatterns == null
|| additionalPatterns.length == 0)) {
return Collections.emptyList();
}
Set<String> patterns = new HashSet<>();
if (additionalPatterns != null) {
Arrays.stream(additionalPatterns).filter(Objects::nonNull)
.forEach(patterns::add);
}
for (RefSpec spec : refSpecs) {
// TODO: for now we only do protocol V2 for fetch. For push
// RefSpecs, the logic would need to be different. (At the
// minimum, take spec.getDestination().)
String src = spec.getSource();
if (ObjectId.isId(src)) {
continue;
}
if (spec.isWildcard()) {
patterns.add(src.substring(0, src.indexOf('*')));
} else {
patterns.add(src);
patterns.add(Constants.R_REFS + src);
patterns.add(Constants.R_HEADS + src);
patterns.add(Constants.R_TAGS + src);
}
}
return patterns;
}

private void readCapabilitiesV2() throws IOException {
// In git protocol V2, capabilities are different. If it's a key-value
// pair, the key may be a command name, and the value a space-separated
// list of capabilities for that command. We still store it in the same
// map as for protocol v0/v1. Protocol v2 code has to account for this.
for (;;) {
String line = readLine();
if (line == null) {
break;
}
addCapability(line);
}
}

private void addCapability(String capability) {
String parts[] = capability.split("=", 2); //$NON-NLS-1$
if (parts.length == 2) {
remoteCapabilities.put(parts[0], parts[1]);
}
remoteCapabilities.put(capability, null);
}

private ObjectId toId(String line, String value)
throws PackProtocolException {
try {
return ObjectId.fromString(value);
} catch (InvalidObjectIdException e) {
PackProtocolException ppe = invalidRefAdvertisementLine(line);
ppe.initCause(e);
throw ppe;
}
}

private void processLineV1(String name, ObjectId id, Map<String, Ref> avail)
throws IOException {
if (name.endsWith("^{}")) { //$NON-NLS-1$
name = name.substring(0, name.length() - 3);
final Ref prior = avail.get(name);
if (prior == null) {
throw new PackProtocolException(uri, MessageFormat.format(
JGitText.get().advertisementCameBefore, name, name));
}
if (prior.getPeeledObjectId() != null) {
throw duplicateAdvertisement(name + "^{}"); //$NON-NLS-1$
}
avail.put(name, new ObjectIdRef.PeeledTag(Ref.Storage.NETWORK, name,
prior.getObjectId(), id));
} else {
final Ref prior = avail.put(name, new ObjectIdRef.PeeledNonTag(
Ref.Storage.NETWORK, name, id));
if (prior != null) {
throw duplicateAdvertisement(name);
}
}
}

private void processLineV2(String line, ObjectId id, String rest,
Map<String, Ref> avail) throws IOException {
String[] parts = rest.split(" "); //$NON-NLS-1$
String name = parts[0];
// Two attributes possible, symref-target or peeled
String symRefTarget = null;
String peeled = null;
for (int i = 1; i < parts.length; i++) {
if (parts[i].startsWith(REF_ATTR_SYMREF_TARGET)) {
if (symRefTarget != null) {
throw new PackProtocolException(uri, MessageFormat.format(
JGitText.get().duplicateRefAttribute, line));
}
symRefTarget = parts[i]
.substring(REF_ATTR_SYMREF_TARGET.length());
} else if (parts[i].startsWith(REF_ATTR_PEELED)) {
if (peeled != null) {
throw new PackProtocolException(uri, MessageFormat.format(
JGitText.get().duplicateRefAttribute, line));
}
peeled = parts[i].substring(REF_ATTR_PEELED.length());
}
if (peeled != null && symRefTarget != null) {
break;
}
}
Ref idRef;
if (peeled != null) {
idRef = new ObjectIdRef.PeeledTag(Ref.Storage.NETWORK, name, id,
toId(line, peeled));
} else {
idRef = new ObjectIdRef.PeeledNonTag(Ref.Storage.NETWORK, name, id);
}
Ref prior = avail.put(name, idRef);
if (prior != null) {
throw duplicateAdvertisement(name);
}
if (symRefTarget != null) {
// What do we have to do with this information? In protocol V0, this
// info comes in the capability advertisement, but OPTION_SYMREF is
// used only in RefAdvertiser. JGit's client side doesn't make use
// of this information, and actually never requests it.
}
}

/**
* Create an exception to indicate problems finding a remote repository. The
* caller is expected to throw the returned exception.
@@ -495,7 +252,7 @@ abstract class BasePackConnection extends BaseConnection {
* @return whether this option is supported
*/
protected boolean isCapableOf(String option) {
return remoteCapabilities.containsKey(option);
return remoteCapablities.contains(option);
}

/**
@@ -515,17 +272,6 @@ abstract class BasePackConnection extends BaseConnection {
return true;
}

/**
* Return a capability value.
*
* @param option
* to get
* @return the value stored, if any.
*/
protected String getCapability(String option) {
return remoteCapabilities.get(option);
}

/**
* Add user agent capability
*
@@ -534,7 +280,7 @@ abstract class BasePackConnection extends BaseConnection {
*/
protected void addUserAgentCapability(StringBuilder b) {
String a = UserAgent.get();
if (a != null && remoteCapabilities.get(OPTION_AGENT) != null) {
if (a != null && UserAgent.hasAgent(remoteCapablities)) {
b.append(' ').append(OPTION_AGENT).append('=').append(a);
}
}
@@ -542,8 +288,7 @@ abstract class BasePackConnection extends BaseConnection {
/** {@inheritDoc} */
@Override
public String getPeerUserAgent() {
String agent = remoteCapabilities.get(OPTION_AGENT);
return agent != null ? agent : super.getPeerUserAgent();
return UserAgent.getAgent(remoteCapablities, super.getPeerUserAgent());
}

private PackProtocolException duplicateAdvertisement(String name) {

+ 16
- 171
org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java View File

@@ -16,12 +16,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

import org.eclipse.jgit.errors.PackProtocolException;
@@ -215,8 +212,6 @@ public abstract class BasePackFetchConnection extends BasePackConnection

private PacketLineOut pckState;

private Set<String> fetchCapabilities = new HashSet<>();

/**
* Either FilterSpec.NO_FILTER for a filter that doesn't filter
* anything, or a filter that indicates what and what not to send to the
@@ -359,28 +354,6 @@ public abstract class BasePackFetchConnection extends BasePackConnection
pckState = new PacketLineOut(state);
}

if (TransferConfig.ProtocolVersion.V2
.equals(getProtocolVersion())) {
sideband = true;
noDone = true;
multiAck = MultiAck.DETAILED;
setFetchOptions();
PacketLineOut output = statelessRPC ? pckState : pckOut;
output.writeString(
"command=" + GitProtocolConstants.COMMAND_FETCH); //$NON-NLS-1$
// Capabilities are sent as command arguments in protocol V2
String agent = UserAgent.get();
if (agent != null
&& isCapableOf(GitProtocolConstants.OPTION_AGENT)) {
output.writeString(
GitProtocolConstants.OPTION_AGENT + '=' + agent);
}
output.writeDelim();
// Arguments
for (String capability : getCapabilitiesV2()) {
output.writeString(capability);
}
}
if (sendWants(want)) {
negotiate(monitor);

@@ -389,25 +362,6 @@ public abstract class BasePackFetchConnection extends BasePackConnection
state = null;
pckState = null;

if (TransferConfig.ProtocolVersion.V2
.equals(getProtocolVersion())) {
String header = pckIn.readString();
if (PacketLineIn.isEnd(header)) {
// No packfile following.
return;
}

if (header.startsWith("ERR ")) { //$NON-NLS-1$
// Protocol V2 may give us an error here (for instance,
// invalid want)
throw new PackProtocolException(header.substring(4));
}
if (!GitProtocolConstants.SECTION_PACKFILE.equals(header)) {
throw new PackProtocolException(MessageFormat.format(
JGitText.get().expectedGot,
GitProtocolConstants.SECTION_PACKFILE, header));
}
}
receivePack(monitor, outputStream);
}
} catch (CancelledException ce) {
@@ -427,14 +381,6 @@ public abstract class BasePackFetchConnection extends BasePackConnection
super.close();
}

private void setFetchOptions() {
String advertised = getCapability(GitProtocolConstants.COMMAND_FETCH);
if (advertised == null) {
return;
}
fetchCapabilities.addAll(Arrays.asList(advertised.split(" "))); //$NON-NLS-1$
}

FetchConfig getFetchConfig() {
return local.getConfig().get(FetchConfig::new);
}
@@ -533,11 +479,10 @@ public abstract class BasePackFetchConnection extends BasePackConnection
final StringBuilder line = new StringBuilder(46);
line.append("want "); //$NON-NLS-1$
line.append(objectId.name());
if (first && TransferConfig.ProtocolVersion.V0
.equals(getProtocolVersion())) {
if (first) {
line.append(enableCapabilities());
first = false;
}
first = false;
line.append('\n');
p.writeString(line.toString());
}
@@ -547,35 +492,11 @@ public abstract class BasePackFetchConnection extends BasePackConnection
if (!filterSpec.isNoOp()) {
p.writeString(filterSpec.filterLine());
}
if (TransferConfig.ProtocolVersion.V0.equals(getProtocolVersion())) {
p.end();
outNeedsEnd = false;
}
p.end();
outNeedsEnd = false;
return true;
}

private Set<String> getCapabilitiesV2() throws TransportException {
Set<String> capabilities = new LinkedHashSet<>();
if (noProgress) {
capabilities.add(OPTION_NO_PROGRESS);
}
if (includeTags) {
capabilities.add(OPTION_INCLUDE_TAG);
}
if (allowOfsDelta) {
capabilities.add(OPTION_OFS_DELTA);
}
if (thinPack) {
capabilities.add(OPTION_THIN_PACK);
}
if (!filterSpec.isNoOp()
&& !fetchCapabilities.contains(OPTION_FILTER)) {
throw new PackProtocolException(uri,
JGitText.get().filterRequiresCapability);
}
return capabilities;
}

private String enableCapabilities() throws TransportException {
final StringBuilder line = new StringBuilder();
if (noProgress)
@@ -629,7 +550,6 @@ public abstract class BasePackFetchConnection extends BasePackConnection
boolean receivedContinue = false;
boolean receivedAck = false;
boolean receivedReady = false;
boolean needsAcknowledgementV2 = true;

if (statelessRPC) {
state.writeTo(out, null);
@@ -643,7 +563,7 @@ public abstract class BasePackFetchConnection extends BasePackConnection
}

ObjectId o = c.getId();
pckOut.writeString("have " + o.name() + '\n'); //$NON-NLS-1$
pckOut.writeString("have " + o.name() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
havesSent++;
havesSinceLastContinue++;

@@ -660,7 +580,6 @@ public abstract class BasePackFetchConnection extends BasePackConnection
}

pckOut.end();
outNeedsEnd = false;
resultsPending++; // Each end will cause a result to come back.

if (havesSent == 32 && !statelessRPC) {
@@ -672,32 +591,9 @@ public abstract class BasePackFetchConnection extends BasePackConnection
continue;
}

// Read the section header
if (needsAcknowledgementV2 && TransferConfig.ProtocolVersion.V2
.equals(getProtocolVersion())) {
String header = pckIn.readString();
if (!GitProtocolConstants.SECTION_ACKNOWLEDGMENTS
.equals(header)) {
throw new PackProtocolException(MessageFormat.format(
JGitText.get().expectedGot,
GitProtocolConstants.SECTION_ACKNOWLEDGMENTS,
header));
}
needsAcknowledgementV2 = false;
}
READ_RESULT: for (;;) {
AckNackResult anr = pckIn.readACKorEOF(ackId);
final AckNackResult anr = pckIn.readACK(ackId);
switch (anr) {
case ACK_EOF:
if (TransferConfig.ProtocolVersion.V0
.equals(getProtocolVersion())) {
throw new PackProtocolException(
JGitText.get().expectedACKNAKFoundEOF);
}
// More lines needed
resultsPending--;
break READ_RESULT;

case NAK:
// More have lines are necessary to compute the
// pack on the remote side. Keep doing that.
@@ -706,24 +602,17 @@ public abstract class BasePackFetchConnection extends BasePackConnection
break READ_RESULT;

case ACK:
if (TransferConfig.ProtocolVersion.V0
.equals(getProtocolVersion())) {
// The remote side is happy and knows exactly what
// to send us. There is no further negotiation and
// we can break out immediately.
//
multiAck = MultiAck.OFF;
resultsPending = 0;
receivedAck = true;
if (statelessRPC) {
state.writeTo(out, null);
}
break SEND_HAVES;
}
// Keep on reading ACKs until we get the ACK_READY
markCommon(walk.parseAny(ackId), AckNackResult.ACK_COMMON);
// The remote side is happy and knows exactly what
// to send us. There is no further negotiation and
// we can break out immediately.
//
multiAck = MultiAck.OFF;
resultsPending = 0;
receivedAck = true;
break;
if (statelessRPC) {
state.writeTo(out, null);
}
break SEND_HAVES;

case ACK_CONTINUE:
case ACK_COMMON:
@@ -739,12 +628,6 @@ public abstract class BasePackFetchConnection extends BasePackConnection
havesSinceLastContinue = 0;
if (anr == AckNackResult.ACK_READY) {
receivedReady = true;
if (TransferConfig.ProtocolVersion.V2
.equals(getProtocolVersion())) {
multiAck = MultiAck.OFF;
resultsPending = 0;
break SEND_HAVES;
}
}
break;
}
@@ -778,36 +661,15 @@ public abstract class BasePackFetchConnection extends BasePackConnection
throw new CancelledException();
}

if (receivedReady && TransferConfig.ProtocolVersion.V2
.equals(getProtocolVersion())) {
// We'll get the packfile right away. Skip the delimiter.
String delim = pckIn.readString();
if (!PacketLineIn.isDelimiter(delim)) {
throw new PackProtocolException(MessageFormat
.format(JGitText.get().expectedGot, "0001", delim)); //$NON-NLS-1$
}
return;
}
if (!receivedReady || !noDone) {
// When statelessRPC is true we should always leave SEND_HAVES
// loop above while in the middle of a request. This allows us
// to just write done immediately.
//
pckOut.writeString("done\n"); //$NON-NLS-1$
if (TransferConfig.ProtocolVersion.V2
.equals(getProtocolVersion())) {
pckOut.end();
outNeedsEnd = false;
pckOut.flush();
// Protocol V2 will skip acknowledgments completely if we send
// a done.
return;
}
pckOut.flush();
}

// Below is protocol V0 only.

if (!receivedAck) {
// Apparently if we have never received an ACK earlier
// there is one more result expected from the done we
@@ -827,14 +689,6 @@ public abstract class BasePackFetchConnection extends BasePackConnection
//
break;

case ACK_EOF:
if (TransferConfig.ProtocolVersion.V0
.equals(getProtocolVersion())) {
throw new PackProtocolException(
JGitText.get().expectedACKNAKFoundEOF);
}
break READ_RESULT;

case ACK:
// A solitary ACK at this point means the remote won't
// speak anymore, but is going to send us a pack now.
@@ -843,16 +697,7 @@ public abstract class BasePackFetchConnection extends BasePackConnection

case ACK_CONTINUE:
case ACK_COMMON:
// We will expect a normal ACK to break out of the loop.
//
multiAck = MultiAck.CONTINUE;
break;

case ACK_READY:
if (TransferConfig.ProtocolVersion.V2
.equals(getProtocolVersion())) {
break READ_RESULT;
}
// We will expect a normal ACK to break out of the loop.
//
multiAck = MultiAck.CONTINUE;

+ 3
- 26
org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java View File

@@ -102,21 +102,7 @@ class FetchProcess {
private void executeImp(final ProgressMonitor monitor,
final FetchResult result) throws NotSupportedException,
TransportException {
final TagOpt tagopt = transport.getTagOpt();
String getTags = (tagopt == TagOpt.NO_TAGS) ? null : Constants.R_TAGS;
String getHead = null;
try {
// If we don't have a HEAD yet, we're cloning and need to get the
// upstream HEAD, too.
Ref head = transport.local.exactRef(Constants.HEAD);
ObjectId id = head != null ? head.getObjectId() : null;
if (id == null || id.equals(ObjectId.zeroId())) {
getHead = Constants.HEAD;
}
} catch (IOException e) {
// Ignore
}
conn = transport.openFetch(toFetch, getTags, getHead);
conn = transport.openFetch();
try {
result.setAdvertisedRefs(transport.getURI(), conn.getRefsMap());
result.peerUserAgent = conn.getPeerUserAgent();
@@ -133,6 +119,7 @@ class FetchProcess {
}

Collection<Ref> additionalTags = Collections.<Ref> emptyList();
final TagOpt tagopt = transport.getTagOpt();
if (tagopt == TagOpt.AUTO_FOLLOW)
additionalTags = expandAutoFollowTags();
else if (tagopt == TagOpt.FETCH_TAGS)
@@ -266,17 +253,7 @@ class FetchProcess {
if (conn != null)
return;

// Build prefixes
Set<String> prefixes = new HashSet<>();
for (Ref toGet : askFor.values()) {
String src = toGet.getName();
prefixes.add(src);
prefixes.add(Constants.R_REFS + src);
prefixes.add(Constants.R_HEADS + src);
prefixes.add(Constants.R_TAGS + src);
}
conn = transport.openFetch(Collections.emptyList(),
prefixes.toArray(new String[0]));
conn = transport.openFetch();

// Since we opened a new connection we cannot be certain
// that the system we connected to has the same exact set

+ 0
- 68
org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java View File

@@ -247,74 +247,6 @@ public final class GitProtocolConstants {
*/
public static final String COMMAND_FETCH = "fetch"; //$NON-NLS-1$

/**
* HTTP header to set by clients to request a specific git protocol version
* in the HTTP transport.
*
* @since 5.10
*/
public static final String PROTOCOL_HEADER = "Git-Protocol"; //$NON-NLS-1$

/**
* Environment variable to set by clients to request a specific git protocol
* in the file:// and ssh:// transports.
*
* @since 5.10
*/
public static final String PROTOCOL_ENVIRONMENT_VARIABLE = "GIT_PROTOCOL"; //$NON-NLS-1$

/**
* Protocol V2 ref advertisement attribute containing the peeled object id
* for annotated tags.
*
* @since 5.10
*/
public static final String REF_ATTR_PEELED = "peeled:"; //$NON-NLS-1$

/**
* Protocol V2 ref advertisement attribute containing the name of the ref
* for symbolic refs.
*
* @since 5.10
*/
public static final String REF_ATTR_SYMREF_TARGET = "symref-target:"; //$NON-NLS-1$

/**
* Protocol V2 acknowledgments section header.
*
* @since 5.10
*/
public static final String SECTION_ACKNOWLEDGMENTS = "acknowledgments"; //$NON-NLS-1$

/**
* Protocol V2 packfile section header.
*
* @since 5.10
*/
public static final String SECTION_PACKFILE = "packfile"; //$NON-NLS-1$

/**
* Protocol announcement for protocol version 1. This is the same as V0,
* except for this initial line.
*
* @since 5.10
*/
public static final String VERSION_1 = "version 1"; //$NON-NLS-1$

/**
* Protocol announcement for protocol version 2.
*
* @since 5.10
*/
public static final String VERSION_2 = "version 2"; //$NON-NLS-1$

/**
* Protocol request for protocol version 2.
*
* @since 5.10
*/
public static final String VERSION_2_REQUEST = "version=2"; //$NON-NLS-1$

enum MultiAck {
OFF, CONTINUE, DETAILED;
}

+ 2
- 18
org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineIn.java View File

@@ -72,9 +72,7 @@ public class PacketLineIn {
/** ACK + common */
ACK_COMMON,
/** ACK + ready */
ACK_READY,
/** EOF (0000) recieved in protocol V2 when expecting an ACK/NAK */
ACK_EOF;
ACK_READY;
}

private final byte[] lineBuffer = new byte[SideBandOutputStream.SMALL_BUF];
@@ -105,26 +103,12 @@ public class PacketLineIn {
this.limit = limit;
}


AckNackResult readACK(MutableObjectId returnedId) throws IOException {
AckNackResult result = readACKorEOF(returnedId);
if (result == AckNackResult.ACK_EOF) {
throw new PackProtocolException(
JGitText.get().expectedACKNAKFoundEOF);
}
return result;
}

AckNackResult readACKorEOF(MutableObjectId returnedId) throws IOException {
final String line = readString();
if (line.length() == 0)
return AckNackResult.ACK_EOF;
throw new PackProtocolException(JGitText.get().expectedACKNAKFoundEOF);
if ("NAK".equals(line)) //$NON-NLS-1$
return AckNackResult.NAK;
if ("ready".equals(line)) { //$NON-NLS-1$
// Protocol V2
return AckNackResult.ACK_READY;
}
if (line.startsWith("ACK ")) { //$NON-NLS-1$
returnedId.fromString(line.substring(4, 44));
if (line.length() == 44)

+ 2
- 6
org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java View File

@@ -13,8 +13,6 @@ package org.eclipse.jgit.transport;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_STRING_LENGTH;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SYMREF;
import static org.eclipse.jgit.transport.GitProtocolConstants.REF_ATTR_PEELED;
import static org.eclipse.jgit.transport.GitProtocolConstants.REF_ATTR_SYMREF_TARGET;

import java.io.IOException;
import java.nio.ByteBuffer;
@@ -289,8 +287,7 @@ public abstract class RefAdvertiser {

if (useProtocolV2) {
String symrefPart = symrefs.containsKey(ref.getName())
? (' ' + REF_ATTR_SYMREF_TARGET
+ symrefs.get(ref.getName()))
? (" symref-target:" + symrefs.get(ref.getName())) //$NON-NLS-1$
: ""; //$NON-NLS-1$
String peelPart = ""; //$NON-NLS-1$
if (derefTags) {
@@ -299,8 +296,7 @@ public abstract class RefAdvertiser {
}
ObjectId peeledObjectId = ref.getPeeledObjectId();
if (peeledObjectId != null) {
peelPart = ' ' + REF_ATTR_PEELED
+ peeledObjectId.getName();
peelPart = " peeled:" + peeledObjectId.getName(); //$NON-NLS-1$
}
}
writeOne(objectId.getName() + " " + ref.getName() + symrefPart //$NON-NLS-1$

+ 0
- 45
org.eclipse.jgit/src/org/eclipse/jgit/transport/RemoteSession2.java View File

@@ -1,45 +0,0 @@
/*
* Copyright (C) 2020, Thomas Wolf <thoams.wolf@paranor.ch>
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
* https://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

package org.eclipse.jgit.transport;

import java.io.IOException;
import java.util.Map;

/**
* A {@link RemoteSession} that supports passing environment variables to
* commands.
*
* @since 5.10
*/
public interface RemoteSession2 extends RemoteSession {

/**
* Creates a new remote {@link Process} to execute the given command. The
* returned process's streams exist and are connected, and execution of the
* process is already started.
*
* @param commandName
* command to execute
* @param environment
* environment variables to pass on
* @param timeout
* timeout value, in seconds, for creating the remote process
* @return a new remote process, already started
* @throws java.io.IOException
* may be thrown in several cases. For example, on problems
* opening input or output streams or on problems connecting or
* communicating with the remote host. For the latter two cases,
* a TransportException may be thrown (a subclass of
* java.io.IOException).
*/
Process exec(String commandName, Map<String, String> environment,
int timeout) throws IOException;
}

+ 0
- 43
org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java View File

@@ -39,7 +39,6 @@ import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;

import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.api.errors.AbortedByHookException;
import org.eclipse.jgit.errors.NotSupportedException;
import org.eclipse.jgit.errors.TransportException;
@@ -775,10 +774,6 @@ public abstract class Transport implements AutoCloseable {
private PrintStream hookOutRedirect;

private PrePushHook prePush;

@Nullable
TransferConfig.ProtocolVersion protocol;

/**
* Create a new transport instance.
*
@@ -794,7 +789,6 @@ public abstract class Transport implements AutoCloseable {
final TransferConfig tc = local.getConfig().get(TransferConfig.KEY);
this.local = local;
this.uri = uri;
this.protocol = tc.protocolVersion;
this.objectChecker = tc.newObjectChecker();
this.credentialsProvider = CredentialsProvider.getDefault();
prePush = Hooks.prePush(local, hookOutRedirect);
@@ -1458,43 +1452,6 @@ public abstract class Transport implements AutoCloseable {
public abstract FetchConnection openFetch() throws NotSupportedException,
TransportException;

/**
* Begins a new connection for fetching from the remote repository.
* <p>
* If the transport has no local repository, the fetch connection can only
* be used for reading remote refs.
* </p>
* <p>
* If the server supports git protocol V2, the {@link RefSpec}s and the
* additional patterns, if any, are used to restrict the server's ref
* advertisement to matching refs only.
* </p>
* <p>
* Transports that want to support git protocol V2 <em>must</em> override
* this; the default implementation ignores its arguments and calls
* {@link #openFetch()}.
* </p>
*
* @param refSpecs
* that will be fetched via
* {@link FetchConnection#fetch(ProgressMonitor, Collection, java.util.Set, OutputStream)} later
* @param additionalPatterns
* that will be set as ref prefixes if the server supports git
* protocol V2; {@code null} values are ignored
*
* @return a fresh connection to fetch from the remote repository.
* @throws org.eclipse.jgit.errors.NotSupportedException
* the implementation does not support fetching.
* @throws org.eclipse.jgit.errors.TransportException
* the remote connection could not be established.
* @since 5.10
*/
public FetchConnection openFetch(Collection<RefSpec> refSpecs,
String... additionalPatterns)
throws NotSupportedException, TransportException {
return openFetch();
}

/**
* Begins a new connection for pushing into the remote repository.
*

+ 4
- 29
org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitAnon.java View File

@@ -22,7 +22,6 @@ import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
@@ -95,13 +94,6 @@ class TransportGitAnon extends TcpTransport implements PackTransport {
return new TcpFetchConnection();
}

@Override
public FetchConnection openFetch(Collection<RefSpec> refSpecs,
String... additionalPatterns)
throws NotSupportedException, TransportException {
return new TcpFetchConnection(refSpecs, additionalPatterns);
}

/** {@inheritDoc} */
@Override
public PushConnection openPush() throws TransportException {
@@ -138,8 +130,7 @@ class TransportGitAnon extends TcpTransport implements PackTransport {
return s;
}

void service(String name, PacketLineOut pckOut,
TransferConfig.ProtocolVersion gitProtocol)
void service(String name, PacketLineOut pckOut)
throws IOException {
final StringBuilder cmd = new StringBuilder();
cmd.append(name);
@@ -153,11 +144,6 @@ class TransportGitAnon extends TcpTransport implements PackTransport {
cmd.append(uri.getPort());
}
cmd.append('\0');
if (TransferConfig.ProtocolVersion.V2.equals(gitProtocol)) {
cmd.append('\0');
cmd.append(GitProtocolConstants.VERSION_2_REQUEST);
cmd.append('\0');
}
pckOut.writeString(cmd.toString());
pckOut.flush();
}
@@ -166,11 +152,6 @@ class TransportGitAnon extends TcpTransport implements PackTransport {
private Socket sock;

TcpFetchConnection() throws TransportException {
this(Collections.emptyList());
}

TcpFetchConnection(Collection<RefSpec> refSpecs,
String... additionalPatterns) throws TransportException {
super(TransportGitAnon.this);
sock = openConnection();
try {
@@ -181,19 +162,13 @@ class TransportGitAnon extends TcpTransport implements PackTransport {
sOut = new BufferedOutputStream(sOut);

init(sIn, sOut);
TransferConfig.ProtocolVersion gitProtocol = protocol;
if (gitProtocol == null) {
gitProtocol = TransferConfig.ProtocolVersion.V2;
}
service("git-upload-pack", pckOut, gitProtocol); //$NON-NLS-1$
service("git-upload-pack", pckOut); //$NON-NLS-1$
} catch (IOException err) {
close();
throw new TransportException(uri,
JGitText.get().remoteHungUpUnexpectedly, err);
}
if (!readAdvertisedRefs()) {
lsRefs(refSpecs, additionalPatterns);
}
readAdvertisedRefs();
}

@Override
@@ -226,7 +201,7 @@ class TransportGitAnon extends TcpTransport implements PackTransport {
sOut = new BufferedOutputStream(sOut);

init(sIn, sOut);
service("git-receive-pack", pckOut, null); //$NON-NLS-1$
service("git-receive-pack", pckOut); //$NON-NLS-1$
} catch (IOException err) {
close();
throw new TransportException(uri,

+ 10
- 55
org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java View File

@@ -19,13 +19,11 @@ import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.eclipse.jgit.errors.NoRemoteRepositoryException;
@@ -146,13 +144,6 @@ public class TransportGitSsh extends SshTransport implements PackTransport {
return new SshFetchConnection();
}

@Override
public FetchConnection openFetch(Collection<RefSpec> refSpecs,
String... additionalPatterns)
throws NotSupportedException, TransportException {
return new SshFetchConnection(refSpecs, additionalPatterns);
}

/** {@inheritDoc} */
@Override
public PushConnection openPush() throws TransportException {
@@ -205,38 +196,29 @@ public class TransportGitSsh extends SshTransport implements PackTransport {
return SystemReader.getInstance().getenv("GIT_SSH") != null; //$NON-NLS-1$
}

private class ExtSession implements RemoteSession2 {

private class ExtSession implements RemoteSession {
@Override
public Process exec(String command, int timeout)
throws TransportException {
return exec(command, null, timeout);
}

@Override
public Process exec(String command, Map<String, String> environment,
int timeout) throws TransportException {
String ssh = SystemReader.getInstance().getenv("GIT_SSH"); //$NON-NLS-1$
boolean putty = ssh.toLowerCase(Locale.ROOT).contains("plink"); //$NON-NLS-1$

List<String> args = new ArrayList<>();
args.add(ssh);
if (putty && !ssh.toLowerCase(Locale.ROOT)
.contains("tortoiseplink")) {//$NON-NLS-1$
if (putty
&& !ssh.toLowerCase(Locale.ROOT).contains("tortoiseplink")) //$NON-NLS-1$
args.add("-batch"); //$NON-NLS-1$
}
if (0 < getURI().getPort()) {
args.add(putty ? "-P" : "-p"); //$NON-NLS-1$ //$NON-NLS-2$
args.add(String.valueOf(getURI().getPort()));
}
if (getURI().getUser() != null) {
if (getURI().getUser() != null)
args.add(getURI().getUser() + "@" + getURI().getHost()); //$NON-NLS-1$
} else {
else
args.add(getURI().getHost());
}
args.add(command);

ProcessBuilder pb = createProcess(args, environment);
ProcessBuilder pb = createProcess(args);
try {
return pb.start();
} catch (IOException err) {
@@ -244,13 +226,9 @@ public class TransportGitSsh extends SshTransport implements PackTransport {
}
}

private ProcessBuilder createProcess(List<String> args,
Map<String, String> environment) {
private ProcessBuilder createProcess(List<String> args) {
ProcessBuilder pb = new ProcessBuilder();
pb.command(args);
if (environment != null) {
pb.environment().putAll(environment);
}
File directory = local != null ? local.getDirectory() : null;
if (directory != null) {
pb.environment().put(Constants.GIT_DIR_KEY,
@@ -271,31 +249,10 @@ public class TransportGitSsh extends SshTransport implements PackTransport {
private StreamCopyThread errorThread;

SshFetchConnection() throws TransportException {
this(Collections.emptyList());
}

SshFetchConnection(Collection<RefSpec> refSpecs,
String... additionalPatterns) throws TransportException {
super(TransportGitSsh.this);
try {
RemoteSession session = getSession();
TransferConfig.ProtocolVersion gitProtocol = protocol;
if (gitProtocol == null) {
gitProtocol = TransferConfig.ProtocolVersion.V2;
}
if (session instanceof RemoteSession2
&& TransferConfig.ProtocolVersion.V2
.equals(gitProtocol)) {
process = ((RemoteSession2) session).exec(
commandFor(getOptionUploadPack()), Collections
.singletonMap(
GitProtocolConstants.PROTOCOL_ENVIRONMENT_VARIABLE,
GitProtocolConstants.VERSION_2_REQUEST),
getTimeout());
} else {
process = session.exec(commandFor(getOptionUploadPack()),
getTimeout());
}
process = getSession().exec(commandFor(getOptionUploadPack()),
getTimeout());
final MessageWriter msg = new MessageWriter();
setMessageWriter(msg);

@@ -315,9 +272,7 @@ public class TransportGitSsh extends SshTransport implements PackTransport {
}

try {
if (!readAdvertisedRefs()) {
lsRefs(refSpecs, additionalPatterns);
}
readAdvertisedRefs();
} catch (NoRemoteRepositoryException notFound) {
final String msgs = getMessages();
checkExecFailure(process.exitValue(), getOptionUploadPack(),

+ 25
- 92
org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java View File

@@ -33,8 +33,8 @@ import static org.eclipse.jgit.util.HttpSupport.HDR_WWW_AUTHENTICATE;
import static org.eclipse.jgit.util.HttpSupport.METHOD_GET;
import static org.eclipse.jgit.util.HttpSupport.METHOD_POST;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
@@ -339,15 +339,11 @@ public class TransportHttp extends HttpTransport implements WalkTransport,

@SuppressWarnings("resource") // Closed by caller
private FetchConnection getConnection(HttpConnection c, InputStream in,
String service, Collection<RefSpec> refSpecs,
String... additionalPatterns) throws IOException {
String service) throws IOException {
BaseConnection f;
if (isSmartHttp(c, service)) {
InputStream withMark = in.markSupported() ? in
: new BufferedInputStream(in);
readSmartHeaders(withMark, service);
f = new SmartHttpFetchConnection(withMark, refSpecs,
additionalPatterns);
readSmartHeaders(in, service);
f = new SmartHttpFetchConnection(in);
} else {
// Assume this server doesn't support smart HTTP fetch
// and fall back on dumb object walking.
@@ -361,23 +357,11 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
@Override
public FetchConnection openFetch() throws TransportException,
NotSupportedException {
return openFetch(Collections.emptyList());
}

@Override
public FetchConnection openFetch(Collection<RefSpec> refSpecs,
String... additionalPatterns)
throws NotSupportedException, TransportException {
final String service = SVC_UPLOAD_PACK;
try {
TransferConfig.ProtocolVersion gitProtocol = protocol;
if (gitProtocol == null) {
gitProtocol = TransferConfig.ProtocolVersion.V2;
}
HttpConnection c = connect(service, gitProtocol);
final HttpConnection c = connect(service);
try (InputStream in = openInputStream(c)) {
return getConnection(c, in, service, refSpecs,
additionalPatterns);
return getConnection(c, in, service);
}
} catch (NotSupportedException | TransportException err) {
throw err;
@@ -472,9 +456,8 @@ public class TransportHttp extends HttpTransport implements WalkTransport,

private PushConnection smartPush(String service, HttpConnection c,
InputStream in) throws IOException, TransportException {
BufferedInputStream inBuf = new BufferedInputStream(in);
readSmartHeaders(inBuf, service);
SmartHttpPushConnection p = new SmartHttpPushConnection(inBuf);
readSmartHeaders(in, service);
SmartHttpPushConnection p = new SmartHttpPushConnection(in);
p.setPeerUserAgent(c.getHeaderField(HttpSupport.HDR_SERVER));
return p;
}
@@ -511,12 +494,6 @@ public class TransportHttp extends HttpTransport implements WalkTransport,

private HttpConnection connect(String service)
throws TransportException, NotSupportedException {
return connect(service, null);
}

private HttpConnection connect(String service,
TransferConfig.ProtocolVersion protocolVersion)
throws TransportException, NotSupportedException {
URL u = getServiceURL(service);
int authAttempts = 1;
int redirects = 0;
@@ -530,11 +507,6 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
} else {
conn.setRequestProperty(HDR_ACCEPT, "*/*"); //$NON-NLS-1$
}
if (TransferConfig.ProtocolVersion.V2.equals(protocolVersion)) {
conn.setRequestProperty(
GitProtocolConstants.PROTOCOL_HEADER,
GitProtocolConstants.VERSION_2_REQUEST);
}
final int status = HttpSupport.response(conn);
processResponseCookies(conn);
switch (status) {
@@ -1176,37 +1148,20 @@ public class TransportHttp extends HttpTransport implements WalkTransport,

private void readSmartHeaders(InputStream in, String service)
throws IOException {
// A smart protocol V0 reply will have a '#' after the first 4 bytes,
// but a dumb reply cannot contain a '#' until after byte 41. Do a
// A smart reply will have a '#' after the first 4 bytes, but
// a dumb reply cannot contain a '#' until after byte 41. Do a
// quick check to make sure its a smart reply before we parse
// as a pkt-line stream.
//
// There appears to be a confusion about this in protocol V2. Github
// sends the # service line as a git (not http) header also when
// protocol V2 is used. Gitlab also does so. JGit's UploadPack doesn't,
// and thus Gerrit also does not.
final byte[] magic = new byte[14];
if (!in.markSupported()) {
throw new TransportException(uri,
JGitText.get().inputStreamMustSupportMark);
}
in.mark(14);
final byte[] magic = new byte[5];
IO.readFully(in, magic, 0, magic.length);
// Did we get 000dversion 2 or similar? (Canonical is 000eversion 2\n,
// but JGit and thus Gerrit omits the \n.)
if (Arrays.equals(Arrays.copyOfRange(magic, 4, 11),
"version".getBytes()) && magic[12] >= '1' && magic[12] <= '9') { //$NON-NLS-1$
// It's a smart server doing version 1 or greater, but not sending
// the # service line header. Don't consume the version line.
in.reset();
return;
}
if (magic[4] != '#') {
throw new TransportException(uri, MessageFormat.format(
JGitText.get().expectedPktLineWithService, RawParseUtils.decode(magic)));
}
in.reset();
final PacketLineIn pckIn = new PacketLineIn(in);

final PacketLineIn pckIn = new PacketLineIn(new UnionInputStream(
new ByteArrayInputStream(magic), in));
final String exp = "# service=" + service; //$NON-NLS-1$
final String act = pckIn.readString();
if (!exp.equals(act)) {
@@ -1372,24 +1327,12 @@ public class TransportHttp extends HttpTransport implements WalkTransport,

SmartHttpFetchConnection(InputStream advertisement)
throws TransportException {
this(advertisement, Collections.emptyList());
}

SmartHttpFetchConnection(InputStream advertisement,
Collection<RefSpec> refSpecs, String... additionalPatterns)
throws TransportException {
super(TransportHttp.this);
statelessRPC = true;

init(advertisement, DisabledOutputStream.INSTANCE);
outNeedsEnd = false;
if (!readAdvertisedRefs()) {
// Must be protocol V2
LongPollService service = new LongPollService(SVC_UPLOAD_PACK,
getProtocolVersion());
init(service.getInputStream(), service.getOutputStream());
lsRefs(refSpecs, additionalPatterns);
}
readAdvertisedRefs();
}

@Override
@@ -1397,8 +1340,7 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
final Collection<Ref> want, final Set<ObjectId> have,
final OutputStream outputStream) throws TransportException {
try {
svc = new MultiRequestService(SVC_UPLOAD_PACK,
getProtocolVersion());
svc = new MultiRequestService(SVC_UPLOAD_PACK);
init(svc.getInputStream(), svc.getOutputStream());
super.doFetch(monitor, want, have, outputStream);
} finally {
@@ -1427,8 +1369,7 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
protected void doPush(final ProgressMonitor monitor,
final Map<String, RemoteRefUpdate> refUpdates,
OutputStream outputStream) throws TransportException {
final Service svc = new MultiRequestService(SVC_RECEIVE_PACK,
getProtocolVersion());
final Service svc = new MultiRequestService(SVC_RECEIVE_PACK);
init(svc.getInputStream(), svc.getOutputStream());
super.doPush(monitor, refUpdates, outputStream);
}
@@ -1448,14 +1389,10 @@ public class TransportHttp extends HttpTransport implements WalkTransport,

protected final HttpExecuteStream execute;

protected final TransferConfig.ProtocolVersion protocolVersion;

final UnionInputStream in;

Service(String serviceName,
TransferConfig.ProtocolVersion protocolVersion) {
Service(String serviceName) {
this.serviceName = serviceName;
this.protocolVersion = protocolVersion;
this.requestType = "application/x-" + serviceName + "-request"; //$NON-NLS-1$ //$NON-NLS-2$
this.responseType = "application/x-" + serviceName + "-result"; //$NON-NLS-1$ //$NON-NLS-2$

@@ -1471,10 +1408,6 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
conn.setDoOutput(true);
conn.setRequestProperty(HDR_CONTENT_TYPE, requestType);
conn.setRequestProperty(HDR_ACCEPT, responseType);
if (TransferConfig.ProtocolVersion.V2.equals(protocolVersion)) {
conn.setRequestProperty(GitProtocolConstants.PROTOCOL_HEADER,
GitProtocolConstants.VERSION_2_REQUEST);
}
}

void sendRequest() throws IOException {
@@ -1730,9 +1663,8 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
class MultiRequestService extends Service {
boolean finalRequest;

MultiRequestService(String serviceName,
TransferConfig.ProtocolVersion protocolVersion) {
super(serviceName, protocolVersion);
MultiRequestService(String serviceName) {
super(serviceName);
}

/** Keep opening send-receive pairs to the given URI. */
@@ -1769,10 +1701,11 @@ public class TransportHttp extends HttpTransport implements WalkTransport,

/** Service for maintaining a single long-poll connection. */
class LongPollService extends Service {

LongPollService(String serviceName,
TransferConfig.ProtocolVersion protocolVersion) {
super(serviceName, protocolVersion);
/**
* @param serviceName
*/
LongPollService(String serviceName) {
super(serviceName);
}

/** Only open one send-receive request. */

+ 6
- 44
org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java View File

@@ -20,7 +20,6 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -154,17 +153,11 @@ class TransportLocal extends Transport implements PackTransport {
/** {@inheritDoc} */
@Override
public FetchConnection openFetch() throws TransportException {
return openFetch(Collections.emptyList());
}

@Override
public FetchConnection openFetch(Collection<RefSpec> refSpecs,
String... additionalPatterns) throws TransportException {
final String up = getOptionUploadPack();
if (!"git-upload-pack".equals(up) //$NON-NLS-1$
&& !"git upload-pack".equals(up)) {//$NON-NLS-1$
return new ForkLocalFetchConnection(refSpecs, additionalPatterns);
}
&& !"git upload-pack".equals(up)) //$NON-NLS-1$
return new ForkLocalFetchConnection();

UploadPackFactory<Void> upf = (Void req,
Repository db) -> createUploadPack(db);
return new InternalFetchConnection<>(this, upf, null, openRepo());
@@ -200,23 +193,6 @@ class TransportLocal extends Transport implements PackTransport {
*/
protected Process spawn(String cmd)
throws TransportException {
return spawn(cmd, null);
}

/**
* Spawn process
*
* @param cmd
* command
* @param protocolVersion
* to use
* @return a {@link java.lang.Process} object.
* @throws org.eclipse.jgit.errors.TransportException
* if any.
*/
private Process spawn(String cmd,
TransferConfig.ProtocolVersion protocolVersion)
throws TransportException {
try {
String[] args = { "." }; //$NON-NLS-1$
ProcessBuilder proc = local.getFS().runInShell(cmd, args);
@@ -232,10 +208,7 @@ class TransportLocal extends Transport implements PackTransport {
env.remove("GIT_GRAFT_FILE"); //$NON-NLS-1$
env.remove("GIT_INDEX_FILE"); //$NON-NLS-1$
env.remove("GIT_NO_REPLACE_OBJECTS"); //$NON-NLS-1$
if (TransferConfig.ProtocolVersion.V2.equals(protocolVersion)) {
env.put(GitProtocolConstants.PROTOCOL_ENVIRONMENT_VARIABLE,
GitProtocolConstants.VERSION_2_REQUEST);
}

return proc.start();
} catch (IOException err) {
throw new TransportException(uri, err.getMessage(), err);
@@ -248,21 +221,12 @@ class TransportLocal extends Transport implements PackTransport {
private Thread errorReaderThread;

ForkLocalFetchConnection() throws TransportException {
this(Collections.emptyList());
}

ForkLocalFetchConnection(Collection<RefSpec> refSpecs,
String... additionalPatterns) throws TransportException {
super(TransportLocal.this);

final MessageWriter msg = new MessageWriter();
setMessageWriter(msg);

TransferConfig.ProtocolVersion gitProtocol = protocol;
if (gitProtocol == null) {
gitProtocol = TransferConfig.ProtocolVersion.V2;
}
uploadPack = spawn(getOptionUploadPack(), gitProtocol);
uploadPack = spawn(getOptionUploadPack());

final InputStream upErr = uploadPack.getErrorStream();
errorReaderThread = new StreamCopyThread(upErr, msg.getRawStream());
@@ -275,9 +239,7 @@ class TransportLocal extends Transport implements PackTransport {
upOut = new BufferedOutputStream(upOut);

init(upIn, upOut);
if (!readAdvertisedRefs()) {
lsRefs(refSpecs, additionalPatterns);
}
readAdvertisedRefs();
}

@Override

+ 4
- 8
org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java View File

@@ -33,7 +33,6 @@ import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDEBAND_AL
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND_64K;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_THIN_PACK;
import static org.eclipse.jgit.transport.GitProtocolConstants.VERSION_2_REQUEST;
import static org.eclipse.jgit.util.RefMap.toRefMap;

import java.io.ByteArrayOutputStream;
@@ -710,7 +709,7 @@ public class UploadPack {
* @since 5.0
*/
public void setExtraParameters(Collection<String> params) {
this.clientRequestedV2 = params.contains(VERSION_2_REQUEST);
this.clientRequestedV2 = params.contains("version=2"); //$NON-NLS-1$
}

/**
@@ -1195,8 +1194,7 @@ public class UploadPack {
new PacketLineOut(NullOutputStream.INSTANCE),
accumulator);
} else {
pckOut.writeString(
GitProtocolConstants.SECTION_ACKNOWLEDGMENTS + '\n');
pckOut.writeString("acknowledgments\n"); //$NON-NLS-1$
for (ObjectId id : req.getPeerHas()) {
if (walk.getObjectReader().has(id)) {
pckOut.writeString("ACK " + id.getName() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -1245,8 +1243,7 @@ public class UploadPack {
if (!pckOut.isUsingSideband()) {
// sendPack will write "packfile\n" for us if sideband-all is used.
// But sideband-all is not used, so we have to write it ourselves.
pckOut.writeString(
GitProtocolConstants.SECTION_PACKFILE + '\n');
pckOut.writeString("packfile\n"); //$NON-NLS-1$
}

accumulator.timeNegotiating = Duration
@@ -2330,8 +2327,7 @@ public class UploadPack {
// for us if provided a PackfileUriConfig. In this case, we
// are not providing a PackfileUriConfig, so we have to
// write this line ourselves.
pckOut.writeString(
GitProtocolConstants.SECTION_PACKFILE + '\n');
pckOut.writeString("packfile\n"); //$NON-NLS-1$
}
}
pw.writePack(pm, NullProgressMonitor.INSTANCE, packOut);

Loading…
Cancel
Save