This extends the fetch-pack protocol to allow the receiving end to ask which actual ref each symbolic ref points at. Although the new capability is advertised on the first available ref in the same way as the other extensions, the way to trigger this extension from the receiving end is not by adding it in the first "want" line as usual. Instead, the receiving end sends a "symbolic-ref" request packet before the usual sequence of "want" lines. This is unfortunate because it forces an extra round trip (receiving end sends a "please tell me symbolic-ref" packet, and then upload side sends "here are the requested information" packet), but it has to be implemented this way because (1) ls-remote may need to ask for this information, in which case there is no "want" to be sent; and (2) the transport API insists that transport_get_remote_refs() returns the final list, and does not allow augmenting what was initially obtained from the call to it by later calls to transport_fetch_refs() easily. It also is unfortunate that with this change on the server side, older clients running "ls-remote" without actually downloading anything will trigger "The remote end hung up unexpectedly" error on the uploading side, which is annoying even though it is benign. You can observe it by applying only this patch but not the patch to the receiving end and running t5601 under "sh -x". Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx> --- upload-pack.c | 43 +++++++++++++++++++++++++++++++++++++++---- 1 files changed, 39 insertions(+), 4 deletions(-) diff --git a/upload-pack.c b/upload-pack.c index 4029019..a925f69 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -494,6 +494,23 @@ static void exchange_shallows(int depth, struct object_array *shallows) } } +static int one_symref_info(const char *refname, const unsigned char *sha1, int flag, void *cb_data) +{ + if ((flag & REF_ISSYMREF)) { + unsigned char dummy[20]; + const char *target = resolve_ref(refname, dummy, 0, NULL); + packet_write(1, "symref %s %s", refname, target); + } + return 0; +} + +static void send_symref_info(void) +{ + head_ref(one_symref_info, NULL); + for_each_ref(one_symref_info, NULL); + packet_flush(1); +} + static void receive_needs(void) { struct object_array shallows = {0, 0, NULL}; @@ -502,11 +519,29 @@ static void receive_needs(void) if (debug_fd) write_in_full(debug_fd, "#S\n", 3); - for (;;) { + + /* + * This is very unfortunate, but the "transport" abstraction + * is screwed up and insists that getting the list of refs + * to finish before actually sending the "needs" list from + * the client end. + */ + len = packet_read_line(0, line, sizeof(line)); + if (len) { + if (!prefixcmp(line, "symbolic-ref")) { + reset_timeout(); + send_symref_info(); + len = 0; + } + } + for (;; len = 0) { struct object *o; unsigned char sha1_buf[20]; - len = packet_read_line(0, line, sizeof(line)); - reset_timeout(); + + if (!len) { + len = packet_read_line(0, line, sizeof(line)); + reset_timeout(); + } if (!len) break; if (debug_fd) @@ -577,7 +612,7 @@ static void receive_needs(void) 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" - " side-band-64k ofs-delta shallow no-progress" + " side-band-64k ofs-delta shallow no-progress symbolic-ref" " include-tag"; struct object *o = parse_object(sha1); -- 1.6.0.4.850.g6bd829 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html