Jonathan Tan <jonathantanmy@xxxxxxxxxx> writes: > Has anyone looked into solutions for this? Both protocol v0 and v2 do > not send symref information about unborn branches (v0 because, as > protocol-capabilities.txt says, "servers SHOULD include this capability > for the HEAD symref if it is one of the refs being sent"; v2 because > a symref is included only if it refers to one of the refs being sent). > In protocol v2, this could be done by adding a capability to ls-remote > (maybe, "unborn"), and in protocol v0, this could be done either by > updating the existing "symref" capability to be written even when the > target branch is unborn (which is potentially backwards incompatible) or > introducing a new capability which is like "symref". Thanks for looking into this (I think this came up again today during my reviews of some topic). It would be a backward incompatible change to add to v0, but at this point shouldn't we be leaving v0 as-is and move everybody to v2? If it is a simple and safe enough change, though, saying "why not" is very tempting, though. > A small issue is that upload-pack protocol v0 doesn't even write the > blank ref line ("000...000 capabilities^{}") if HEAD points to an unborn > branch, but that can be fixed as in the patch below. I think the codepaths we have today in process_capabilities() and process_dummy_ref() (both in connect.c) would do the right thing when it sees a blank ref line even when nothing gets transported, but I smell that the rewrite of this state machine is fairly recent (say in the past few years) and I do not offhand know if clients before the rewrite of the state machine (say in v2.18.0) would be OK with the change. It should be easy to check, though. > Signed-off-by: Jonathan Tan <jonathantanmy@xxxxxxxxxx> > --- > upload-pack.c | 40 +++++++++++++++++++++++++++------------- > 1 file changed, 27 insertions(+), 13 deletions(-) > > diff --git a/upload-pack.c b/upload-pack.c > index 1006bebd50..d2359a8560 100644 > --- a/upload-pack.c > +++ b/upload-pack.c > @@ -1179,18 +1179,15 @@ static void format_symref_info(struct strbuf *buf, struct string_list *symref) > strbuf_addf(buf, " symref=%s:%s", item->string, (char *)item->util); > } > > -static int send_ref(const char *refname, const struct object_id *oid, > - int flag, void *cb_data) > +static const char *capabilities = "multi_ack thin-pack side-band" > + " side-band-64k ofs-delta shallow deepen-since deepen-not" > + " deepen-relative no-progress include-tag multi_ack_detailed"; > + > +static void write_ref_lines(const char *refname_nons, > + const struct object_id *oid, > + const struct object_id *peeled, > + struct upload_pack_data *data) > { > - static const char *capabilities = "multi_ack thin-pack side-band" > - " side-band-64k ofs-delta shallow deepen-since deepen-not" > - " deepen-relative no-progress include-tag multi_ack_detailed"; > - const char *refname_nons = strip_namespace(refname); > - struct object_id peeled; > - struct upload_pack_data *data = cb_data; > - > - if (mark_our_ref(refname_nons, refname, oid)) > - return 0; > > if (capabilities) { > struct strbuf symref_info = STRBUF_INIT; > @@ -1213,8 +1210,23 @@ static int send_ref(const char *refname, const struct object_id *oid, > packet_write_fmt(1, "%s %s\n", oid_to_hex(oid), refname_nons); > } > capabilities = NULL; > - if (!peel_ref(refname, &peeled)) > - packet_write_fmt(1, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons); > + if (peeled) > + packet_write_fmt(1, "%s %s^{}\n", oid_to_hex(peeled), refname_nons); > +} > + > +static int send_ref(const char *refname, const struct object_id *oid, > + int flag, void *cb_data) > +{ > + const char *refname_nons = strip_namespace(refname); > + struct object_id peeled; > + struct upload_pack_data *data = cb_data; > + > + if (mark_our_ref(refname_nons, refname, oid)) > + return 0; > + write_ref_lines(refname_nons, > + oid, > + peel_ref(refname, &peeled) ? NULL : &peeled, > + data); > return 0; > } > > @@ -1332,6 +1344,8 @@ void upload_pack(struct upload_pack_options *options) > reset_timeout(data.timeout); > head_ref_namespaced(send_ref, &data); > for_each_namespaced_ref(send_ref, &data); > + if (capabilities) > + write_ref_lines("capabilities^{}", &null_oid, NULL, &data); > advertise_shallow_grafts(1); > packet_flush(1); > } else {