midx: use midx in abbreviation calculations
Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Derrick Stolee committed
Jul 12, 2018 at 15:39 UTC
8aac67a174061a0744557a3984a433f926bf5cb3
5 files changed
+91
midx.c
+11
@@ -203,6 +203,17 @@ int bsearch_midx(const struct object_id *oid, struct multi_pack_index *m, uint32
203
MIDX_HASH_LEN, result);
204
}
205
206
+struct object_id *nth_midxed_object_oid(struct object_id *oid,
207
+ struct multi_pack_index *m,
208
+ uint32_t n)
209
+{
210
+ if (n >= m->num_objects)
211
+ return NULL;
212
+
213
+ hashcpy(oid->hash, m->chunk_oid_lookup + m->hash_len * n);
214
+ return oid;
215
+}
216
+
217
static off_t nth_midxed_offset(struct multi_pack_index *m, uint32_t pos)
218
{
219
const unsigned char *offset_data;
midx.h
+3
@@ -31,6 +31,9 @@ struct multi_pack_index {
31
32
struct multi_pack_index *load_multi_pack_index(const char *object_dir);
33
int bsearch_midx(const struct object_id *oid, struct multi_pack_index *m, uint32_t *result);
34
+struct object_id *nth_midxed_object_oid(struct object_id *oid,
35
+ struct multi_pack_index *m,
36
+ uint32_t n);
37
int fill_midx_entry(const struct object_id *oid, struct pack_entry *e, struct multi_pack_index *m);
38
int prepare_multi_pack_index_one(struct repository *r, const char *object_dir);
39
packfile.c
+6
@@ -961,6 +961,12 @@ struct packed_git *get_packed_git(struct repository *r)
961
return r->objects->packed_git;
962
}
963
964
+struct multi_pack_index *get_multi_pack_index(struct repository *r)
965
+{
966
+ prepare_packed_git(r);
967
+ return r->objects->multi_pack_index;
968
+}
969
+
970
struct list_head *get_packed_git_mru(struct repository *r)
971
{
972
prepare_packed_git(r);
packfile.h
+1
@@ -45,6 +45,7 @@ extern void install_packed_git(struct repository *r, struct packed_git *pack);
45
46
struct packed_git *get_packed_git(struct repository *r);
47
struct list_head *get_packed_git_mru(struct repository *r);
48
+struct multi_pack_index *get_multi_pack_index(struct repository *r);
49
50
/*
51
* Give a rough count of objects in the repository. This sacrifices accuracy
sha1-name.c
+70
@@ -12,6 +12,7 @@
12
#include "packfile.h"
13
#include "object-store.h"
14
#include "repository.h"
15
+#include "midx.h"
16
17
static int get_oid_oneline(const char *, struct object_id *, struct commit_list *);
18
@@ -149,6 +150,32 @@ static int match_sha(unsigned len, const unsigned char *a, const unsigned char *
150
return 1;
151
}
152
153
+static void unique_in_midx(struct multi_pack_index *m,
154
+ struct disambiguate_state *ds)
155
+{
156
+ uint32_t num, i, first = 0;
157
+ const struct object_id *current = NULL;
158
+ num = m->num_objects;
159
+
160
+ if (!num)
161
+ return;
162
+
163
+ bsearch_midx(&ds->bin_pfx, m, &first);
164
+
165
+ /*
166
+ * At this point, "first" is the location of the lowest object
167
+ * with an object name that could match "bin_pfx". See if we have
168
+ * 0, 1 or more objects that actually match(es).
169
+ */
170
+ for (i = first; i < num && !ds->ambiguous; i++) {
171
+ struct object_id oid;
172
+ current = nth_midxed_object_oid(&oid, m, i);
173
+ if (!match_sha(ds->len, ds->bin_pfx.hash, current->hash))
174
+ break;
175
+ update_candidates(ds, current);
176
+ }
177
+}
178
+
179
static void unique_in_pack(struct packed_git *p,
180
struct disambiguate_state *ds)
181
{
@@ -177,8 +204,12 @@ static void unique_in_pack(struct packed_git *p,
204
205
static void find_short_packed_object(struct disambiguate_state *ds)
206
{
207
+ struct multi_pack_index *m;
208
struct packed_git *p;
209
210
+ for (m = get_multi_pack_index(the_repository); m && !ds->ambiguous;
211
+ m = m->next)
212
+ unique_in_midx(m, ds);
213
for (p = get_packed_git(the_repository); p && !ds->ambiguous;
214
p = p->next)
215
unique_in_pack(p, ds);
@@ -527,6 +558,42 @@ static int extend_abbrev_len(const struct object_id *oid, void *cb_data)
558
return 0;
559
}
560
561
+static void find_abbrev_len_for_midx(struct multi_pack_index *m,
562
+ struct min_abbrev_data *mad)
563
+{
564
+ int match = 0;
565
+ uint32_t num, first = 0;
566
+ struct object_id oid;
567
+ const struct object_id *mad_oid;
568
+
569
+ if (!m->num_objects)
570
+ return;
571
+
572
+ num = m->num_objects;
573
+ mad_oid = mad->oid;
574
+ match = bsearch_midx(mad_oid, m, &first);
575
+
576
+ /*
577
+ * first is now the position in the packfile where we would insert
578
+ * mad->hash if it does not exist (or the position of mad->hash if
579
+ * it does exist). Hence, we consider a maximum of two objects
580
+ * nearby for the abbreviation length.
581
+ */
582
+ mad->init_len = 0;
583
+ if (!match) {
584
+ if (nth_midxed_object_oid(&oid, m, first))
585
+ extend_abbrev_len(&oid, mad);
586
+ } else if (first < num - 1) {
587
+ if (nth_midxed_object_oid(&oid, m, first + 1))
588
+ extend_abbrev_len(&oid, mad);
589
+ }
590
+ if (first > 0) {
591
+ if (nth_midxed_object_oid(&oid, m, first - 1))
592
+ extend_abbrev_len(&oid, mad);
593
+ }
594
+ mad->init_len = mad->cur_len;
595
+}
596
+
597
static void find_abbrev_len_for_pack(struct packed_git *p,
598
struct min_abbrev_data *mad)
599
{
@@ -565,8 +632,11 @@ static void find_abbrev_len_for_pack(struct packed_git *p,
632
633
static void find_abbrev_len_packed(struct min_abbrev_data *mad)
634
{
635
+ struct multi_pack_index *m;
636
struct packed_git *p;
637
638
+ for (m = get_multi_pack_index(the_repository); m; m = m->next)
639
+ find_abbrev_len_for_midx(m, mad);
640
for (p = get_packed_git(the_repository); p; p = p->next)
641
find_abbrev_len_for_pack(p, mad);
642
}