commit-graph: compute generations separately

The compute_generation_numbers() method was introduced by 3258c663 (commit-graph: compute generation numbers, 2018-05-01) to compute what is now known as "topological levels". These are still stored in the commit-graph file for compatibility sake while c1a09119 (commit-graph: implement corrected commit date, 2021-01-16) updated the method to also compute the new version of generation numbers: corrected commit date. It makes sense why these are grouped. They perform very similar walks of the necessary commits and compute similar maximums over each parent. However, having these two together conflates them in subtle ways that is hard to separate. In particular, the topo_level slab is used to store the topological levels in all cases, but the commit_graph_data_at(c)->generation member stores different values depending on the state of the existing commit-graph file. * If the existing commit-graph file has a "GDAT" chunk, then these values represent corrected commit dates. * If the existing commit-graph file doesn't have a "GDAT" chunk, then these values are actually the topological levels. This issue only occurs only when upgrading an existing commit-graph file into one that has the "GDAT" chunk. The current change does not resolve this upgrade problem, but splitting the implementation into two pieces here helps with that process, which will follow in the next change. The important thing this helps with is the case where the num_generation_data_overflows was being incremented incorrectly, triggering a write of the overflow chunk. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Reviewed-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Feb 2, 2021 at 03:01 UTC 9c2c0a82560a49b6b491a88cbaeaaf30378ec6bb
1 file changed +56 -14
commit-graph.c
+56 -14
@@ -1446,27 +1446,24 @@ static void close_reachable(struct write_commit_graph_context *ctx)
1446 stop_progress(&ctx->progress);
1447 }
1448
1449 -static void compute_generation_numbers(struct write_commit_graph_context *ctx)
1449 +static void compute_topological_levels(struct write_commit_graph_context *ctx)
1450 {
1451 int i;
1452 struct commit_list *list = NULL;
1453
1454 if (ctx->report_progress)
1455 ctx->progress = start_delayed_progress(
1456 - _("Computing commit graph generation numbers"),
1456 + _("Computing commit graph topological levels"),
1457 ctx->commits.nr);
1458 for (i = 0; i < ctx->commits.nr; i++) {
1459 struct commit *c = ctx->commits.list[i];
1460 uint32_t level;
1461 - timestamp_t corrected_commit_date;
1461
1462 repo_parse_commit(ctx->r, c);
1463 level = *topo_level_slab_at(ctx->topo_levels, c);
1465 - corrected_commit_date = commit_graph_data_at(c)->generation;
1464
1465 display_progress(ctx->progress, i + 1);
1468 - if (level != GENERATION_NUMBER_ZERO &&
1469 - corrected_commit_date != GENERATION_NUMBER_ZERO)
1466 + if (level != GENERATION_NUMBER_ZERO)
1467 continue;
1468
1469 commit_list_insert(c, &list);
@@ -1475,15 +1472,12 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
1472 struct commit_list *parent;
1473 int all_parents_computed = 1;
1474 uint32_t max_level = 0;
1478 - timestamp_t max_corrected_commit_date = 0;
1475
1476 for (parent = current->parents; parent; parent = parent->next) {
1477 repo_parse_commit(ctx->r, parent->item);
1478 level = *topo_level_slab_at(ctx->topo_levels, parent->item);
1483 - corrected_commit_date = commit_graph_data_at(parent->item)->generation;
1479
1485 - if (level == GENERATION_NUMBER_ZERO ||
1486 - corrected_commit_date == GENERATION_NUMBER_ZERO) {
1480 + if (level == GENERATION_NUMBER_ZERO) {
1481 all_parents_computed = 0;
1482 commit_list_insert(parent->item, &list);
1483 break;
@@ -1491,9 +1485,6 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
1485
1486 if (level > max_level)
1487 max_level = level;
1494 -
1495 - if (corrected_commit_date > max_corrected_commit_date)
1496 - max_corrected_commit_date = corrected_commit_date;
1488 }
1489
1490 if (all_parents_computed) {
@@ -1502,6 +1493,55 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
1493 if (max_level > GENERATION_NUMBER_V1_MAX - 1)
1494 max_level = GENERATION_NUMBER_V1_MAX - 1;
1495 *topo_level_slab_at(ctx->topo_levels, current) = max_level + 1;
1496 + }
1497 + }
1498 + }
1499 + stop_progress(&ctx->progress);
1500 +}
1501 +
1502 +static void compute_generation_numbers(struct write_commit_graph_context *ctx)
1503 +{
1504 + int i;
1505 + struct commit_list *list = NULL;
1506 +
1507 + if (ctx->report_progress)
1508 + ctx->progress = start_delayed_progress(
1509 + _("Computing commit graph generation numbers"),
1510 + ctx->commits.nr);
1511 + for (i = 0; i < ctx->commits.nr; i++) {
1512 + struct commit *c = ctx->commits.list[i];
1513 + timestamp_t corrected_commit_date;
1514 +
1515 + repo_parse_commit(ctx->r, c);
1516 + corrected_commit_date = commit_graph_data_at(c)->generation;
1517 +
1518 + display_progress(ctx->progress, i + 1);
1519 + if (corrected_commit_date != GENERATION_NUMBER_ZERO)
1520 + continue;
1521 +
1522 + commit_list_insert(c, &list);
1523 + while (list) {
1524 + struct commit *current = list->item;
1525 + struct commit_list *parent;
1526 + int all_parents_computed = 1;
1527 + timestamp_t max_corrected_commit_date = 0;
1528 +
1529 + for (parent = current->parents; parent; parent = parent->next) {
1530 + repo_parse_commit(ctx->r, parent->item);
1531 + corrected_commit_date = commit_graph_data_at(parent->item)->generation;
1532 +
1533 + if (corrected_commit_date == GENERATION_NUMBER_ZERO) {
1534 + all_parents_computed = 0;
1535 + commit_list_insert(parent->item, &list);
1536 + break;
1537 + }
1538 +
1539 + if (corrected_commit_date > max_corrected_commit_date)
1540 + max_corrected_commit_date = corrected_commit_date;
1541 + }
1542 +
1543 + if (all_parents_computed) {
1544 + pop_commit(&list);
1545
1546 if (current->date && current->date > max_corrected_commit_date)
1547 max_corrected_commit_date = current->date - 1;
@@ -2401,7 +2441,9 @@ int write_commit_graph(struct object_directory *odb,
2441
2442 validate_mixed_generation_chain(ctx->r->objects->commit_graph);
2443
2404 - compute_generation_numbers(ctx);
2444 + compute_topological_levels(ctx);
2445 + if (ctx->write_generation_data)
2446 + compute_generation_numbers(ctx);
2447
2448 if (ctx->changed_paths)
2449 compute_bloom_filters(ctx);