Make ls-remote http://... list HEAD, like for git://...
authorDaniel Barkalow <barkalow@iabervon.org>
Sat, 26 Apr 2008 19:53:12 +0000 (15:53 -0400)
committerJunio C Hamano <gitster@pobox.com>
Sun, 27 Apr 2008 00:36:18 +0000 (17:36 -0700)
This makes a struct ref able to represent a symref, and makes http.c
able to recognize one, and makes transport.c look for "HEAD" as a ref
in the list, and makes it dereference symrefs for the resulting ref,
if any.

Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
cache.h
http.c
remote.c
remote.h
transport.c

diff --git a/cache.h b/cache.h
index 3fcc2830029feb82223f2c82c424c7ea09fdd0b4..cfc123747c2a9e50a114a80b3c247f6f97899edb 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -634,6 +634,7 @@ struct ref {
        struct ref *next;
        unsigned char old_sha1[20];
        unsigned char new_sha1[20];
+       char *symref;
        unsigned int force:1,
                merge:1,
                nonfastforward:1,
diff --git a/http.c b/http.c
index c8df13b8ae186d4565760d3b25103267713f7229..acf746a12da0f0b5e3fe3f097a6626e17da8852c 100644 (file)
--- a/http.c
+++ b/http.c
@@ -626,7 +626,10 @@ int http_fetch_ref(const char *base, struct ref *ref)
                        strbuf_rtrim(&buffer);
                        if (buffer.len == 40)
                                ret = get_sha1_hex(buffer.buf, ref->old_sha1);
-                       else
+                       else if (!prefixcmp(buffer.buf, "ref: ")) {
+                               ref->symref = xstrdup(buffer.buf + 5);
+                               ret = 0;
+                       } else
                                ret = 1;
                } else {
                        ret = error("Couldn't get %s for %s\n%s",
index 2d9af4023eba6f8b2fe528ccbf03569fcaa265ee..1504cd01e863d2fb1c54423d3d4a99ac35b616ee 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -706,13 +706,22 @@ struct ref *copy_ref_list(const struct ref *ref)
        return ret;
 }
 
+void free_ref(struct ref *ref)
+{
+       if (!ref)
+               return;
+       free(ref->remote_status);
+       free(ref->symref);
+       free(ref);
+}
+
 void free_refs(struct ref *ref)
 {
        struct ref *next;
        while (ref) {
                next = ref->next;
                free(ref->peer_ref);
-               free(ref);
+               free_ref(ref);
                ref = next;
        }
 }
@@ -1172,3 +1181,15 @@ int get_fetch_map(const struct ref *remote_refs,
 
        return 0;
 }
+
+int resolve_remote_symref(struct ref *ref, struct ref *list)
+{
+       if (!ref->symref)
+               return 0;
+       for (; list; list = list->next)
+               if (!strcmp(ref->symref, list->name)) {
+                       hashcpy(ref->old_sha1, list->old_sha1);
+                       return 0;
+               }
+       return 1;
+}
index a38774bbdc5acfb5ed9360ac92e1049fa79b26e1..ab8230850cabce7e51c05bf391bcb93a774361c3 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -62,6 +62,8 @@ int check_ref_type(const struct ref *ref, int flags);
  */
 void free_refs(struct ref *ref);
 
+int resolve_remote_symref(struct ref *ref, struct ref *list);
+
 /*
  * Removes and frees any duplicate refs in the map.
  */
index 393e0e8fe233ca51dc4c5db94c55e81ee53baa52..b012a283386de601a7f5df15b11b659c5297f21d 100644 (file)
@@ -441,10 +441,14 @@ static struct ref *get_refs_via_curl(struct transport *transport)
        struct ref *ref = NULL;
        struct ref *last_ref = NULL;
 
+       struct walker *walker;
+
        if (!transport->data)
                transport->data = get_http_walker(transport->url,
                                                transport->remote);
 
+       walker = transport->data;
+
        refs_url = xmalloc(strlen(transport->url) + 11);
        sprintf(refs_url, "%s/info/refs", transport->url);
 
@@ -500,6 +504,16 @@ static struct ref *get_refs_via_curl(struct transport *transport)
 
        strbuf_release(&buffer);
 
+       ref = alloc_ref(strlen("HEAD") + 1);
+       strcpy(ref->name, "HEAD");
+       if (!walker->fetch_ref(walker, ref) &&
+           !resolve_remote_symref(ref, refs)) {
+               ref->next = refs;
+               refs = ref;
+       } else {
+               free(ref);
+       }
+
        return refs;
 }