Commit 71049b4a479ed20bb2d1d6144d87dce932eefc59

Edward Thomson 2022-01-22T09:03:34

midx: use raw oid data A multi-pack index uses raw oid data, use a byte array to index into them.

diff --git a/src/libgit2/midx.c b/src/libgit2/midx.c
index 0092601..d4e53c4 100644
--- a/src/libgit2/midx.c
+++ b/src/libgit2/midx.c
@@ -115,7 +115,7 @@ static int midx_parse_oid_lookup(
 		struct git_midx_chunk *chunk_oid_lookup)
 {
 	uint32_t i;
-	git_oid *oid, *prev_oid, zero_oid = {{0}};
+	unsigned char *oid, *prev_oid, zero_oid[GIT_OID_RAWSZ] = {0};
 
 	if (chunk_oid_lookup->offset == 0)
 		return midx_error("missing OID Lookup chunk");
@@ -124,10 +124,10 @@ static int midx_parse_oid_lookup(
 	if (chunk_oid_lookup->length != idx->num_objects * GIT_OID_RAWSZ)
 		return midx_error("OID Lookup chunk has wrong length");
 
-	idx->oid_lookup = oid = (git_oid *)(data + chunk_oid_lookup->offset);
-	prev_oid = &zero_oid;
-	for (i = 0; i < idx->num_objects; ++i, ++oid) {
-		if (git_oid_cmp(prev_oid, oid) >= 0)
+	idx->oid_lookup = oid = (unsigned char *)(data + chunk_oid_lookup->offset);
+	prev_oid = zero_oid;
+	for (i = 0; i < idx->num_objects; ++i, oid += GIT_OID_RAWSZ) {
+		if (git_oid_raw_cmp(prev_oid, oid) >= 0)
 			return midx_error("OID Lookup index is non-monotonic");
 		prev_oid = oid;
 	}
@@ -389,7 +389,7 @@ int git_midx_entry_find(
 	int pos, found = 0;
 	size_t pack_index;
 	uint32_t hi, lo;
-	const git_oid *current = NULL;
+	unsigned char *current = NULL;
 	const unsigned char *object_offset;
 	off64_t offset;
 
@@ -403,26 +403,25 @@ int git_midx_entry_find(
 	if (pos >= 0) {
 		/* An object matching exactly the oid was found */
 		found = 1;
-		current = idx->oid_lookup + pos;
+		current = idx->oid_lookup + (pos * GIT_OID_RAWSZ);
 	} else {
 		/* No object was found */
 		/* pos refers to the object with the "closest" oid to short_oid */
 		pos = -1 - pos;
 		if (pos < (int)idx->num_objects) {
-			current = idx->oid_lookup + pos;
+			current = idx->oid_lookup + (pos * GIT_OID_RAWSZ);
 
-			if (!git_oid_ncmp(short_oid, current, len))
+			if (!git_oid_raw_ncmp(short_oid->id, current, len))
 				found = 1;
 		}
 	}
 
 	if (found && len != GIT_OID_HEXSZ && pos + 1 < (int)idx->num_objects) {
 		/* Check for ambiguousity */
-		const git_oid *next = current + 1;
+		const unsigned char *next = current + GIT_OID_RAWSZ;
 
-		if (!git_oid_ncmp(short_oid, next, len)) {
+		if (!git_oid_raw_ncmp(short_oid->id, next, len))
 			found = 2;
-		}
 	}
 
 	if (!found)
@@ -450,7 +449,7 @@ int git_midx_entry_find(
 		return midx_error("invalid index into the packfile names table");
 	e->pack_index = pack_index;
 	e->offset = offset;
-	git_oid_cpy(&e->sha1, current);
+	git_oid_fromraw(&e->sha1, current);
 	return 0;
 }
 
@@ -459,13 +458,17 @@ int git_midx_foreach_entry(
 		git_odb_foreach_cb cb,
 		void *data)
 {
+	git_oid oid;
 	size_t i;
 	int error;
 
 	GIT_ASSERT_ARG(idx);
 
 	for (i = 0; i < idx->num_objects; ++i) {
-		if ((error = cb(&idx->oid_lookup[i], data)) != 0)
+		if ((error = git_oid_fromraw(&oid, &idx->oid_lookup[i * GIT_OID_RAWSZ])) < 0)
+			return error;
+
+		if ((error = cb(&oid, data)) != 0)
 			return git_error_set_after_callback(error);
 	}
 
@@ -751,7 +754,7 @@ static int midx_write(
 
 	/* Fill the OID Lookup table. */
 	git_vector_foreach (&object_entries, i, entry) {
-		error = git_str_put(&oid_lookup, (const char *)&entry->sha1, sizeof(entry->sha1));
+		error = git_str_put(&oid_lookup, (char *)&entry->sha1.id, GIT_OID_RAWSZ);
 		if (error < 0)
 			goto cleanup;
 	}
diff --git a/src/libgit2/midx.h b/src/libgit2/midx.h
index 7dd851b..bcb0d9a 100644
--- a/src/libgit2/midx.h
+++ b/src/libgit2/midx.h
@@ -17,6 +17,7 @@
 #include "map.h"
 #include "mwindow.h"
 #include "odb.h"
+#include "oid.h"
 
 /*
  * A multi-pack-index file.
@@ -40,7 +41,7 @@ typedef struct git_midx_file {
 	uint32_t num_objects;
 
 	/* The OID Lookup table. */
-	git_oid *oid_lookup;
+	unsigned char *oid_lookup;
 
 	/* The Object Offsets table. Each entry has two 4-byte fields with the pack index and the offset. */
 	const unsigned char *object_offsets;