diff options
Diffstat (limited to 'sha1-name.c')
-rw-r--r-- | sha1-name.c | 119 |
1 files changed, 98 insertions, 21 deletions
diff --git a/sha1-name.c b/sha1-name.c index 60d9ef3c7e..faa60f69e3 100644 --- a/sha1-name.c +++ b/sha1-name.c @@ -12,6 +12,8 @@ #include "packfile.h" #include "object-store.h" #include "repository.h" +#include "midx.h" +#include "commit-reach.h" static int get_oid_oneline(const char *, struct object_id *, struct commit_list *); @@ -44,7 +46,7 @@ static void update_candidates(struct disambiguate_state *ds, const struct object oidcpy(&ds->candidate, current); ds->candidate_exists = 1; return; - } else if (!oidcmp(&ds->candidate, current)) { + } else if (oideq(&ds->candidate, current)) { /* the same as what we already have seen */ return; } @@ -149,6 +151,32 @@ static int match_sha(unsigned len, const unsigned char *a, const unsigned char * return 1; } +static void unique_in_midx(struct multi_pack_index *m, + struct disambiguate_state *ds) +{ + uint32_t num, i, first = 0; + const struct object_id *current = NULL; + num = m->num_objects; + + if (!num) + return; + + bsearch_midx(&ds->bin_pfx, m, &first); + + /* + * At this point, "first" is the location of the lowest object + * with an object name that could match "bin_pfx". See if we have + * 0, 1 or more objects that actually match(es). + */ + for (i = first; i < num && !ds->ambiguous; i++) { + struct object_id oid; + current = nth_midxed_object_oid(&oid, m, i); + if (!match_sha(ds->len, ds->bin_pfx.hash, current->hash)) + break; + update_candidates(ds, current); + } +} + static void unique_in_pack(struct packed_git *p, struct disambiguate_state *ds) { @@ -177,8 +205,12 @@ static void unique_in_pack(struct packed_git *p, static void find_short_packed_object(struct disambiguate_state *ds) { + struct multi_pack_index *m; struct packed_git *p; + for (m = get_multi_pack_index(the_repository); m && !ds->ambiguous; + m = m->next) + unique_in_midx(m, ds); for (p = get_packed_git(the_repository); p && !ds->ambiguous; p = p->next) unique_in_pack(p, ds); @@ -239,7 +271,8 @@ static int disambiguate_committish_only(const struct object_id *oid, void *cb_da return 0; /* We need to do this the hard way... */ - obj = deref_tag(parse_object(oid), NULL, 0); + obj = deref_tag(the_repository, parse_object(the_repository, oid), + NULL, 0); if (obj && obj->type == OBJ_COMMIT) return 1; return 0; @@ -263,7 +296,8 @@ static int disambiguate_treeish_only(const struct object_id *oid, void *cb_data_ return 0; /* We need to do this the hard way... */ - obj = deref_tag(parse_object(oid), NULL, 0); + obj = deref_tag(the_repository, parse_object(the_repository, oid), + NULL, 0); if (obj && (obj->type == OBJ_TREE || obj->type == OBJ_COMMIT)) return 1; return 0; @@ -310,7 +344,7 @@ static int init_object_disambiguation(const char *name, int len, { int i; - if (len < MINIMUM_ABBREV || len > GIT_SHA1_HEXSZ) + if (len < MINIMUM_ABBREV || len > the_hash_algo->hexsz) return -1; memset(ds, 0, sizeof(*ds)); @@ -351,14 +385,14 @@ static int show_ambiguous_object(const struct object_id *oid, void *data) type = oid_object_info(the_repository, oid, NULL); if (type == OBJ_COMMIT) { - struct commit *commit = lookup_commit(oid); + struct commit *commit = lookup_commit(the_repository, oid); if (commit) { struct pretty_print_context pp = {0}; pp.date_mode.type = DATE_SHORT; format_commit_message(commit, " %ad - %s", &desc, &pp); } } else if (type == OBJ_TAG) { - struct tag *tag = lookup_tag(oid); + struct tag *tag = lookup_tag(the_repository, oid); if (!parse_tag(tag) && tag->tag) strbuf_addf(&desc, " %s", tag->tag); } @@ -527,6 +561,42 @@ static int extend_abbrev_len(const struct object_id *oid, void *cb_data) return 0; } +static void find_abbrev_len_for_midx(struct multi_pack_index *m, + struct min_abbrev_data *mad) +{ + int match = 0; + uint32_t num, first = 0; + struct object_id oid; + const struct object_id *mad_oid; + + if (!m->num_objects) + return; + + num = m->num_objects; + mad_oid = mad->oid; + match = bsearch_midx(mad_oid, m, &first); + + /* + * first is now the position in the packfile where we would insert + * mad->hash if it does not exist (or the position of mad->hash if + * it does exist). Hence, we consider a maximum of two objects + * nearby for the abbreviation length. + */ + mad->init_len = 0; + if (!match) { + if (nth_midxed_object_oid(&oid, m, first)) + extend_abbrev_len(&oid, mad); + } else if (first < num - 1) { + if (nth_midxed_object_oid(&oid, m, first + 1)) + extend_abbrev_len(&oid, mad); + } + if (first > 0) { + if (nth_midxed_object_oid(&oid, m, first - 1)) + extend_abbrev_len(&oid, mad); + } + mad->init_len = mad->cur_len; +} + static void find_abbrev_len_for_pack(struct packed_git *p, struct min_abbrev_data *mad) { @@ -565,8 +635,11 @@ static void find_abbrev_len_for_pack(struct packed_git *p, static void find_abbrev_len_packed(struct min_abbrev_data *mad) { + struct multi_pack_index *m; struct packed_git *p; + for (m = get_multi_pack_index(the_repository); m; m = m->next) + find_abbrev_len_for_midx(m, mad); for (p = get_packed_git(the_repository); p; p = p->next) find_abbrev_len_for_pack(p, mad); } @@ -576,6 +649,8 @@ int find_unique_abbrev_r(char *hex, const struct object_id *oid, int len) struct disambiguate_state ds; struct min_abbrev_data mad; struct object_id oid_ret; + const unsigned hexsz = the_hash_algo->hexsz; + if (len < 0) { unsigned long count = approximate_object_count(); /* @@ -599,8 +674,8 @@ int find_unique_abbrev_r(char *hex, const struct object_id *oid, int len) } oid_to_hex_r(hex, oid); - if (len == GIT_SHA1_HEXSZ || !len) - return GIT_SHA1_HEXSZ; + if (len == hexsz || !len) + return hexsz; mad.init_len = len; mad.cur_len = len; @@ -706,7 +781,7 @@ static int get_oid_basic(const char *str, int len, struct object_id *oid, int refs_found = 0; int at, reflog_len, nth_prior = 0; - if (len == GIT_SHA1_HEXSZ && !get_oid_hex(str, oid)) { + if (len == the_hash_algo->hexsz && !get_oid_hex(str, oid)) { if (warn_ambiguous_refs && warn_on_object_refname_ambiguity) { refs_found = dwim_ref(str, len, &tmp_oid, &real_ref); if (refs_found > 0) { @@ -750,7 +825,7 @@ static int get_oid_basic(const char *str, int len, struct object_id *oid, int detached; if (interpret_nth_prior_checkout(str, len, &buf) > 0) { - detached = (buf.len == GIT_SHA1_HEXSZ && !get_oid_hex(buf.buf, oid)); + detached = (buf.len == the_hash_algo->hexsz && !get_oid_hex(buf.buf, oid)); strbuf_release(&buf); if (detached) return 0; @@ -844,7 +919,7 @@ static int get_parent(const char *name, int len, if (ret) return ret; - commit = lookup_commit_reference(&oid); + commit = lookup_commit_reference(the_repository, &oid); if (parse_commit(commit)) return -1; if (!idx) { @@ -872,7 +947,7 @@ static int get_nth_ancestor(const char *name, int len, ret = get_oid_1(name, len, &oid, GET_OID_COMMITTISH); if (ret) return ret; - commit = lookup_commit_reference(&oid); + commit = lookup_commit_reference(the_repository, &oid); if (!commit) return -1; @@ -891,7 +966,7 @@ struct object *peel_to_type(const char *name, int namelen, if (name && !namelen) namelen = strlen(name); while (1) { - if (!o || (!o->parsed && !parse_object(&o->oid))) + if (!o || (!o->parsed && !parse_object(the_repository, &o->oid))) return NULL; if (expected_type == OBJ_ANY || o->type == expected_type) return o; @@ -964,12 +1039,12 @@ static int peel_onion(const char *name, int len, struct object_id *oid, if (get_oid_1(name, sp - name - 2, &outer, lookup_flags)) return -1; - o = parse_object(&outer); + o = parse_object(the_repository, &outer); if (!o) return -1; if (!expected_type) { - o = deref_tag(o, name, sp - name - 2); - if (!o || (!o->parsed && !parse_object(&o->oid))) + o = deref_tag(the_repository, o, name, sp - name - 2); + if (!o || (!o->parsed && !parse_object(the_repository, &o->oid))) return -1; oidcpy(oid, &o->oid); return 0; @@ -1096,11 +1171,12 @@ static int handle_one_ref(const char *path, const struct object_id *oid, int flag, void *cb_data) { struct commit_list **list = cb_data; - struct object *object = parse_object(oid); + struct object *object = parse_object(the_repository, oid); if (!object) return 0; if (object->type == OBJ_TAG) { - object = deref_tag(object, path, strlen(path)); + object = deref_tag(the_repository, object, path, + strlen(path)); if (!object) return 0; } @@ -1142,7 +1218,7 @@ static int get_oid_oneline(const char *prefix, struct object_id *oid, int matches; commit = pop_most_recent_commit(&list, ONELINE_SEEN); - if (!parse_object(&commit->object.oid)) + if (!parse_object(the_repository, &commit->object.oid)) continue; buf = get_commit_buffer(commit, NULL); p = strstr(buf, "\n\n"); @@ -1251,13 +1327,13 @@ int get_oid_mb(const char *name, struct object_id *oid) } if (st) return st; - one = lookup_commit_reference_gently(&oid_tmp, 0); + one = lookup_commit_reference_gently(the_repository, &oid_tmp, 0); if (!one) return -1; if (get_oid_committish(dots[3] ? (dots + 3) : "HEAD", &oid_tmp)) return -1; - two = lookup_commit_reference_gently(&oid_tmp, 0); + two = lookup_commit_reference_gently(the_repository, &oid_tmp, 0); if (!two) return -1; mbs = get_merge_bases(one, two); @@ -1650,6 +1726,7 @@ static int get_oid_with_context_1(const char *name, struct commit_list *list = NULL; for_each_ref(handle_one_ref, &list); + head_ref(handle_one_ref, &list); commit_list_sort_by_date(&list); return get_oid_oneline(name + 2, oid, list); } |