Parse <value> as the remote-specific revision indicator. The ref is first stored as 'impure', meaning that it doesn't have any representation within git. Only after the remote helper fetches that version into git, it can tell us which git object (SHA1) that revision maps to. That is done with the new reply 'map <value> <sha1>' to the 'list' command. Signed-off-by: Tomas Carnecky <tom@xxxxxxxxxxxxx> --- builtin/ls-remote.c | 7 ++++++- cache.h | 2 +- remote.c | 8 +++++++- transport-helper.c | 41 +++++++++++++++++++++++++++++++++++++++-- 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c index 97eed40..23dd0d2 100644 --- a/builtin/ls-remote.c +++ b/builtin/ls-remote.c @@ -109,7 +109,12 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) continue; if (!tail_match(pattern, ref->name)) continue; - printf("%s %s\n", sha1_to_hex(ref->old_sha1), ref->name); + if (ref->impure) { + int len = strlen(ref->impure) + strlen(" (impure)"); + printf("%s (impure)%*s %s\n", ref->impure, 40 - len, " ", ref->name); + } else { + printf("%s %s\n", sha1_to_hex(ref->old_sha1), ref->name); + } } return 0; } diff --git a/cache.h b/cache.h index 2ef2fa3..23b43a6 100644 --- a/cache.h +++ b/cache.h @@ -905,7 +905,7 @@ struct ref { struct ref *next; unsigned char old_sha1[20]; unsigned char new_sha1[20]; - char *symref; + char *symref, *impure; unsigned int force:1, merge:1, nonfastforward:1, diff --git a/remote.c b/remote.c index 9143ec7..c355f11 100644 --- a/remote.c +++ b/remote.c @@ -907,6 +907,7 @@ static struct ref *copy_ref(const struct ref *ref) memcpy(cpy, ref, sizeof(struct ref) + len + 1); cpy->next = NULL; cpy->symref = ref->symref ? xstrdup(ref->symref) : NULL; + cpy->impure = ref->impure ? xstrdup(ref->impure) : NULL; cpy->remote_status = ref->remote_status ? xstrdup(ref->remote_status) : NULL; cpy->peer_ref = copy_ref(ref->peer_ref); return cpy; @@ -931,6 +932,7 @@ static void free_ref(struct ref *ref) free_ref(ref->peer_ref); free(ref->remote_status); free(ref->symref); + free(ref->impure); free(ref); } @@ -1453,7 +1455,11 @@ int resolve_remote_symref(struct ref *ref, struct ref *list) return 0; for (; list; list = list->next) if (!strcmp(ref->symref, list->name)) { - hashcpy(ref->old_sha1, list->old_sha1); + if (list->impure) { + ref->impure = xstrdup(list->impure); + } else { + hashcpy(ref->old_sha1, list->old_sha1); + } return 0; } return 1; diff --git a/transport-helper.c b/transport-helper.c index acfc88e..0fe886e 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -307,6 +307,29 @@ static int release_helper(struct transport *transport) return 0; } +/* Map an impure ref to its actual value within Git. */ +static void map_impure_ref(int nr_heads, struct ref **to_fetch, char *map) +{ + int i; + char *eov; + + eov = strchr(map, ' '); + if (!eov) + die("Malformed impure ref mapping: %s", map); + *eov = '\0'; + + /* There may be multiple impure refs with the same value, be sure to + * map all of them. */ + for (i = 0; i < nr_heads; i++) { + struct ref *posn = to_fetch[i]; + if (posn->impure && !strcmp(map, posn->impure)) { + get_sha1_hex(eov + 1, posn->old_sha1); + free(posn->impure); + posn->impure = NULL; + } + } +} + static int fetch_with_fetch(struct transport *transport, int nr_heads, struct ref **to_fetch) { @@ -318,11 +341,17 @@ static int fetch_with_fetch(struct transport *transport, for (i = 0; i < nr_heads; i++) { const struct ref *posn = to_fetch[i]; + if (posn->status & REF_STATUS_UPTODATE) continue; - strbuf_addf(&buf, "fetch %s %s\n", + if (posn->impure) { + strbuf_addf(&buf, "fetch %s %s\n", + posn->impure, posn->name); + } else { + strbuf_addf(&buf, "fetch %s %s\n", sha1_to_hex(posn->old_sha1), posn->name); + } } strbuf_addch(&buf, '\n'); @@ -337,12 +366,18 @@ static int fetch_with_fetch(struct transport *transport, warning("%s also locked %s", data->name, name); else transport->pack_lockfile = xstrdup(name); + } else if (!prefixcmp(buf.buf, "map ")) { + map_impure_ref(nr_heads, to_fetch, buf.buf + 4); } else if (!buf.len) break; else warning("%s unexpectedly said: '%s'", data->name, buf.buf); } + + /* The helper may have created one or more new packs. */ + reprepare_packed_git(); + strbuf_release(&buf); return 0; } @@ -824,7 +859,9 @@ static struct ref *get_refs_list(struct transport *transport, int for_push) *tail = alloc_ref(eov + 1); if (buf.buf[0] == '@') (*tail)->symref = xstrdup(buf.buf + 1); - else if (buf.buf[0] != '?') + else if (buf.buf[0] == ':') { + (*tail)->impure = xstrdup(buf.buf + 1); + } else if (buf.buf[0] != '?') get_sha1_hex(buf.buf, (*tail)->old_sha1); if (eon) { if (has_attribute(eon + 1, "unchanged")) { -- 1.7.3.37.gb6088b -- 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