Skip to content

Commit 75979d9

Browse files
derrickstoleegitster
authored andcommitted
commit-graph: fix ordering bug in generation numbers
When computing the generation numbers for a commit-graph, we compute the corrected commit dates and then check if their offsets from the actual dates is too large to fit in the 32-bit Generation Data chunk. However, there is a problem with this approach: if we have parsed the generation data from the previous commit-graph, then we continue the loop because the corrected commit date is already computed. This causes an under-count in the number of overflow values. It is incorrect to add an increment to num_generation_data_overflows next to this 'continue' statement, because we might start double-counting commits that are computed because of the depth-first search walk from a commit with an earlier OID. Instead, iterate over the full commit list at the end, checking the offsets to see how many grow beyond the maximum value. Create a new t5328-commit-graph-64-bit-time.sh test script to handle special cases of testing 64-bit timestamps. This helps demonstrate this bug in more cases. It still won't hit all potential cases until the next change, which reenables reading generation numbers. Use the skip_all trick from 0a2bfcc (t0051: use "skip_all" under !MINGW in single-test file, 2022-02-04) to make the output clean when run on a 32-bit system. Helped-by: Ævar Arnfjörð Bjarmason <[email protected]> Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 17925e0 commit 75979d9

File tree

3 files changed

+48
-5
lines changed

3 files changed

+48
-5
lines changed

commit-graph.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,12 +1556,16 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
15561556
if (current->date && current->date > max_corrected_commit_date)
15571557
max_corrected_commit_date = current->date - 1;
15581558
commit_graph_data_at(current)->generation = max_corrected_commit_date + 1;
1559-
1560-
if (commit_graph_data_at(current)->generation - current->date > GENERATION_NUMBER_V2_OFFSET_MAX)
1561-
ctx->num_generation_data_overflows++;
15621559
}
15631560
}
15641561
}
1562+
1563+
for (i = 0; i < ctx->commits.nr; i++) {
1564+
struct commit *c = ctx->commits.list[i];
1565+
timestamp_t offset = commit_graph_data_at(c)->generation - c->date;
1566+
if (offset > GENERATION_NUMBER_V2_OFFSET_MAX)
1567+
ctx->num_generation_data_overflows++;
1568+
}
15651569
stop_progress(&ctx->progress);
15661570
}
15671571

t/t5318-commit-graph.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,10 +425,10 @@ test_expect_success 'warn on improper hash version' '
425425
)
426426
'
427427

428-
test_expect_success 'lower layers have overflow chunk' '
428+
test_expect_success TIME_IS_64BIT,TIME_T_IS_64BIT 'lower layers have overflow chunk' '
429429
cd "$TRASH_DIRECTORY/full" &&
430430
UNIX_EPOCH_ZERO="@0 +0000" &&
431-
FUTURE_DATE="@2147483646 +0000" &&
431+
FUTURE_DATE="@4147483646 +0000" &&
432432
rm -f .git/objects/info/commit-graph &&
433433
test_commit --date "$FUTURE_DATE" future-1 &&
434434
test_commit --date "$UNIX_EPOCH_ZERO" old-1 &&

t/t5328-commit-graph-64bit-time.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/sh
2+
3+
test_description='commit graph with 64-bit timestamps'
4+
. ./test-lib.sh
5+
6+
if ! test_have_prereq TIME_IS_64BIT || ! test_have_prereq TIME_T_IS_64BIT
7+
then
8+
skip_all='skipping 64-bit timestamp tests'
9+
test_done
10+
fi
11+
12+
. "$TEST_DIRECTORY"/lib-commit-graph.sh
13+
14+
UNIX_EPOCH_ZERO="@0 +0000"
15+
FUTURE_DATE="@4147483646 +0000"
16+
17+
GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0
18+
19+
test_expect_success 'lower layers have overflow chunk' '
20+
rm -f .git/objects/info/commit-graph &&
21+
test_commit --date "$FUTURE_DATE" future-1 &&
22+
test_commit --date "$UNIX_EPOCH_ZERO" old-1 &&
23+
git commit-graph write --reachable &&
24+
test_commit --date "$FUTURE_DATE" future-2 &&
25+
test_commit --date "$UNIX_EPOCH_ZERO" old-2 &&
26+
git commit-graph write --reachable --split=no-merge &&
27+
test_commit extra &&
28+
git commit-graph write --reachable --split=no-merge &&
29+
git commit-graph write --reachable &&
30+
graph_read_expect 5 "generation_data generation_data_overflow" &&
31+
mv .git/objects/info/commit-graph commit-graph-upgraded &&
32+
git commit-graph write --reachable &&
33+
graph_read_expect 5 "generation_data generation_data_overflow" &&
34+
test_cmp .git/objects/info/commit-graph commit-graph-upgraded
35+
'
36+
37+
graph_git_behavior 'overflow' '' HEAD~2 HEAD
38+
39+
test_done

0 commit comments

Comments
 (0)