One long-standing flaw in the pack transfer protocol was that there
was no way to tell the other end which branch "HEAD" points at.
With a new "sym" capability (e.g. "sym=HEAD:refs/heads/master"; can
be repeated more than once to represent symbolic refs other than
HEAD, such as "refs/remotes/origin/HEAD").

Add an infrastructure to collect symbolic refs, format them as extra
capabilities and put it on the wire.  For now, just send information
on the "HEAD" and nothing else.

Signed-off-by: Junio C Hamano <gits...@pobox.com>
---
 upload-pack.c | 48 +++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 43 insertions(+), 5 deletions(-)

diff --git a/upload-pack.c b/upload-pack.c
index a6e107f..53958b9 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -734,6 +734,16 @@ static int mark_our_ref(const char *refname, const 
unsigned char *sha1, int flag
        return 0;
 }
 
+static void format_symref_info(struct strbuf *buf, struct string_list *symref)
+{
+       struct string_list_item *item;
+
+       if (!symref->nr)
+               return;
+       for_each_string_list_item(item, symref)
+               strbuf_addf(buf, " sym=%s:%s", item->string, (char 
*)item->util);
+}
+
 static int send_ref(const char *refname, const unsigned char *sha1, int flag, 
void *cb_data)
 {
        static const char *capabilities = "multi_ack thin-pack side-band"
@@ -745,32 +755,60 @@ static int send_ref(const char *refname, const unsigned 
char *sha1, int flag, vo
        if (mark_our_ref(refname, sha1, flag, NULL))
                return 0;
 
-       if (capabilities)
-               packet_write(1, "%s %s%c%s%s%s agent=%s\n",
+       if (capabilities) {
+               struct strbuf symref_info = STRBUF_INIT;
+
+               format_symref_info(&symref_info, cb_data);
+               packet_write(1, "%s %s%c%s%s%s%s agent=%s\n",
                             sha1_to_hex(sha1), refname_nons,
                             0, capabilities,
                             allow_tip_sha1_in_want ? " allow-tip-sha1-in-want" 
: "",
                             stateless_rpc ? " no-done" : "",
+                            symref_info.buf,
                             git_user_agent_sanitized());
-       else
+               strbuf_release(&symref_info);
+       } else {
                packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname_nons);
+       }
        capabilities = NULL;
        if (!peel_ref(refname, peeled))
                packet_write(1, "%s %s^{}\n", sha1_to_hex(peeled), 
refname_nons);
        return 0;
 }
 
+static int find_symref(const char *refname, const unsigned char *sha1, int 
flag,
+                      void *cb_data)
+{
+       const char *symref_target;
+       struct string_list_item *item;
+       unsigned char unused[20];
+
+       if ((flag & REF_ISSYMREF) == 0)
+               return 0;
+       symref_target = resolve_ref_unsafe(refname, unused, 0, &flag);
+       if (!symref_target || (flag & REF_ISSYMREF) == 0)
+               die("'%s' is a symref but it is not?", refname);
+       item = string_list_append(cb_data, refname);
+       item->util = xstrdup(symref_target);
+       return 0;
+}
+
 static void upload_pack(void)
 {
+       struct string_list symref = STRING_LIST_INIT_DUP;
+
+       head_ref_namespaced(find_symref, &symref);
+
        if (advertise_refs || !stateless_rpc) {
                reset_timeout();
-               head_ref_namespaced(send_ref, NULL);
+               head_ref_namespaced(send_ref, &symref);
                for_each_namespaced_ref(send_ref, NULL);
                packet_flush(1);
        } else {
-               head_ref_namespaced(mark_our_ref, NULL);
+               head_ref_namespaced(mark_our_ref, &symref);
                for_each_namespaced_ref(mark_our_ref, NULL);
        }
+       string_list_clear(&symref, 1);
        if (advertise_refs)
                return;
 
-- 
1.8.4-585-g8d1dcaf

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to