Skip to content

Commit 5bd0b21

Browse files
committed
Merge branch 'ds/commit-graph-genno-fix'
Fix incremental update of commit-graph file around corrected commit date data. * ds/commit-graph-genno-fix: commit-graph: prepare commit graph commit-graph: be extra careful about mixed generations commit-graph: compute generations separately commit-graph: validate layers for generation data commit-graph: always parse before commit_graph_data_at() commit-graph: use repo_parse_commit
2 parents 8b4701a + bc50d6c commit 5bd0b21

File tree

3 files changed

+125
-39
lines changed

3 files changed

+125
-39
lines changed

commit-graph.c

Lines changed: 101 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -614,19 +614,29 @@ static struct commit_graph *load_commit_graph_chain(struct repository *r,
614614
return graph_chain;
615615
}
616616

617-
static void validate_mixed_generation_chain(struct commit_graph *g)
617+
/*
618+
* returns 1 if and only if all graphs in the chain have
619+
* corrected commit dates stored in the generation_data chunk.
620+
*/
621+
static int validate_mixed_generation_chain(struct commit_graph *g)
618622
{
619-
int read_generation_data;
623+
int read_generation_data = 1;
624+
struct commit_graph *p = g;
620625

621-
if (!g)
622-
return;
626+
while (read_generation_data && p) {
627+
read_generation_data = p->read_generation_data;
628+
p = p->base_graph;
629+
}
623630

624-
read_generation_data = !!g->chunk_generation_data;
631+
if (read_generation_data)
632+
return 1;
625633

626634
while (g) {
627-
g->read_generation_data = read_generation_data;
635+
g->read_generation_data = 0;
628636
g = g->base_graph;
629637
}
638+
639+
return 0;
630640
}
631641

