git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 7/9] pack-revindex: read multi-pack reverse indexes

From
Taylor Blau <me@ttaylorr.com>
Date
Feb 10, 2021, 23:03 UTC
Message-ID
<4c5e64c5fcb2948a0598d6e0c70097a9561716a9.1612998106.git.me@ttaylorr.com>
In-Reply-To
<cover.1612998106.git.me@ttaylorr.com>

Implement reading for multi-pack reverse indexes, as described in the previous patch.

Note that these functions don't yet have any callers, and won't until multi-pack reachability bitmaps are introduced in a later patch series. In the meantime, this patch implements some of the infrastructure necessary to support multi-pack bitmaps.

There are three new functions exposed by the revindex API:
  - load_midx_revindex(): loads the reverse index corresponding to the
    given multi-pack index.
  - midx_to_pack_pos() and pack_pos_to_midx(): these convert between the
    multi-pack index and pseudo-pack order.

load_midx_revindex() and pack_pos_to_midx() are both relatively straightforward.

load_midx_revindex() needs a few functions to be exposed from the midx API. One to get the checksum of a midx, and another to get the .rev's filename. Similar to recent changes in the packed_git struct, three new fields are added to the multi_pack_index struct: one to keep track of the size, one to keep track of the mmap'd pointer, and another to point past the header and at the reverse index's data.

pack_pos_to_midx() simply reads the corresponding entry out of the table.

midx_to_pack_pos() is the trickiest, since it needs to find an object's position in the psuedo-pack order, but that order can only be recovered in the .rev file itself. This mapping can be implemented with a binary search, but note that the thing we're binary searching over isn't an array, but rather a _permutation_.

So, when comparing two items, it's helpful to keep in mind the difference. Instead of a traditional binary search, where you are comparing two things directly, here we're comparing a (pack, offset) tuple with an index into the multi-pack index. That index describes another (pack, offset) tuple, and it is _those_ two tuples that are compared.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
 midx.c          |  11 +++++
 midx.h          |   6 +++
 pack-revindex.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++
 pack-revindex.h |  46 ++++++++++++++++++++
 packfile.c      |   3 ++
 5 files changed, 178 insertions(+)
diff --git a/midx.c b/midx.c
index bf258c4fde..12bfce8bb1 100644
--- a/midx.c
+++ b/midx.c
@@ -48,11 +48,22 @@ static uint8_t oid_version(void)
 	}
 }
 
+static const unsigned char *get_midx_checksum(struct multi_pack_index *m)
+{
+	return m->data + m->data_len - the_hash_algo->rawsz;
+}
+
 static char *get_midx_filename(const char *object_dir)
 {
 	return xstrfmt("%s/pack/multi-pack-index", object_dir);
 }
 
