From a4d695de0dbaf41505cb6db44c6bb8290980398e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 17 Sep 2013 16:03:32 -0700 Subject: upload-pack.c: do not pass confusing cb_data to mark_our_ref() The callee does not use cb_data, and the caller is an intermediate function in a callchain that later wants to use the cb_data for its own use. Clarify the code by breaking the dataflow explicitly by not passing cb_data down to mark_our_ref(). Signed-off-by: Junio C Hamano --- upload-pack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'upload-pack.c') diff --git a/upload-pack.c b/upload-pack.c index 127e59a60..a6e107f0b 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -742,7 +742,7 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo const char *refname_nons = strip_namespace(refname); unsigned char peeled[20]; - if (mark_our_ref(refname, sha1, flag, cb_data)) + if (mark_our_ref(refname, sha1, flag, NULL)) return 0; if (capabilities) -- cgit v1.2.1 From 7171d8c15f919c760d52f814a0aee1b1253385b1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 17 Sep 2013 16:17:33 -0700 Subject: upload-pack: send symbolic ref information as capability 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 capability "symref=HEAD:refs/heads/master", let the sender to tell the receiver what symbolic ref points at what ref. This capability 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 --- upload-pack.c | 48 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) (limited to 'upload-pack.c') diff --git a/upload-pack.c b/upload-pack.c index a6e107f0b..979fc8eae 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, " symref=%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); - for_each_namespaced_ref(send_ref, NULL); + head_ref_namespaced(send_ref, &symref); + for_each_namespaced_ref(send_ref, &symref); packet_flush(1); } else { head_ref_namespaced(mark_our_ref, NULL); for_each_namespaced_ref(mark_our_ref, NULL); } + string_list_clear(&symref, 1); if (advertise_refs) return; -- cgit v1.2.1 From 5e7dcad771cb873e278a0571b46910d7c32e2f6c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 17 Sep 2013 16:21:33 -0700 Subject: upload-pack: send non-HEAD symbolic refs With the same mechanism as used to tell where "HEAD" points at to the other end, we can tell the target of other symbolic refs as well. Signed-off-by: Junio C Hamano --- upload-pack.c | 1 + 1 file changed, 1 insertion(+) (limited to 'upload-pack.c') diff --git a/upload-pack.c b/upload-pack.c index 979fc8eae..2826909eb 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -798,6 +798,7 @@ static void upload_pack(void) struct string_list symref = STRING_LIST_INIT_DUP; head_ref_namespaced(find_symref, &symref); + for_each_namespaced_ref(find_symref, &symref); if (advertise_refs || !stateless_rpc) { reset_timeout(); -- cgit v1.2.1