{"thread":{"id":"13271","subject":"[PATCH 2/2] Make ls-remote http://... list HEAD, like for git://...","startedAt":"2008-04-26T19:53:12Z","lastAt":"2008-04-26T19:53:12Z","messageCount":1,"participants":["Daniel Barkalow"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"75233","messageId":"alpine.LNX.1.00.0804261542080.19665@iabervon.org","threadId":"13271","inReplyTo":null,"subject":"[PATCH 2/2] Make ls-remote http://... list HEAD, like for git://...","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2008-04-26T19:53:12Z","receivedAt":"2008-04-26T19:53:12Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"This makes a struct ref able to represent a symref, and makes http.c\nable to recognize one, and makes transport.c look for \"HEAD\" as a ref\nin the list, and makes it dereference symrefs for the resulting ref,\nif any.\n\nSigned-off-by: Daniel Barkalow <barkalow@iabervon.org>\n---\nGetting HEAD for HTTP turns out to be surprisingly tricky. First, you need \nto look for it explicitly, because it's not in info/refs. Then, it's \nnormally a symref, so you have to be able to handle that as a response. \nAnd you don't have the list of things it can reference at that point in \nthe code.\n\nIn any case, it will be useful to be able to have the response from \ntransport_get_remote_refs() able to mention that HEAD is a symref, and \nwhat it links to, so that the HEAD detection can use the remote repo's \nactual information (instead of guessing) when the remote repo provides \nthat information.\n\n cache.h     |    1 +\n http.c      |    5 ++++-\n remote.c    |   23 ++++++++++++++++++++++-\n remote.h    |    2 ++\n transport.c |   14 ++++++++++++++\n 5 files changed, 43 insertions(+), 2 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 50b28fa..7674277 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -624,6 +624,7 @@ struct ref {\n \tstruct ref *next;\n \tunsigned char old_sha1[20];\n \tunsigned char new_sha1[20];\n+\tchar *symref;\n \tunsigned int force:1,\n \t\tmerge:1,\n \t\tnonfastforward:1,\ndiff --git a/http.c b/http.c\nindex c8df13b..acf746a 100644\n--- a/http.c\n+++ b/http.c\n@@ -626,7 +626,10 @@ int http_fetch_ref(const char *base, struct ref *ref)\n \t\t\tstrbuf_rtrim(&buffer);\n \t\t\tif (buffer.len == 40)\n \t\t\t\tret = get_sha1_hex(buffer.buf, ref->old_sha1);\n-\t\t\telse\n+\t\t\telse if (!prefixcmp(buffer.buf, \"ref: \")) {\n+\t\t\t\tref->symref = xstrdup(buffer.buf + 5);\n+\t\t\t\tret = 0;\n+\t\t\t} else\n \t\t\t\tret = 1;\n \t\t} else {\n \t\t\tret = error(\"Couldn't get %s for %s\\n%s\",\ndiff --git a/remote.c b/remote.c\nindex 06ad156..a54f0f7 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -706,13 +706,22 @@ struct ref *copy_ref_list(const struct ref *ref)\n \treturn ret;\n }\n \n+void free_ref(struct ref *ref)\n+{\n+\tif (!ref)\n+\t\treturn;\n+\tfree(ref->remote_status);\n+\tfree(ref->symref);\n+\tfree(ref);\n+}\n+\n void free_refs(struct ref *ref)\n {\n \tstruct ref *next;\n \twhile (ref) {\n \t\tnext = ref->next;\n \t\tfree(ref->peer_ref);\n-\t\tfree(ref);\n+\t\tfree_ref(ref);\n \t\tref = next;\n \t}\n }\n@@ -1146,3 +1155,15 @@ int get_fetch_map(const struct ref *remote_refs,\n \n \treturn 0;\n }\n+\n+int resolve_remote_symref(struct ref *ref, struct ref *list)\n+{\n+\tif (!ref->symref)\n+\t\treturn 0;\n+\tfor (; list; list = list->next)\n+\t\tif (!strcmp(ref->symref, list->name)) {\n+\t\t\thashcpy(ref->old_sha1, list->old_sha1);\n+\t\t\treturn 0;\n+\t\t}\n+\treturn 1;\n+}\ndiff --git a/remote.h b/remote.h\nindex a38774b..ab82308 100644\n--- a/remote.h\n+++ b/remote.h\n@@ -62,6 +62,8 @@ int check_ref_type(const struct ref *ref, int flags);\n  */\n void free_refs(struct ref *ref);\n \n+int resolve_remote_symref(struct ref *ref, struct ref *list);\n+\n /*\n  * Removes and frees any duplicate refs in the map.\n  */\ndiff --git a/transport.c b/transport.c\nindex 393e0e8..b012a28 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -441,10 +441,14 @@ static struct ref *get_refs_via_curl(struct transport *transport)\n \tstruct ref *ref = NULL;\n \tstruct ref *last_ref = NULL;\n \n+\tstruct walker *walker;\n+\n \tif (!transport->data)\n \t\ttransport->data = get_http_walker(transport->url,\n \t\t\t\t\t\ttransport->remote);\n \n+\twalker = transport->data;\n+\n \trefs_url = xmalloc(strlen(transport->url) + 11);\n \tsprintf(refs_url, \"%s/info/refs\", transport->url);\n \n@@ -500,6 +504,16 @@ static struct ref *get_refs_via_curl(struct transport *transport)\n \n \tstrbuf_release(&buffer);\n \n+\tref = alloc_ref(strlen(\"HEAD\") + 1);\n+\tstrcpy(ref->name, \"HEAD\");\n+\tif (!walker->fetch_ref(walker, ref) &&\n+\t    !resolve_remote_symref(ref, refs)) {\n+\t\tref->next = refs;\n+\t\trefs = ref;\n+\t} else {\n+\t\tfree(ref);\n+\t}\n+\n \treturn refs;\n }\n \n-- \n1.5.4.3.610.gea6cd\n"}]}