Subject: [RFC PATCH 17/18] sha1_name: use midx for abbreviations

From: Derrick Stolee <[email-masked]>
Date: Sun, 7 Jan 2018 13:14:58 -0500

Create unique_in_midx() to mimic behavior of unique_in_pack().

Create find_abbrev_len_for_midx() to mimic behavior of
find_abbrev_len_for_pack().

Consume these methods when interacting with abbreviations.

Signed-off-by: Derrick Stolee <[email-masked]>
---
 sha1_name.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 68 insertions(+), 2 deletions(-)

diff --git a/sha1_name.c b/sha1_name.c
index 611c7d24dd..2f426e136e 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -10,6 +10,7 @@
 #include "dir.h"
 #include "sha1-array.h"
 #include "packfile.h"
+#include "midx.h"
 
 static int get_oid_oneline(const char *, struct object_id *, struct commit_list *);
 
@@ -190,11 +191,40 @@ static void unique_in_pack(struct packed_git *p,
 	}
 }
 
+static void unique_in_midx(struct midxed_git *m,
+			   struct disambiguate_state *ds)
+{
+	uint32_t num, i, first = 0;
+	const struct object_id *current = NULL;
+
+	if (!m->num_objects)
+		return;
+
+	num = m->num_objects;
+	bsearch_midx(m, ds->bin_pfx.hash, &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 find_short_packed_object(struct disambiguate_state *ds)
 {
 	struct packed_git *p;
+	struct midxed_git *m;
 
-	prepare_packed_git();
+	prepare_packed_git_internal(1);
+	for (m = midxed_git; m && !ds->ambiguous; m = m->next)
+		unique_in_midx(m, ds);
 	for (p = packed_git; p && !ds->ambiguous; p = p->next)
 		unique_in_pack(p, ds);
 }
@@ -508,6 +538,39 @@ static int extend_abbrev_len(const struct object_id *oid, void *cb_data)
 	return 0;
 }
 
+static void find_abbrev_len_for_midx(struct midxed_git *m,
+				     struct min_abbrev_data *mad)
+{
+	int match = 0;
+	uint32_t first = 0;
+	struct object_id oid;
+
+	if (!m->num_objects)
+		return;
+
+	match = bsearch_midx(m, mad->hash, &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 three objects
+	 * nearby for the abbreviation length.
+	 */
+	mad->init_len = 0;
+	if (!match) {
+		nth_midxed_object_oid(&oid, m, first);
+		extend_abbrev_len(&oid, mad);
+	} else if (first < m->num_objects - 1) {
+		nth_midxed_object_oid(&oid, m, first + 1);
+		extend_abbrev_len(&oid, mad);
+	}
+	if (first > 0) {
+		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)
 {
@@ -563,8 +626,11 @@ static void find_abbrev_len_for_pack(struct packed_git *p,
 static void find_abbrev_len_packed(struct min_abbrev_data *mad)
 {
 	struct packed_git *p;
+	struct midxed_git *m;
 
-	prepare_packed_git();
+	prepare_packed_git_internal(1);
+	for (m = midxed_git; m; m = m->next)
+		find_abbrev_len_for_midx(m, mad);
 	for (p = packed_git; p; p = p->next)
 		find_abbrev_len_for_pack(p, mad);
 }
-- 
2.15.0