Skip to content

Commit 1373e54

Browse files
derrickstoleegitster
authored andcommitted
commit-graph: verify generation number
While iterating through the commit parents, perform the generation number calculation and compare against the value stored in the commit-graph. The tests demonstrate that having a different set of parents affects the generation number calculation, and this value propagates to descendants. Hence, we drop the single-line condition on the output. Since Git will ship with the commit-graph feature without generation numbers, we need to accept commit-graphs with all generation numbers equal to zero. In this case, ignore the generation number calculation. However, verify that we should never have a mix of zero and non-zero generation numbers. Create a test that sets one commit to generation zero and all following commits report a failure as they have non-zero generation in a file that contains generation number zero. Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 53614b1 commit 1373e54

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

commit-graph.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,10 +846,14 @@ static void graph_report(const char *fmt, ...)
846846
va_end(ap);
847847
}
848848

849+
#define GENERATION_ZERO_EXISTS 1
850+
#define GENERATION_NUMBER_EXISTS 2
851+
849852
int verify_commit_graph(struct repository *r, struct commit_graph *g)
850853
{
851854
uint32_t i, cur_fanout_pos = 0;
852855
struct object_id prev_oid, cur_oid;
856+
int generation_zero = 0;
853857

854858
if (!g) {
855859
graph_report("no commit-graph file loaded");
@@ -911,6 +915,7 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g)
911915
for (i = 0; i < g->num_commits; i++) {
912916
struct commit *graph_commit, *odb_commit;
913917
struct commit_list *graph_parents, *odb_parents;
918+
uint32_t max_generation = 0;
914919

915920
hashcpy(cur_oid.hash, g->chunk_oid_lookup + g->hash_len * i);
916921

@@ -945,13 +950,42 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g)
945950
oid_to_hex(&graph_parents->item->object.oid),
946951
oid_to_hex(&odb_parents->item->object.oid));
947952

953+
if (graph_parents->item->generation > max_generation)
954+
max_generation = graph_parents->item->generation;
955+
948956
graph_parents = graph_parents->next;
949957
odb_parents = odb_parents->next;
950958
}
951959

952960
if (odb_parents != NULL)
953961
graph_report("commit-graph parent list for commit %s terminates early",
954962
oid_to_hex(&cur_oid));
963+
964+
if (!graph_commit->generation) {
965+
if (generation_zero == GENERATION_NUMBER_EXISTS)
966+
graph_report("commit-graph has generation number zero for commit %s, but non-zero elsewhere",
967+
oid_to_hex(&cur_oid));
968+
generation_zero = GENERATION_ZERO_EXISTS;
969+
} else if (generation_zero == GENERATION_ZERO_EXISTS)
970+
graph_report("commit-graph has non-zero generation number for commit %s, but zero elsewhere",
971+
oid_to_hex(&cur_oid));
972+
973+
if (generation_zero == GENERATION_ZERO_EXISTS)
974+
continue;
975+
976+
/*
977+
* If one of our parents has generation GENERATION_NUMBER_MAX, then
978+
* our generation is also GENERATION_NUMBER_MAX. Decrement to avoid
979+
* extra logic in the following condition.
980+
*/
981+
if (max_generation == GENERATION_NUMBER_MAX)
982+
max_generation--;
983+
984+
if (graph_commit->generation != max_generation + 1)
985+
graph_report("commit-graph generation for commit %s is %u != %u",
986+
oid_to_hex(&cur_oid),
987+
graph_commit->generation,
988+
max_generation + 1);
955989
}
956990

957991
return verify_commit_graph_error;

t/t5318-commit-graph.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ GRAPH_BYTE_COMMIT_TREE=$GRAPH_COMMIT_DATA_OFFSET
272272
GRAPH_BYTE_COMMIT_PARENT=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN))
273273
GRAPH_BYTE_COMMIT_EXTRA_PARENT=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 4))
274274
GRAPH_BYTE_COMMIT_WRONG_PARENT=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 3))
275+
GRAPH_BYTE_COMMIT_GENERATION=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 11))
275276

276277
# usage: corrupt_graph_and_verify <position> <data> <string>
277278
# Manipulates the commit-graph file at the position
@@ -366,4 +367,14 @@ test_expect_success 'detect wrong parent' '
366367
"commit-graph parent for"
367368
'
368369

370+
test_expect_success 'detect incorrect generation number' '
371+
corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_GENERATION "\070" \
372+
"generation for commit"
373+
'
374+
375+
test_expect_success 'detect incorrect generation number' '
376+
corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_GENERATION "\01" \
377+
"non-zero generation number"
378+
'
379+
369380
test_done

0 commit comments

Comments
 (0)