Skip to content

Commit 79f261d

Browse files
ttaylorrgitster
authored andcommitted
pack-bitmap-write: sort pseudo-merge commit lookup table in pack order
The pseudo-merge commit lookup table stores each commit's position in the pack- or pseudo-pack order, and is used to perform a binary search in order to determine which pseudo-merge(s) a given commit belongs to. However, the table was previously sorted in lexical order (via `oid_array_sort()`), causing the binary search to fail. While this causes pseudo-merge bitmaps to be de-facto broken for fill-in traversal, there are a couple of important points to keep in mind: * Pseudo-merge application during the initial phases of a bitmap-based traversal are applied via `cascade_pseudo_merges_1()`. This function enumerates the known pseudo-merges and determines if its parents are a subset of the traversal roots. This is a different path than the fill-in traversal, where we are looking for any pseudo-merges which may be satisfied after visiting some commit along an object walk, which involves the aforementioned (broken) binary search. As a consequence, any pseudo-merges we apply at this stage are done so correctly. * While this bug makes applying pseudo-merges during fill-in traversal effectively broken, it does not produce wrong results. Instead of applying the *wrong* pseudo-merge, we will simply fail to find satisfied pseudo-merges, leaving the traversal to use the existing fill-in routines. Fix this by sorting the table by bit position before writing, matching the order that the reader's binary search expects. This does produce a change the on-disk format insofar as the actual code now complies with the documented format (for more details, refer to: Documentation/technical/bitmap-format.adoc). Given that this never worked in the first place, such a change should be OK to perform. If an out-of-tree implementation of pseudo-merges happened to generate bitmaps that comply with the documented format, they will continue to be read and interpreted as normal. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 856b377 commit 79f261d

2 files changed

Lines changed: 21 additions & 2 deletions

File tree

pack-bitmap-write.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,20 @@ static void write_selected_commits_v1(struct bitmap_writer *writer,
819819
}
820820
}
821821

822+
static int pseudo_merge_commit_pos_cmp(const void *_va, const void *_vb,
823+
void *_data)
824+
{
825+
struct bitmap_writer *writer = _data;
826+
uint32_t pos_a = find_object_pos(writer, _va, NULL);
827+
uint32_t pos_b = find_object_pos(writer, _vb, NULL);
828+
829+
if (pos_a < pos_b)
830+
return -1;
831+
if (pos_a > pos_b)
832+
return 1;
833+
return 0;
834+
}
835+
822836
static void write_pseudo_merges(struct bitmap_writer *writer,
823837
struct hashfile *f)
824838
{
@@ -876,7 +890,12 @@ static void write_pseudo_merges(struct bitmap_writer *writer,
876890
oid_array_append(&commits, &kh_key(writer->pseudo_merge_commits, i));
877891
}
878892

879-
oid_array_sort(&commits);
893+
/*
894+
* Sort the commits by their bit position so that the lookup
895+
* table can be binary searched by the reader (see
896+
* find_pseudo_merge()).
897+
*/
898+
QSORT_S(commits.oid, commits.nr, pseudo_merge_commit_pos_cmp, writer);
880899

881900
/* write lookup table (non-extended) */
882901
for (i = 0; i < commits.nr; i++) {

t/t5333-pseudo-merge-bitmaps.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ test_expect_success 'use pseudo-merge in boundary traversal' '
462462
)
463463
'
464464

465-
test_expect_failure 'apply pseudo-merges during fill-in traversal' '
465+
test_expect_success 'apply pseudo-merges during fill-in traversal' '
466466
git init pseudo-merge-fill-in-traversal &&
467467
test_when_finished "rm -fr pseudo-merge-fill-in-traversal" &&
468468
(

0 commit comments

Comments
 (0)