diff options
author | Jonathan Tan <jonathantanmy@google.com> | 2018-02-22 10:24:19 -0800 |
---|---|---|
committer | Jonathan Nieder <jrn@google.com> | 2018-04-23 10:26:51 -0700 |
commit | 332bc611249d21f9b604f2c0207bf0bdfbfc3a78 (patch) | |
tree | 7238a842e2c4481c0ebe279d30f1a8caa0177a5b /org.eclipse.jgit/src/org/eclipse | |
parent | 2661bc081340ae83d2a2ecba11994d3e8d56586b (diff) | |
download | jgit-332bc611249d21f9b604f2c0207bf0bdfbfc3a78.tar.gz jgit-332bc611249d21f9b604f2c0207bf0bdfbfc3a78.zip |
Implement ls-refs in UploadPack
Implement support for Git protocol v2's "ls-refs" command and its
"symrefs" and "peel" parameters.
This adds support for this command to UploadPack but the git://,
ssh://, and git:// transports do not make use of it yet. That will
have to wait for later patches.
Change-Id: I8abc6bcc6ed4a88c165677ff1245625aca01267b
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
Signed-off-by: Jonathan Nieder <jrn@google.com>
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse')
3 files changed, 79 insertions, 1 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java index 6d39dcd8a7..ccefb51684 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java @@ -222,6 +222,13 @@ public class GitProtocolConstants { */ public static final String CAPABILITY_PUSH_OPTIONS = "push-options"; //$NON-NLS-1$ + /** + * The server supports listing refs using protocol v2. + * + * @since 5.0 + */ + public static final String COMMAND_LS_REFS = "ls-refs"; //$NON-NLS-1$ + static enum MultiAck { OFF, CONTINUE, DETAILED; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java index 6ad39e3ddd..0257ebec63 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java @@ -53,6 +53,7 @@ import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Map; @@ -176,6 +177,11 @@ public abstract class RefAdvertiser { boolean first = true; + private boolean useProtocolV2; + + /* only used in protocol v2 */ + private final Map<String, String> symrefs = new HashMap<>(); + /** * Initialize this advertiser with a repository for peeling tags. * @@ -187,6 +193,15 @@ public abstract class RefAdvertiser { } /** + * @param b + * true if this advertiser should advertise using the + * protocol v2 format, false otherwise + */ + public void setUseProtocolV2(boolean b) { + useProtocolV2 = b; + } + + /** * Toggle tag peeling. * <p> * <p> @@ -253,7 +268,11 @@ public abstract class RefAdvertiser { * @since 3.6 */ public void addSymref(String from, String to) { - advertiseCapability(OPTION_SYMREF, from + ':' + to); + if (useProtocolV2) { + symrefs.put(from, to); + } else { + advertiseCapability(OPTION_SYMREF, from + ':' + to); + } } /** @@ -273,6 +292,23 @@ public abstract class RefAdvertiser { if (ref.getObjectId() == null) continue; + if (useProtocolV2) { + String symrefPart = symrefs.containsKey(ref.getName()) + ? (" symref-target:" + symrefs.get(ref.getName())) + : ""; + String peelPart = ""; + if (derefTags) { + if (!ref.isPeeled() && repository != null) { + ref = repository.peel(ref); + } + if (ref.getPeeledObjectId() != null) { + peelPart = " peeled:" + ref.getPeeledObjectId().getName(); + } + } + writeOne(ref.getObjectId().getName() + " " + ref.getName() + symrefPart + peelPart + "\n"); + continue; + } + advertiseAny(ref.getObjectId(), ref.getName()); if (!derefTags) 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 7f6182bf9b..b2b346a6b3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java @@ -44,6 +44,7 @@ package org.eclipse.jgit.transport; import static org.eclipse.jgit.lib.RefDatabase.ALL; +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.OPTION_ALLOW_REACHABLE_SHA1_IN_WANT; import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_ALLOW_TIP_SHA1_IN_WANT; @@ -117,6 +118,7 @@ public class UploadPack { // supports protocol version 2. private static final String[] v2CapabilityAdvertisement = { "version 2", + COMMAND_LS_REFS }; /** Policy the server uses to validate client requests */ @@ -864,6 +866,35 @@ public class UploadPack { sendPack(accumulator); } + private void lsRefsV2() throws IOException { + PacketLineOutRefAdvertiser adv = new PacketLineOutRefAdvertiser(pckOut); + Map<String, Ref> refs = getAdvertisedOrDefaultRefs(); + String line; + + adv.setUseProtocolV2(true); + + 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")) { + adv.setDerefTags(true); + } else if (line.equals("symrefs")) { + findSymrefs(adv, refs); + } else { + throw new PackProtocolException("unexpected " + line); + } + } + } else if (line != PacketLineIn.END) { + throw new PackProtocolException("unexpected " + line); + } + + adv.send(refs); + adv.end(); + } + /* * Returns true if this is the last command and we should tear down the * connection. @@ -882,6 +913,10 @@ public class UploadPack { // case. return true; } + if (command.equals("command=" + COMMAND_LS_REFS)) { + lsRefsV2(); + return false; + } throw new PackProtocolException("unknown command " + command); } |