diff options
5 files changed, 375 insertions, 32 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java index 9c43c0b0a4..79d3d87e2d 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java @@ -3,20 +3,22 @@ package org.eclipse.jgit.transport; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.theInstance; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.StringWriter; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + import org.eclipse.jgit.errors.PackProtocolException; import org.eclipse.jgit.errors.TransportException; import org.eclipse.jgit.internal.storage.dfs.DfsGarbageCollector; @@ -31,8 +33,8 @@ import org.eclipse.jgit.lib.Sets; import org.eclipse.jgit.lib.TextProgressMonitor; import org.eclipse.jgit.revwalk.RevBlob; import org.eclipse.jgit.revwalk.RevCommit; -import org.eclipse.jgit.revwalk.RevTree; import org.eclipse.jgit.revwalk.RevTag; +import org.eclipse.jgit.revwalk.RevTree; import org.eclipse.jgit.transport.UploadPack.RequestPolicy; import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; @@ -421,7 +423,8 @@ public class UploadPackTest { * and returns UploadPack's output stream. */ private ByteArrayInputStream uploadPackV2Setup(RequestPolicy requestPolicy, - RefFilter refFilter, String... inputLines) throws Exception { + RefFilter refFilter, ProtocolV2Hook hook, String... inputLines) + throws Exception { ByteArrayOutputStream send = new ByteArrayOutputStream(); PacketLineOut pckOut = new PacketLineOut(send); @@ -442,6 +445,9 @@ public class UploadPackTest { if (refFilter != null) up.setRefFilter(refFilter); up.setExtraParameters(Sets.of("version=2")); + if (hook != null) { + up.setProtocolV2Hook(hook); + } ByteArrayOutputStream recv = new ByteArrayOutputStream(); up.upload(new ByteArrayInputStream(send.toByteArray()), recv, null); @@ -455,9 +461,10 @@ public class UploadPackTest { * advertisement by the server. */ private ByteArrayInputStream uploadPackV2(RequestPolicy requestPolicy, - RefFilter refFilter, String... inputLines) throws Exception { + RefFilter refFilter, ProtocolV2Hook hook, String... inputLines) + throws Exception { ByteArrayInputStream recvStream = - uploadPackV2Setup(requestPolicy, refFilter, inputLines); + uploadPackV2Setup(requestPolicy, refFilter, hook, inputLines); PacketLineIn pckIn = new PacketLineIn(recvStream); // drain capabilities @@ -468,15 +475,33 @@ public class UploadPackTest { } private ByteArrayInputStream uploadPackV2(String... inputLines) throws Exception { - return uploadPackV2(null, null, inputLines); + return uploadPackV2(null, null, null, inputLines); + } + + private static class TestV2Hook implements ProtocolV2Hook { + private CapabilitiesV2Request capabilitiesRequest; + + private LsRefsV2Request lsRefsRequest; + + @Override + public void onCapabilities(CapabilitiesV2Request req) { + capabilitiesRequest = req; + } + + @Override + public void onLsRefs(LsRefsV2Request req) { + lsRefsRequest = req; + } } @Test public void testV2Capabilities() throws Exception { + TestV2Hook hook = new TestV2Hook(); ByteArrayInputStream recvStream = - uploadPackV2Setup(null, null, PacketLineIn.END); + uploadPackV2Setup(null, null, hook, PacketLineIn.END); PacketLineIn pckIn = new PacketLineIn(recvStream); + assertThat(hook.capabilitiesRequest, notNullValue()); assertThat(pckIn.readString(), is("version 2")); assertThat( Arrays.asList(pckIn.readString(), pckIn.readString()), @@ -494,7 +519,7 @@ public class UploadPackTest { public void testV2CapabilitiesAllowFilter() throws Exception { server.getConfig().setBoolean("uploadpack", null, "allowfilter", true); ByteArrayInputStream recvStream = - uploadPackV2Setup(null, null, PacketLineIn.END); + uploadPackV2Setup(null, null, null, PacketLineIn.END); PacketLineIn pckIn = new PacketLineIn(recvStream); assertThat(pckIn.readString(), is("version 2")); @@ -510,7 +535,7 @@ public class UploadPackTest { public void testV2CapabilitiesRefInWant() throws Exception { server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true); ByteArrayInputStream recvStream = - uploadPackV2Setup(null, null, PacketLineIn.END); + uploadPackV2Setup(null, null, null, PacketLineIn.END); PacketLineIn pckIn = new PacketLineIn(recvStream); assertThat(pckIn.readString(), is("version 2")); @@ -526,7 +551,7 @@ public class UploadPackTest { public void testV2CapabilitiesRefInWantNotAdvertisedIfUnallowed() throws Exception { server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", false); ByteArrayInputStream recvStream = - uploadPackV2Setup(null, null, PacketLineIn.END); + uploadPackV2Setup(null, null, null, PacketLineIn.END); PacketLineIn pckIn = new PacketLineIn(recvStream); assertThat(pckIn.readString(), is("version 2")); @@ -541,7 +566,7 @@ public class UploadPackTest { server.getConfig().setBoolean("uploadpack", null, "allowrefinwant", true); server.getConfig().setBoolean("uploadpack", null, "advertiserefinwant", false); ByteArrayInputStream recvStream = - uploadPackV2Setup(null, null, PacketLineIn.END); + uploadPackV2Setup(null, null, null, PacketLineIn.END); PacketLineIn pckIn = new PacketLineIn(recvStream); assertThat(pckIn.readString(), is("version 2")); @@ -568,9 +593,12 @@ public class UploadPackTest { RevTag tag = remote.tag("tag", tip); remote.update("refs/tags/tag", tag); - ByteArrayInputStream recvStream = uploadPackV2("command=ls-refs\n", PacketLineIn.END); + TestV2Hook hook = new TestV2Hook(); + ByteArrayInputStream recvStream = uploadPackV2(null, null, hook, + "command=ls-refs\n", PacketLineIn.END); PacketLineIn pckIn = new PacketLineIn(recvStream); + assertThat(hook.lsRefsRequest, notNullValue()); assertThat(pckIn.readString(), is(tip.toObjectId().getName() + " HEAD")); assertThat(pckIn.readString(), is(tip.toObjectId().getName() + " refs/heads/master")); assertThat(pckIn.readString(), is(tag.toObjectId().getName() + " refs/tags/tag")); @@ -722,6 +750,7 @@ public class UploadPackTest { uploadPackV2( RequestPolicy.ADVERTISED, null, + null, "command=fetch\n", PacketLineIn.DELIM, "want " + advertized.name() + "\n", @@ -734,6 +763,7 @@ public class UploadPackTest { uploadPackV2( RequestPolicy.ADVERTISED, null, + null, "command=fetch\n", PacketLineIn.DELIM, "want " + unadvertized.name() + "\n", @@ -751,6 +781,7 @@ public class UploadPackTest { uploadPackV2( RequestPolicy.REACHABLE_COMMIT, null, + null, "command=fetch\n", PacketLineIn.DELIM, "want " + reachable.name() + "\n", @@ -763,6 +794,7 @@ public class UploadPackTest { uploadPackV2( RequestPolicy.REACHABLE_COMMIT, null, + null, "command=fetch\n", PacketLineIn.DELIM, "want " + unreachable.name() + "\n", @@ -779,6 +811,7 @@ public class UploadPackTest { uploadPackV2( RequestPolicy.TIP, new RejectAllRefFilter(), + null, "command=fetch\n", PacketLineIn.DELIM, "want " + tip.name() + "\n", @@ -791,6 +824,7 @@ public class UploadPackTest { uploadPackV2( RequestPolicy.TIP, new RejectAllRefFilter(), + null, "command=fetch\n", PacketLineIn.DELIM, "want " + parentOfTip.name() + "\n", @@ -808,6 +842,7 @@ public class UploadPackTest { uploadPackV2( RequestPolicy.REACHABLE_COMMIT_TIP, new RejectAllRefFilter(), + null, "command=fetch\n", PacketLineIn.DELIM, "want " + parentOfTip.name() + "\n", @@ -820,6 +855,7 @@ public class UploadPackTest { uploadPackV2( RequestPolicy.REACHABLE_COMMIT_TIP, new RejectAllRefFilter(), + null, "command=fetch\n", PacketLineIn.DELIM, "want " + unreachable.name() + "\n", @@ -834,6 +870,7 @@ public class UploadPackTest { uploadPackV2( RequestPolicy.ANY, null, + null, "command=fetch\n", PacketLineIn.DELIM, "want " + unreachable.name() + "\n", diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/CapabilitiesV2Request.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/CapabilitiesV2Request.java new file mode 100644 index 0000000000..b133ab579a --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/CapabilitiesV2Request.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2018, Google LLC. + * 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.transport; + +/** + * Capabilities protocol v2 request. + * + * <p> + * This is used as an input to {@link ProtocolV2Hook}. + * + * @since 5.1 + */ +public final class CapabilitiesV2Request { + private CapabilitiesV2Request() { + } + + /** @return A builder of {@link CapabilitiesV2Request}. */ + public static Builder builder() { + return new Builder(); + } + + /** A builder for {@link CapabilitiesV2Request}. */ + public static final class Builder { + private Builder() { + } + + /** @return CapabilitiesV2Request */ + public CapabilitiesV2Request build() { + return new CapabilitiesV2Request(); + } + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/LsRefsV2Request.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/LsRefsV2Request.java new file mode 100644 index 0000000000..3aff584a00 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/LsRefsV2Request.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2018, Google LLC. + * 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.transport; + +import java.util.Collections; +import java.util.List; + +/** + * ls-refs protocol v2 request. + * + * <p> + * This is used as an input to {@link ProtocolV2Hook}. + * + * @since 5.1 + */ +public final class LsRefsV2Request { + private final List<String> refPrefixes; + + private final boolean symrefs; + + private final boolean peel; + + private LsRefsV2Request(List<String> refPrefixes, boolean symrefs, + boolean peel) { + this.refPrefixes = refPrefixes; + this.symrefs = symrefs; + this.peel = peel; + } + + /** @return ref prefixes that the client requested. */ + public List<String> getRefPrefixes() { + return refPrefixes; + } + + /** @return true if the client requests symbolic references. */ + public boolean getSymrefs() { + return symrefs; + } + + /** @return true if the client requests tags to be peeled. */ + public boolean getPeel() { + return peel; + } + + /** @return A builder of {@link LsRefsV2Request}. */ + public static Builder builder() { + return new Builder(); + } + + /** A builder for {@link LsRefsV2Request}. */ + public static final class Builder { + private List<String> refPrefixes = Collections.emptyList(); + + private boolean symrefs; + + private boolean peel; + + private Builder() { + } + + /** + * @param value + * @return the Builder + */ + public Builder setRefPrefixes(List<String> value) { + refPrefixes = value; + return this; + } + + /** + * @param value + * @return the Builder + */ + public Builder setSymrefs(boolean value) { + symrefs = value; + return this; + } + + /** + * @param value + * @return the Builder + */ + public Builder setPeel(boolean value) { + peel = value; + return this; + } + + /** @return LsRefsV2Request */ + public LsRefsV2Request build() { + return new LsRefsV2Request( + Collections.unmodifiableList(refPrefixes), symrefs, peel); + } + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Hook.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Hook.java new file mode 100644 index 0000000000..02760fdde4 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Hook.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2018, Google LLC. + * 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.transport; + +/** + * Hook to allow callers to be notified on Git protocol v2 requests. + * + * @see UploadPack#setProtocolV2Hook(ProtocolV2Hook) + * @since 5.1 + */ +public interface ProtocolV2Hook { + /** + * The default hook implementation that does nothing. + */ + static ProtocolV2Hook DEFAULT = new ProtocolV2Hook() { + // No override. + }; + + /** + * @param req + * the capabilities request + * @throws ServiceMayNotContinueException + * abort; the message will be sent to the user + * @since 5.1 + */ + default void onCapabilities(CapabilitiesV2Request req) + throws ServiceMayNotContinueException { + // Do nothing by default. + } + + /** + * @param req + * the ls-refs request + * @throws ServiceMayNotContinueException + * abort; the message will be sent to the user + * @since 5.1 + */ + default void onLsRefs(LsRefsV2Request req) + throws ServiceMayNotContinueException { + // Do nothing by default. + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java index 3ad350d0db..de7be6dec5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java @@ -267,6 +267,9 @@ public class UploadPack { /** The refs we advertised as existing at the start of the connection. */ private Map<String, Ref> refs; + /** Hook used while processing Git protocol v2 requests. */ + private ProtocolV2Hook protocolV2Hook = ProtocolV2Hook.DEFAULT; + /** Hook used while advertising the refs to the client. */ private AdvertiseRefsHook advertiseRefsHook = AdvertiseRefsHook.DEFAULT; @@ -579,6 +582,16 @@ public class UploadPack { } /** + * Set the protocol V2 hook. + * + * @param hook + * @since 5.1 + */ + public void setProtocolV2Hook(ProtocolV2Hook hook) { + this.protocolV2Hook = hook; + } + + /** * Set the filter used while advertising the refs to the client. * <p> * Only refs allowed by this filter will be sent to the client. The filter @@ -880,25 +893,19 @@ public class UploadPack { } private void lsRefsV2() throws IOException { - PacketLineOutRefAdvertiser adv = new PacketLineOutRefAdvertiser(pckOut); - String line; - ArrayList<String> refPrefixes = new ArrayList<>(); - boolean needToFindSymrefs = false; - - adv.setUseProtocolV2(true); - - line = pckIn.readString(); - + LsRefsV2Request.Builder builder = LsRefsV2Request.builder(); + List<String> prefixes = new ArrayList<>(); + String line = pckIn.readString(); // Currently, we do not support any capabilities, so the next // line is DELIM if there are arguments or END if not. if (line == PacketLineIn.DELIM) { while ((line = pckIn.readString()) != PacketLineIn.END) { if (line.equals("peel")) { //$NON-NLS-1$ - adv.setDerefTags(true); + builder.setPeel(true); } else if (line.equals("symrefs")) { //$NON-NLS-1$ - needToFindSymrefs = true; + builder.setSymrefs(true); } else if (line.startsWith("ref-prefix ")) { //$NON-NLS-1$ - refPrefixes.add(line.substring("ref-prefix ".length())); //$NON-NLS-1$ + prefixes.add(line.substring("ref-prefix ".length())); //$NON-NLS-1$ } else { throw new PackProtocolException(MessageFormat .format(JGitText.get().unexpectedPacketLine, line)); @@ -908,21 +915,28 @@ public class UploadPack { throw new PackProtocolException(MessageFormat .format(JGitText.get().unexpectedPacketLine, line)); } - rawOut.stopBuffering(); + LsRefsV2Request req = builder.setRefPrefixes(prefixes).build(); + + protocolV2Hook.onLsRefs(req); + rawOut.stopBuffering(); + PacketLineOutRefAdvertiser adv = new PacketLineOutRefAdvertiser(pckOut); + adv.setUseProtocolV2(true); + if (req.getPeel()) { + adv.setDerefTags(true); + } Map<String, Ref> refsToSend; - if (refPrefixes.isEmpty()) { + if (req.getRefPrefixes().isEmpty()) { refsToSend = getAdvertisedOrDefaultRefs(); } else { refsToSend = new HashMap<>(); - for (String refPrefix : refPrefixes) { + for (String refPrefix : req.getRefPrefixes()) { for (Ref ref : db.getRefDatabase().getRefsByPrefix(refPrefix)) { refsToSend.put(ref.getName(), ref); } } } - - if (needToFindSymrefs) { + if (req.getSymrefs()) { findSymrefs(adv, refsToSend); } @@ -1174,6 +1188,8 @@ public class UploadPack { // is sent only if this is a bidirectional pipe. (If // not, the client is expected to call // sendAdvertisedRefs() on its own.) + protocolV2Hook + .onCapabilities(CapabilitiesV2Request.builder().build()); for (String s : getV2CapabilityAdvertisement()) { pckOut.writeString(s + "\n"); //$NON-NLS-1$ } @@ -1338,6 +1354,8 @@ public class UploadPack { if (useProtocolV2()) { // The equivalent in v2 is only the capabilities // advertisement. + protocolV2Hook + .onCapabilities(CapabilitiesV2Request.builder().build()); for (String s : getV2CapabilityAdvertisement()) { adv.writeOne(s); } |