diff options
Diffstat (limited to 'sha1-name.c')
-rw-r--r-- | sha1-name.c | 117 |
1 files changed, 81 insertions, 36 deletions
diff --git a/sha1-name.c b/sha1-name.c index c9cc1318b7..a656481c6a 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; } @@ -81,51 +83,25 @@ static void update_candidates(struct disambiguate_state *ds, const struct object /* otherwise, current can be discarded and candidate is still good */ } -static int append_loose_object(const struct object_id *oid, const char *path, - void *data) -{ - oid_array_append(data, oid); - return 0; -} - static int match_sha(unsigned, const unsigned char *, const unsigned char *); static void find_short_object_filename(struct disambiguate_state *ds) { - int subdir_nr = ds->bin_pfx.hash[0]; - struct alternate_object_database *alt; - static struct alternate_object_database *fakeent; - - if (!fakeent) { - /* - * Create a "fake" alternate object database that - * points to our own object database, to make it - * easier to get a temporary working space in - * alt->name/alt->base while iterating over the - * object databases including our own. - */ - fakeent = alloc_alt_odb(get_object_directory()); - } - fakeent->next = the_repository->objects->alt_odb_list; + struct object_directory *odb; - for (alt = fakeent; alt && !ds->ambiguous; alt = alt->next) { + for (odb = the_repository->objects->odb; + odb && !ds->ambiguous; + odb = odb->next) { int pos; + struct oid_array *loose_objects; - if (!alt->loose_objects_subdir_seen[subdir_nr]) { - struct strbuf *buf = alt_scratch_buf(alt); - for_each_file_in_obj_subdir(subdir_nr, buf, - append_loose_object, - NULL, NULL, - &alt->loose_objects_cache); - alt->loose_objects_subdir_seen[subdir_nr] = 1; - } - - pos = oid_array_lookup(&alt->loose_objects_cache, &ds->bin_pfx); + loose_objects = odb_loose_cache(odb, &ds->bin_pfx); + pos = oid_array_lookup(loose_objects, &ds->bin_pfx); if (pos < 0) pos = -1 - pos; - while (!ds->ambiguous && pos < alt->loose_objects_cache.nr) { + while (!ds->ambiguous && pos < loose_objects->nr) { const struct object_id *oid; - oid = alt->loose_objects_cache.oid + pos; + oid = loose_objects->oid + pos; if (!match_sha(ds->len, ds->bin_pfx.hash, oid->hash)) break; update_candidates(ds, oid); @@ -149,6 +125,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 +179,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); @@ -529,6 +535,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) { @@ -567,8 +609,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); } |