632642
struct commit_graph *read_commit_graph_one(struct repository *r,
@@ -1026,7 +1036,8 @@ struct write_commit_graph_context {
10261036
split:1,
10271037
changed_paths:1,
10281038
order_by_pack:1,
1029-
write_generation_data:1;
1039+
write_generation_data:1,
1040+
trust_generation_numbers:1;
10301041

10311042
struct topo_level_slab *topo_levels;
10321043
const struct commit_graph_opts *opts;
@@ -1098,7 +1109,7 @@ static int write_graph_chunk_data(struct hashfile *f,
10981109
uint32_t packedDate[2];
10991110
display_progress(ctx->progress, ++ctx->progress_cnt);
11001111

1101-
if (parse_commit_no_graph(*list))
1112+
if (repo_parse_commit_no_graph(ctx->r, *list))
11021113
die(_("unable to parse commit %s"),
11031114
oid_to_hex(&(*list)->object.oid));
11041115
tree = get_commit_tree_oid(*list);
@@ -1193,7 +1204,9 @@ static int write_graph_chunk_generation_data(struct hashfile *f,
11931204

11941205
for (i = 0; i < ctx->commits.nr; i++) {
11951206
struct commit *c = ctx->commits.list[i];
1196-
timestamp_t offset = commit_graph_data_at(c)->generation - c->date;
1207+
timestamp_t offset;
1208+
repo_parse_commit(ctx->r, c);
1209+
offset = commit_graph_data_at(c)->generation - c->date;
11971210
display_progress(ctx->progress, ++ctx->progress_cnt);
11981211

11991212
if (offset > GENERATION_NUMBER_V2_OFFSET_MAX) {
@@ -1411,11 +1424,11 @@ static void close_reachable(struct write_commit_graph_context *ctx)
14111424
if (!commit)
14121425
continue;
14131426
if (ctx->split) {
1414-
if ((!parse_commit(commit) &&
1427+
if ((!repo_parse_commit(ctx->r, commit) &&
14151428
commit_graph_position(commit) == COMMIT_NOT_FROM_GRAPH) ||
14161429
flags == COMMIT_GRAPH_SPLIT_REPLACE)
14171430
add_missing_parents(ctx, commit);
1418-
} else if (!parse_commit_no_graph(commit))
1431+
} else if (!repo_parse_commit_no_graph(ctx->r, commit))
14191432
add_missing_parents(ctx, commit);
14201433
}
14211434
stop_progress(&ctx->progress);
@@ -1434,48 +1447,45 @@ static void close_reachable(struct write_commit_graph_context *ctx)
14341447
stop_progress(&ctx->progress);
14351448
}
14361449

1437-
static void compute_generation_numbers(struct write_commit_graph_context *ctx)
1450+
static void compute_topological_levels(struct write_commit_graph_context *ctx)
14381451
{
14391452
int i;
14401453
struct commit_list *list = NULL;
14411454

14421455
if (ctx->report_progress)
14431456
ctx->progress = start_delayed_progress(
1444-
_("Computing commit graph generation numbers"),
1457+
_("Computing commit graph topological levels"),
14451458
ctx->commits.nr);
14461459
for (i = 0; i < ctx->commits.nr; i++) {
1447-
uint32_t level = *topo_level_slab_at(ctx->topo_levels, ctx->commits.list[i]);
1448-
timestamp_t corrected_commit_date = commit_graph_data_at(ctx->commits.list[i])->generation;
1460+
struct commit *c = ctx->commits.list[i];
1461+
uint32_t level;
1462+
1463+
repo_parse_commit(ctx->r, c);
1464+
level = *topo_level_slab_at(ctx->topo_levels, c);
14491465

14501466
display_progress(ctx->progress, i + 1);
1451-
if (level != GENERATION_NUMBER_ZERO &&
1452-
corrected_commit_date != GENERATION_NUMBER_ZERO)
1467+
if (level != GENERATION_NUMBER_ZERO)
14531468
continue;
14541469

1455-
commit_list_insert(ctx->commits.list[i], &list);
1470+
commit_list_insert(c, &list);
14561471
while (list) {
14571472
struct commit *current = list->item;
14581473
struct commit_list *parent;
14591474
int all_parents_computed = 1;
14601475
uint32_t max_level = 0;
1461-
timestamp_t max_corrected_commit_date = 0;
14621476

14631477
for (parent = current->parents; parent; parent = parent->next) {
1478+
repo_parse_commit(ctx->r, parent->item);
14641479
level = *topo_level_slab_at(ctx->topo_levels, parent->item);
1465-
corrected_commit_date = commit_graph_data_at(parent->item)->generation;
14661480

1467-
if (level == GENERATION_NUMBER_ZERO ||
1468-
corrected_commit_date == GENERATION_NUMBER_ZERO) {
1481+
if (level == GENERATION_NUMBER_ZERO) {
14691482
all_parents_computed = 0;
14701483
commit_list_insert(parent->item, &list);
14711484
break;
14721485
}
14731486

14741487
if (level > max_level)
14751488
max_level = level;
1476-
1477-
if (corrected_commit_date > max_corrected_commit_date)
1478-
max_corrected_commit_date = corrected_commit_date;
14791489
}
14801490

14811491
if (all_parents_computed) {
@@ -1484,6 +1494,64 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
14841494
if (max_level > GENERATION_NUMBER_V1_MAX - 1)
14851495
max_level = GENERATION_NUMBER_V1_MAX - 1;
14861496
*topo_level_slab_at(ctx->topo_levels, current) = max_level + 1;
1497+
}
1498+
}
1499+
}
1500+
stop_progress(&ctx->progress);
1501+
}
1502+
1503+
static void compute_generation_numbers(struct write_commit_graph_context *ctx)
1504+
{
1505+
int i;
1506+
struct commit_list *list = NULL;
1507+
1508+
if (ctx->report_progress)
1509+
ctx->progress = start_delayed_progress(
1510+
_("Computing commit graph generation numbers"),
1511+
ctx->commits.nr);
1512+
1513+
if (!ctx->trust_generation_numbers) {
1514+
for (i = 0; i < ctx->commits.nr; i++) {
1515+
struct commit *c = ctx->commits.list[i];
1516+
repo_parse_commit(ctx->r, c);
1517+
commit_graph_data_at(c)->generation = GENERATION_NUMBER_ZERO;
1518+
}
1519+
}
1520+
1521+
for (i = 0; i < ctx->commits.nr; i++) {
1522+
struct commit *c = ctx->commits.list[i];
1523+
timestamp_t corrected_commit_date;
1524+
1525+
repo_parse_commit(ctx->r, c);
1526+
corrected_commit_date = commit_graph_data_at(c)->generation;
1527+
1528+
display_progress(ctx->progress, i + 1);
1529+
if (corrected_commit_date != GENERATION_NUMBER_ZERO)
1530+
continue;
1531+
1532+
commit_list_insert(c, &list);
1533+
while (list) {
1534+
struct commit *current = list->item;
1535+
struct commit_list *parent;
1536+
int all_parents_computed = 1;
1537+
timestamp_t max_corrected_commit_date = 0;
1538+
1539+
for (parent = current->parents; parent; parent = parent->next) {
1540+
repo_parse_commit(ctx->r, parent->item);
1541+
corrected_commit_date = commit_graph_data_at(parent->item)->generation;
1542+
1543+
if (corrected_commit_date == GENERATION_NUMBER_ZERO) {
1544+
all_parents_computed = 0;
1545+
commit_list_insert(parent->item, &list);
1546+
break;
1547+
}
1548+
1549+
if (corrected_commit_date > max_corrected_commit_date)
1550+
max_corrected_commit_date = corrected_commit_date;
1551+
}
1552+
1553+
if (all_parents_computed) {
1554+
pop_commit(&list);
14871555

14881556
if (current->date && current->date > max_corrected_commit_date)
14891557
max_corrected_commit_date = current->date - 1;
@@ -1710,9 +1778,9 @@ static void copy_oids_to_commits(struct write_commit_graph_context *ctx)
17101778
continue;
17111779

17121780
if (ctx->split && flags == COMMIT_GRAPH_SPLIT_REPLACE)
1713-
parse_commit(ctx->commits.list[ctx->commits.nr]);
1781+
repo_parse_commit(ctx->r, ctx->commits.list[ctx->commits.nr]);
17141782
else
1715-
parse_commit_no_graph(ctx->commits.list[ctx->commits.nr]);
1783+
repo_parse_commit_no_graph(ctx->r, ctx->commits.list[ctx->commits.nr]);
17161784

17171785
num_parents = commit_list_count(ctx->commits.list[ctx->commits.nr]->parents);
17181786
if (num_parents > 2)
@@ -2280,6 +2348,7 @@ int write_commit_graph(struct object_directory *odb,
22802348
init_topo_level_slab(&topo_levels);
22812349
ctx->topo_levels = &topo_levels;
22822350

2351+
prepare_commit_graph(ctx->r);
22832352
if (ctx->r->objects->commit_graph) {
22842353
struct commit_graph *g = ctx->r->objects->commit_graph;
22852354

@@ -2293,7 +2362,6 @@ int write_commit_graph(struct object_directory *odb,
22932362
ctx->changed_paths = 1;
22942363
if (!(flags & COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS)) {
22952364
struct commit_graph *g;
2296-
prepare_commit_graph_one(ctx->r, ctx->odb);
22972365

22982366
g = ctx->r->objects->commit_graph;
22992367

@@ -2305,10 +2373,7 @@ int write_commit_graph(struct object_directory *odb,
23052373
}
23062374

23072375
if (ctx->split) {
2308-
struct commit_graph *g;
2309-
prepare_commit_graph(ctx->r);
2310-
2311-
g = ctx->r->objects->commit_graph;
2376+
struct commit_graph *g = ctx->r->objects->commit_graph;
23122377

23132378
while (g) {
23142379
ctx->num_commit_graphs_before++;
@@ -2332,9 +2397,6 @@ int write_commit_graph(struct object_directory *odb,
23322397

23332398
ctx->approx_nr_objects = approximate_object_count();
23342399

2335-
if (ctx->append)
2336-
prepare_commit_graph_one(ctx->r, ctx->odb);
2337-
23382400
if (ctx->append && ctx->r->objects->commit_graph) {
23392401
struct commit_graph *g = ctx->r->objects->commit_graph;
23402402
for (i = 0; i < g->num_commits; i++) {
@@ -2381,9 +2443,11 @@ int write_commit_graph(struct object_directory *odb,
23812443
} else
23822444
ctx->num_commit_graphs_after = 1;
23832445

2384-
validate_mixed_generation_chain(ctx->r->objects->commit_graph);
2446+
ctx->trust_generation_numbers = validate_mixed_generation_chain(ctx->r->objects->commit_graph);
23852447

2386-
compute_generation_numbers(ctx);
2448+
compute_topological_levels(ctx);
2449+
if (ctx->write_generation_data)
2450+
compute_generation_numbers(ctx);
23872451

23882452
if (ctx->changed_paths)
23892453
compute_bloom_filters(ctx);

commit.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,10 @@ static inline int repo_parse_commit(struct repository *r, struct commit *item)
8989
return repo_parse_commit_gently(r, item, 0);
9090
}
9191

92-
static inline int parse_commit_no_graph(struct commit *commit)
92+
static inline int repo_parse_commit_no_graph(struct repository *r,
93+
struct commit *commit)
9394
{
94-
return repo_parse_commit_internal(the_repository, commit, 0, 0);
95+
return repo_parse_commit_internal(r, commit, 0, 0);
9596
}
9697

9798
#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS

t/t5318-commit-graph.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,27 @@ test_expect_success 'warn on improper hash version' '
446446
)
447447
'
448448

449+
test_expect_success 'lower layers have overflow chunk' '
450+
cd "$TRASH_DIRECTORY/full" &&
451+
UNIX_EPOCH_ZERO="@0 +0000" &&
452+
FUTURE_DATE="@2147483646 +0000" &&
453+
rm -f .git/objects/info/commit-graph &&
454+
test_commit --date "$FUTURE_DATE" future-1 &&
455+
test_commit --date "$UNIX_EPOCH_ZERO" old-1 &&
456+
git commit-graph write --reachable &&
457+
test_commit --date "$FUTURE_DATE" future-2 &&
458+
test_commit --date "$UNIX_EPOCH_ZERO" old-2 &&
459+
git commit-graph write --reachable --split=no-merge &&
460+
test_commit extra &&
461+
git commit-graph write --reachable --split=no-merge &&
462+
git commit-graph write --reachable &&
463+
graph_read_expect 16 "generation_data generation_data_overflow extra_edges" &&
464+
mv .git/objects/info/commit-graph commit-graph-upgraded &&
465+
git commit-graph write --reachable &&
466+
graph_read_expect 16 "generation_data generation_data_overflow extra_edges" &&
467+
test_cmp .git/objects/info/commit-graph commit-graph-upgraded
468+
'
469+
449470
# the verify tests below expect the commit-graph to contain
450471
# exactly the commits reachable from the commits/8 branch.
451472
# If the file changes the set of commits in the list, then the

0 commit comments

Comments
 (0)