Skip to content

Commit beb8217

Browse files
ttaylorrgitster
authored andcommitted
pack-bitmap: parse commits in find_pseudo_merge_group_for_ref()
`find_pseudo_merge_group_for_ref()` uses the commit's date to classify it as either "stable" (older than the stable threshold) or "unstable" (otherwise). However, to find the relevant commit from a given OID, the function `find_pseudo_merge_group_for_ref()` uses `lookup_commit()` which does not parse commits. Because an unparsed commit has its "date" set to zero, every candidate is placed in the "stable" bucket regardless of its actual committer timestamp. This means the `bitmapPseudoMerge.*.threshold` and `stableThreshold` configuration options have no effect: the stable/unstable split is always determined by comparing against zero rather than the real commit date. The net result is that pseudo-merge groups are partitioned by `stableSize` instead of the intended decay-based sizing, and the `sampleRate` knob (which only applies to the unstable path) is never exercised. Fix this by calling `repo_parse_commit()` after `lookup_commit()`, bailing out of the callback if parsing fails. The corresponding test configures two pseudo-merge groups that both match all tags. The "stable" group uses `threshold=1.month.ago`, and the "all" group uses `threshold=now`. The test use our custom "GIT_TEST_DATE_NOW" environment variable by setting it to the value of "$test_tick" to align Git's notion of "now" (and therefore "1.month.ago") with the `test_tick` timestamps, so the commits appear to be younger than one month: only the "all" group matches them, producing exactly one pseudo-merge. Without the fix every commit has `date == 0`, which satisfies `date <= threshold` for both groups (since 0 is older than one month ago), and the "stable" group erroneously matches as well. Now that commits are correctly classified as "unstable", the bug described in the test exercising the "sampleRate=0" test is reachable, and the test is marked as failing. It will be fixed in a following commit. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 4ca1878 commit beb8217

2 files changed

Lines changed: 14 additions & 10 deletions

File tree

pseudo-merge.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@ static int find_pseudo_merge_group_for_ref(const struct reference *ref, void *_d
236236
c = lookup_commit(the_repository, maybe_peeled);
237237
if (!c)
238238
return 0;
239+
if (repo_parse_commit(the_repository, c))
240+
return 0;
239241
if (!packlist_find(writer->to_pack, maybe_peeled))
240242
return 0;
241243

t/t5333-pseudo-merge-bitmaps.sh

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -592,32 +592,34 @@ test_expect_success 'apply pseudo-merges with overlapping groups during fill-in'
592592
)
593593
'
594594

595-
test_expect_failure 'pseudo-merge commits are correctly classified by date' '
595+
test_expect_success 'pseudo-merge commits are correctly classified by date' '
596596
git init pseudo-merge-date-classification &&
597597
test_when_finished "rm -fr pseudo-merge-date-classification" &&
598598
(
599599
cd pseudo-merge-date-classification &&
600600
601601
test_commit_bulk 64 &&
602+
602603
tag_everything &&
603604
git repack -ad &&
604605
605606
pack="$(ls .git/objects/pack/pack-*.pack)" &&
606607
607608
# Configure two pseudo-merge groups: one that only
608-
# matches "stable" refs (older than one month), and one
609-
# that matches all refs. With 64 freshly-created tags
610-
# (all younger than one month) the stable group should
611-
# have zero pseudo-merges and the catch-all group should
612-
# have one.
609+
# matches "stable" refs (older than one month), and
610+
# one that matches all refs. With 64 tags whose
611+
# commits are all younger than one month, the
612+
# "stable" group should have zero pseudo-merges and
613+
# the "all" group should have one.
613614
#
614615
# Use GIT_TEST_DATE_NOW to align "now" (and therefore
615616
# "1.month.ago") with the test_tick timestamps so that
616617
# the commits are within the last month.
617618
#
618-
# This exercises the date-based classification in
619-
# find_pseudo_merge_group_for_ref(), which requires
620-
# that commits are parsed before inspecting their date.
619+
# Without parsing the commit, its date field would
620+
# be zero, causing it to satisfy date <= threshold
621+
# for the "stable" group as well, and both groups
622+
# would produce pseudo-merges.
621623
git config bitmapPseudoMerge.stable.pattern "refs/tags/" &&
622624
git config bitmapPseudoMerge.stable.maxMerges 64 &&
623625
git config bitmapPseudoMerge.stable.stableThreshold never &&
@@ -637,7 +639,7 @@ test_expect_failure 'pseudo-merge commits are correctly classified by date' '
637639
)
638640
'
639641

640-
test_expect_success 'sampleRate=0 does not cause division by zero' '
642+
test_expect_failure 'sampleRate=0 does not cause division by zero' '
641643
git init pseudo-merge-sample-rate-zero &&
642644
test_when_finished "rm -fr pseudo-merge-sample-rate-zero" &&
643645
(

0 commit comments

Comments
 (0)