+char *get_midx_rev_filename(struct multi_pack_index *m)
+{
+	return xstrfmt("%s/pack/multi-pack-index-%s.rev",
+		       m->object_dir, hash_to_hex(get_midx_checksum(m)));
+}
+
 struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local)
 {
 	struct multi_pack_index *m = NULL;
diff --git a/midx.h b/midx.h
index 93bd68189e..0a8294d2ee 100644
--- a/midx.h
+++ b/midx.h
@@ -15,6 +15,10 @@ struct multi_pack_index {
 	const unsigned char *data;
 	size_t data_len;
 
+	const uint32_t *revindex_data;
+	const uint32_t *revindex_map;
+	size_t revindex_len;
+
 	uint32_t signature;
 	unsigned char version;
 	unsigned char hash_len;
@@ -37,6 +41,8 @@ struct multi_pack_index {
 
 #define MIDX_PROGRESS     (1 << 0)
 
+char *get_midx_rev_filename(struct multi_pack_index *m);
+
 struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local);
 int prepare_midx_pack(struct repository *r, struct multi_pack_index *m, uint32_t pack_int_id);
 int bsearch_midx(const struct object_id *oid, struct multi_pack_index *m, uint32_t *result);
diff --git a/pack-revindex.c b/pack-revindex.c
index 83fe4de773..da4101f4b2 100644
--- a/pack-revindex.c
+++ b/pack-revindex.c
@@ -3,6 +3,7 @@
 #include "object-store.h"
 #include "packfile.h"
 #include "config.h"
+#include "midx.h"
 
 struct revindex_entry {
 	off_t offset;
@@ -292,6 +293,29 @@ int load_pack_revindex(struct packed_git *p)
 	return -1;
 }
 
+int load_midx_revindex(struct multi_pack_index *m)
+{
+	char *revindex_name;
+	int ret;
+	if (m->revindex_data)
+		return 0;
+
+	revindex_name = get_midx_rev_filename(m);
+
+	ret = load_revindex_from_disk(revindex_name,
+				      m->num_objects,
+				      &m->revindex_map,
+				      &m->revindex_len);
+	if (ret)
+		goto cleanup;
+
+	m->revindex_data = (const uint32_t *)((const char *)m->revindex_map + RIDX_HEADER_SIZE);
+
+cleanup:
+	free(revindex_name);
+	return ret;
+}
+
 int offset_to_pack_pos(struct packed_git *p, off_t ofs, uint32_t *pos)
 {
 	unsigned lo, hi;
@@ -346,3 +370,91 @@ off_t pack_pos_to_offset(struct packed_git *p, uint32_t pos)
 	else
 		return nth_packed_object_offset(p, pack_pos_to_index(p, pos));
 }
+
+uint32_t pack_pos_to_midx(struct multi_pack_index *m, uint32_t pos)
+{
+	if (!m->revindex_data)
+		BUG("pack_pos_to_midx: reverse index not yet loaded");
+	if (m->num_objects <= pos)
+		BUG("pack_pos_to_midx: out-of-bounds object at %"PRIu32, pos);
+	return get_be32((const char *)m->revindex_data + (pos * sizeof(uint32_t)));
+}
+
+struct midx_pack_key {
+	uint32_t pack;
+	off_t offset;
+
+	uint32_t preferred_pack;
+	struct multi_pack_index *midx;
+};
+
+static int midx_pack_order_cmp(const void *va, const void *vb)
+{
+	const struct midx_pack_key *key = va;
+	struct multi_pack_index *midx = key->midx;
+
+	uint32_t versus = pack_pos_to_midx(midx, (uint32_t*)vb - (const uint32_t *)midx->revindex_data);
+	uint32_t versus_pack = nth_midxed_pack_int_id(midx, versus);
+	off_t versus_offset;
+
+	uint32_t key_preferred = key->pack == key->preferred_pack;
+	uint32_t versus_preferred = versus_pack == key->preferred_pack;
+
+	/*
+	 * First, compare the preferred-ness, noting that the preferred pack
+	 * comes first.
+	 */
+	if (key_preferred && !versus_preferred)
+		return -1;
+	else if (!key_preferred && versus_preferred)
+		return 1;
+
+	/* Then, break ties first by comparing the pack IDs. */
+	if (key->pack < versus_pack)
+		return -1;
+	else if (key->pack > versus_pack)
+		return 1;
+
+	/* Finally, break ties by comparing offsets within a pack. */
+	versus_offset = nth_midxed_offset(midx, versus);
+	if (key->offset < versus_offset)
+		return -1;
+	else if (key->offset > versus_offset)
+		return 1;
+
+	return 0;
+}
+
+int midx_to_pack_pos(struct multi_pack_index *m, uint32_t at, uint32_t *pos)
+{
+	struct midx_pack_key key;
+	uint32_t *found;
+
+	if (!m->revindex_data)
+		BUG("midx_to_pack_pos: reverse index not yet loaded");
+	if (m->num_objects <= at)
+		BUG("midx_to_pack_pos: out-of-bounds object at %"PRIu32, at);
+
+	key.pack = nth_midxed_pack_int_id(m, at);
+	key.offset = nth_midxed_offset(m, at);
+	key.midx = m;
+	/*
+	 * The preferred pack sorts first, so determine its identifier by
+	 * looking at the first object in pseudo-pack order.
+	 *
+	 * Note that if no --preferred-pack is explicitly given when writing a
+	 * multi-pack index, then whichever pack has the lowest identifier
+	 * implicitly is preferred (and includes all its objects, since ties are
+	 * broken first by pack identifier).
+	 */
+	key.preferred_pack = nth_midxed_pack_int_id(m, pack_pos_to_midx(m, 0));
+
+	found = bsearch(&key, m->revindex_data, m->num_objects,
+			sizeof(uint32_t), midx_pack_order_cmp);
+
+	if (!found)
+		return error("bad offset for revindex");
+
+	*pos = found - m->revindex_data;
+	return 0;
+}
diff --git a/pack-revindex.h b/pack-revindex.h
index ba7c82c125..49d604aa9a 100644
--- a/pack-revindex.h
+++ b/pack-revindex.h
@@ -14,6 +14,20 @@
  *
  * - offset: the byte offset within the .pack file at which the object contents
  *   can be found
+ *
+ * The revindex can also be used with a multi-pack index (MIDX). In this
+ * setting:
+ *
+ *   - index position refers to an object's numeric position within the MIDX
+ *
+ *   - pack position refers to an object's position within a non-existent pack
+ *     described by the MIDX. The pack structure is described in
+ *     Documentation/technical/pack-format.txt.
+ *
+ *     It is effectively a concatanation of all packs in the MIDX (ordered by
+ *     their numeric ID within the MIDX) in their original order within each
+ *     pack), removing duplicates, and placing the preferred pack (if any)
+ *     first.
  */
 
 
@@ -24,6 +38,7 @@
 #define GIT_TEST_REV_INDEX_DIE_IN_MEMORY "GIT_TEST_REV_INDEX_DIE_IN_MEMORY"
 
 struct packed_git;
+struct multi_pack_index;
 
 /*
  * load_pack_revindex populates the revindex's internal data-structures for the
@@ -34,6 +49,15 @@ struct packed_git;
  */
 int load_pack_revindex(struct packed_git *p);
 
+/*
+ * load_midx_revindex loads the '.rev' file corresponding to the given
+ * multi-pack index by mmap-ing it and assigning pointers in the
+ * multi_pack_index to point at it.
+ *
+ * A negative number is returned on error.
+ */
+int load_midx_revindex(struct multi_pack_index *m);
+
 /*
  * offset_to_pack_pos converts an object offset to a pack position. This
  * function returns zero on success, and a negative number otherwise. The
@@ -71,4 +95,26 @@ uint32_t pack_pos_to_index(struct packed_git *p, uint32_t pos);
  */
 off_t pack_pos_to_offset(struct packed_git *p, uint32_t pos);
 
+/*
+ * pack_pos_to_midx converts the object at position "pos" within the MIDX
+ * pseudo-pack into a MIDX position.
+ *
+ * If the reverse index has not yet been loaded, or the position is out of
+ * bounds, this function aborts.
+ *
+ * This function runs in time O(log N) with the number of objects in the MIDX.
+ */
+uint32_t pack_pos_to_midx(struct multi_pack_index *m, uint32_t pos);
+
+/*
+ * midx_to_pack_pos converts from the MIDX-relative position at "at" to the
+ * corresponding pack position.
+ *
+ * If the reverse index has not yet been loaded, or the position is out of
+ * bounds, this function aborts.
+ *
+ * This function runs in constant time.
+ */
+int midx_to_pack_pos(struct multi_pack_index *midx, uint32_t at, uint32_t *pos);
+
 #endif
diff --git a/packfile.c b/packfile.c
index 1fec12ac5f..82623e0cb4 100644
--- a/packfile.c
+++ b/packfile.c
@@ -862,6 +862,9 @@ static void prepare_pack(const char *full_name, size_t full_name_len,
 
 	if (!strcmp(file_name, "multi-pack-index"))
 		return;
+	if (starts_with(file_name, "multi-pack-index") &&
+	    ends_with(file_name, ".rev"))
+		return;
 	if (ends_with(file_name, ".idx") ||
 	    ends_with(file_name, ".rev") ||
 	    ends_with(file_name, ".pack") ||
-- 
2.30.0.667.g81c0cbc6fd
Previous: Taylor BlauNext: Derrick Stolee
Message 55 of 171 in “midx: implement a multi-pack reverse index”
  1. 0/9 midx: implement a multi-pack reverse indexTaylor Blau, Feb 10, 2021
  2. 1/9 t/helper/test-read-midx.c: add '--show-objects'Taylor Blau, Feb 10, 2021
  3. Derrick StoleeFeb 11, 2021
  4. Taylor BlauFeb 11, 2021
  5. 2/9 midx: allow marking a pack as preferredTaylor Blau, Feb 10, 2021
  6. SZEDER GáborFeb 11, 2021
  7. Taylor BlauFeb 15, 2021
  8. Ævar Arnfjörð BjarmasonFeb 15, 2021
  9. 0/5 commit-graph: parse_options() cleanupÆvar Arnfjörð Bjarmason, Feb 15, 2021
  10. 1/5 commit-graph: define common usage with a macroÆvar Arnfjörð Bjarmason, Feb 15, 2021
  11. Derrick StoleeFeb 16, 2021
  12. 2/5 commit-graph: remove redundant handling of -hÆvar Arnfjörð Bjarmason, Feb 15, 2021
  13. Derrick StoleeFeb 16, 2021
  14. 4/5 commit-graph: refactor dispatch loop for styleÆvar Arnfjörð Bjarmason, Feb 15, 2021
  15. Taylor BlauFeb 15, 2021
  16. Derrick StoleeFeb 16, 2021
  17. Ævar Arnfjörð BjarmasonFeb 16, 2021
  18. Derrick StoleeFeb 16, 2021
  19. 3/5 commit-graph: use parse_options_concat()Ævar Arnfjörð Bjarmason, Feb 15, 2021
  20. Taylor BlauFeb 15, 2021
  21. Taylor BlauFeb 15, 2021
  22. Ævar Arnfjörð BjarmasonFeb 15, 2021
  23. SZEDER GáborSep 17, 2021
  24. Jeff KingSep 17, 2021
  25. Taylor BlauSep 18, 2021
  26. Ævar Arnfjörð BjarmasonSep 18, 2021
  27. Taylor BlauSep 18, 2021
  28. Taylor BlauSep 18, 2021
  29. Ævar Arnfjörð BjarmasonSep 18, 2021
  30. 5/5 commit-graph: show usage on "commit-graph [write|verify] garbage"Ævar Arnfjörð Bjarmason, Feb 15, 2021
  31. Taylor BlauFeb 15, 2021
  32. Derrick StoleeFeb 16, 2021
  33. 0/4 midx: split out sub-commandsTaylor Blau, Feb 15, 2021
  34. 1/4 builtin/multi-pack-index.c: inline 'flags' with optionsTaylor Blau, Feb 15, 2021
  35. 2/4 builtin/multi-pack-index.c: don't handle 'progress' separatelyTaylor Blau, Feb 15, 2021
  36. Ævar Arnfjörð BjarmasonFeb 15, 2021
  37. Taylor BlauFeb 15, 2021
  38. Derrick StoleeFeb 16, 2021
  39. 3/4 builtin/multi-pack-index.c: define common usage with a macroTaylor Blau, Feb 15, 2021
  40. 4/4 builtin/multi-pack-index.c: split sub-commandsTaylor Blau, Feb 15, 2021
  41. Ævar Arnfjörð BjarmasonFeb 15, 2021
  42. Taylor BlauFeb 15, 2021
  43. Ævar Arnfjörð BjarmasonFeb 15, 2021
  44. Taylor BlauFeb 15, 2021
  45. Derrick StoleeFeb 16, 2021
  46. Taylor BlauFeb 16, 2021
  47. 3/9 midx: don't free midx_name earlyTaylor Blau, Feb 10, 2021
  48. 4/9 midx: keep track of the checksumTaylor Blau, Feb 10, 2021
  49. Derrick StoleeFeb 11, 2021
  50. Taylor BlauFeb 11, 2021
  51. 5/9 midx: make some functions non-staticTaylor Blau, Feb 10, 2021
  52. 6/9 Documentation/technical: describe multi-pack reverse indexesTaylor Blau, Feb 10, 2021
  53. Derrick StoleeFeb 11, 2021
  54. Taylor BlauFeb 11, 2021
  55. 7/9 pack-revindex: read multi-pack reverse indexesTaylor Blau, Feb 10, 2021
  56. Derrick StoleeFeb 11, 2021
  57. Taylor BlauFeb 11, 2021
  58. Junio C HamanoFeb 11, 2021
  59. Taylor BlauFeb 11, 2021
  60. 8/9 pack-write.c: extract 'write_rev_file_order'Taylor Blau, Feb 10, 2021
  61. 9/9 pack-revindex: write multi-pack reverse indexesTaylor Blau, Feb 10, 2021
  62. Derrick StoleeFeb 11, 2021
  63. Taylor BlauFeb 11, 2021
  64. Junio C HamanoFeb 11, 2021
  65. Derrick StoleeFeb 11, 2021
  66. Junio C HamanoFeb 11, 2021
  67. 00/15 midx: implement a multi-pack reverse indexTaylor Blau, Feb 24, 2021
  68. 01/15 builtin/multi-pack-index.c: inline 'flags' with optionsTaylor Blau, Feb 24, 2021
  69. 03/15 builtin/multi-pack-index.c: define common usage with a macroTaylor Blau, Feb 24, 2021
  70. 02/15 builtin/multi-pack-index.c: don't handle 'progress' separatelyTaylor Blau, Feb 24, 2021
  71. 04/15 builtin/multi-pack-index.c: split sub-commandsTaylor Blau, Feb 24, 2021
  72. Jonathan TanMar 2, 2021
  73. Taylor BlauMar 2, 2021
  74. Jonathan TanMar 4, 2021
  75. Taylor BlauMar 4, 2021
  76. 06/15 builtin/multi-pack-index.c: display usage on unrecognized commandTaylor Blau, Feb 24, 2021
  77. 05/15 builtin/multi-pack-index.c: don't enter bogus cmd_modeTaylor Blau, Feb 24, 2021
  78. 07/15 t/helper/test-read-midx.c: add '--show-objects'Taylor Blau, Feb 24, 2021
  79. 08/15 midx: allow marking a pack as preferredTaylor Blau, Feb 24, 2021
  80. Jonathan TanMar 2, 2021
  81. Taylor BlauMar 2, 2021
  82. Jonathan TanMar 4, 2021
  83. Taylor BlauMar 4, 2021
  84. 15/15 pack-revindex: write multi-pack reverse indexesTaylor Blau, Feb 24, 2021
  85. Jonathan TanMar 2, 2021
  86. Taylor BlauMar 3, 2021
  87. Jonathan TanMar 4, 2021
  88. Taylor BlauMar 4, 2021
  89. 09/15 midx: don't free midx_name earlyTaylor Blau, Feb 24, 2021
  90. 11/15 midx: make some functions non-staticTaylor Blau, Feb 24, 2021
  91. 10/15 midx: keep track of the checksumTaylor Blau, Feb 24, 2021
  92. 12/15 Documentation/technical: describe multi-pack reverse indexesTaylor Blau, Feb 24, 2021
  93. Jonathan TanMar 2, 2021
  94. Taylor BlauMar 2, 2021
  95. Taylor BlauMar 2, 2021
  96. Jonathan TanMar 4, 2021
  97. 13/15 pack-revindex: read multi-pack reverse indexesTaylor Blau, Feb 24, 2021
  98. Jonathan TanMar 2, 2021
  99. Taylor BlauMar 3, 2021
  100. 14/15 pack-write.c: extract 'write_rev_file_order'Taylor Blau, Feb 24, 2021
  101. 00/16 midx: implement a multi-pack reverse indexTaylor Blau, Mar 11, 2021
  102. 02/16 builtin/multi-pack-index.c: don't handle 'progress' separatelyTaylor Blau, Mar 11, 2021
  103. Jeff KingMar 29, 2021
  104. 01/16 builtin/multi-pack-index.c: inline 'flags' with optionsTaylor Blau, Mar 11, 2021
  105. Jeff KingMar 29, 2021
  106. 03/16 builtin/multi-pack-index.c: define common usage with a macroTaylor Blau, Mar 11, 2021
  107. 04/16 builtin/multi-pack-index.c: split sub-commandsTaylor Blau, Mar 11, 2021
  108. Jeff KingMar 29, 2021
  109. Taylor BlauMar 29, 2021
  110. Jeff KingMar 30, 2021
  111. 05/16 builtin/multi-pack-index.c: don't enter bogus cmd_modeTaylor Blau, Mar 11, 2021
  112. 09/16 midx: don't free midx_name earlyTaylor Blau, Mar 11, 2021
  113. 07/16 t/helper/test-read-midx.c: add '--show-objects'Taylor Blau, Mar 11, 2021
  114. 06/16 builtin/multi-pack-index.c: display usage on unrecognized commandTaylor Blau, Mar 11, 2021
  115. Jeff KingMar 29, 2021
  116. Taylor BlauMar 29, 2021
  117. 08/16 midx: allow marking a pack as preferredTaylor Blau, Mar 11, 2021
  118. Jeff KingMar 29, 2021
  119. Taylor BlauMar 29, 2021
  120. Jeff KingMar 30, 2021
  121. 10/16 midx: keep track of the checksumTaylor Blau, Mar 11, 2021
  122. 11/16 midx: make some functions non-staticTaylor Blau, Mar 11, 2021
  123. 12/16 Documentation/technical: describe multi-pack reverse indexesTaylor Blau, Mar 11, 2021
  124. Jeff KingMar 29, 2021
  125. Taylor BlauMar 29, 2021
  126. 13/16 pack-revindex: read multi-pack reverse indexesTaylor Blau, Mar 11, 2021
  127. Jeff KingMar 29, 2021
  128. Taylor BlauMar 29, 2021
  129. 14/16 pack-write.c: extract 'write_rev_file_order'Taylor Blau, Mar 11, 2021
  130. 15/16 pack-revindex: write multi-pack reverse indexesTaylor Blau, Mar 11, 2021
  131. Jeff KingMar 29, 2021
  132. Taylor BlauMar 29, 2021
  133. 16/16 midx.c: improve cache locality in midx_pack_order_cmp()Taylor Blau, Mar 11, 2021
  134. Jeff KingMar 29, 2021
  135. Taylor BlauMar 29, 2021
  136. Jeff KingMar 30, 2021
  137. Derrick StoleeMar 12, 2021
  138. Jeff KingMar 29, 2021
  139. Junio C HamanoMar 29, 2021
  140. Taylor BlauMar 29, 2021
  141. Jeff KingMar 30, 2021
  142. Taylor BlauMar 30, 2021
  143. 00/16 midx: implement a multi-pack reverse indexTaylor Blau, Mar 30, 2021
  144. 01/16 builtin/multi-pack-index.c: inline 'flags' with optionsTaylor Blau, Mar 30, 2021
  145. 02/16 builtin/multi-pack-index.c: don't handle 'progress' separatelyTaylor Blau, Mar 30, 2021
  146. 04/16 builtin/multi-pack-index.c: split sub-commandsTaylor Blau, Mar 30, 2021
  147. 03/16 builtin/multi-pack-index.c: define common usage with a macroTaylor Blau, Mar 30, 2021
  148. 06/16 builtin/multi-pack-index.c: display usage on unrecognized commandTaylor Blau, Mar 30, 2021
  149. 05/16 builtin/multi-pack-index.c: don't enter bogus cmd_modeTaylor Blau, Mar 30, 2021
  150. 07/16 t/helper/test-read-midx.c: add '--show-objects'Taylor Blau, Mar 30, 2021
  151. 08/16 midx: allow marking a pack as preferredTaylor Blau, Mar 30, 2021
  152. Taylor BlauApr 1, 2021
  153. 10/16 midx: keep track of the checksumTaylor Blau, Mar 30, 2021
  154. 09/16 midx: don't free midx_name earlyTaylor Blau, Mar 30, 2021
  155. 11/16 midx: make some functions non-staticTaylor Blau, Mar 30, 2021
  156. 14/16 pack-write.c: extract 'write_rev_file_order'Taylor Blau, Mar 30, 2021
  157. pack-write: skip *.rev work when not writing *.revÆvar Arnfjörð Bjarmason, Sep 8, 2021
  158. Carlo ArenasSep 8, 2021
  159. Taylor BlauSep 8, 2021
  160. Junio C HamanoSep 8, 2021
  161. Taylor BlauSep 8, 2021
  162. Taylor BlauSep 8, 2021
  163. Ævar Arnfjörð BjarmasonSep 8, 2021
  164. Taylor BlauSep 8, 2021
  165. 12/16 Documentation/technical: describe multi-pack reverse indexesTaylor Blau, Mar 30, 2021
  166. 13/16 pack-revindex: read multi-pack reverse indexesTaylor Blau, Mar 30, 2021
  167. 16/16 midx.c: improve cache locality in midx_pack_order_cmp()Taylor Blau, Mar 30, 2021
  168. 15/16 pack-revindex: write multi-pack reverse indexesTaylor Blau, Mar 30, 2021
  169. Jeff KingMar 30, 2021
  170. Taylor BlauMar 30, 2021
  171. Jeff KingMar 30, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.