commit-graph: refactor compute_topological_levels()

This patch extracts the common code used to compute topological levels and corrected committer dates into a common routine, compute_reachable_generation_numbers(). For ease of reading, it only modifies compute_topological_levels() to use this new routine, leaving compute_generation_numbers() to be modified in the next change. This new routine dispatches to call the necessary functions to get and set the generation number for a given commit through a vtable (the compute_generation_info struct). Computing the generation number itself is done in compute_generation_from_max(), which dispatches its implementation based on the generation version requested, or issuing a BUG() for unrecognized generation versions. This does not use a vtable because the logic depends only on the generation number version, not where the data is being loaded from or being stored to. This is a subtle point that will make more sense in a future change that modifies the in-memory generation values instead of just preparing values for writing to a commit-graph file. This change looks like it adds a lot of new code. However, two upcoming changes will be quite small due to the work being done in this change. Co-authored-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Derrick Stolee <derrickstolee@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Mar 20, 2023 at 11:26 UTC 368d19b0b7fa780d84918cf4ed4a31a410ed865d
1 file changed +83 -23
commit-graph.c
+83 -23
@@ -1446,24 +1446,52 @@ static void close_reachable(struct write_commit_graph_context *ctx)
1446 stop_progress(&ctx->progress);
1447 }
1448
1449 -static void compute_topological_levels(struct write_commit_graph_context *ctx)
1449 +struct compute_generation_info {
1450 + struct repository *r;
1451 + struct packed_commit_list *commits;
1452 + struct progress *progress;
1453 + int progress_cnt;
1454 +
1455 + timestamp_t (*get_generation)(struct commit *c, void *data);
1456 + void (*set_generation)(struct commit *c, timestamp_t gen, void *data);
1457 + void *data;
1458 +};
1459 +
1460 +static timestamp_t compute_generation_from_max(struct commit *c,
1461 + timestamp_t max_gen,
1462 + int generation_version)
1463 +{
1464 + switch (generation_version) {
1465 + case 1: /* topological levels */
1466 + if (max_gen > GENERATION_NUMBER_V1_MAX - 1)
1467 + max_gen = GENERATION_NUMBER_V1_MAX - 1;
1468 + return max_gen + 1;
1469 +
1470 + case 2: /* corrected commit date */
1471 + if (c->date && c->date > max_gen)
1472 + max_gen = c->date - 1;
1473 + return max_gen + 1;
1474 +
1475 + default:
1476 + BUG("attempting unimplemented version");
1477 + }
1478 +}
1479 +
1480 +static void compute_reachable_generation_numbers(
1481 + struct compute_generation_info *info,
1482 + int generation_version)
1483 {
1484 int i;
1485 struct commit_list *list = NULL;
1486
1454 - if (ctx->report_progress)
1455 - ctx->progress = start_delayed_progress(
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 -
1462 - repo_parse_commit(ctx->r, c);
1463 - level = *topo_level_slab_at(ctx->topo_levels, c);
1487 + for (i = 0; i < info->commits->nr; i++) {
1488 + struct commit *c = info->commits->list[i];
1489 + timestamp_t gen;
1490 + repo_parse_commit(info->r, c);
1491 + gen = info->get_generation(c, info->data);
1492 + display_progress(info->progress, info->progress_cnt + 1);
1493
1465 - display_progress(ctx->progress, i + 1);
1466 - if (level != GENERATION_NUMBER_ZERO)
1494 + if (gen != GENERATION_NUMBER_ZERO && gen != GENERATION_NUMBER_INFINITY)
1495 continue;
1496
1497 commit_list_insert(c, &list);
@@ -1471,31 +1499,63 @@ static void compute_topological_levels(struct write_commit_graph_context *ctx)
1499 struct commit *current = list->item;
1500 struct commit_list *parent;
1501 int all_parents_computed = 1;
1474 - uint32_t max_level = 0;
1502 + uint32_t max_gen = 0;
1503
1504 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);
1505 + repo_parse_commit(info->r, parent->item);
1506 + gen = info->get_generation(parent->item, info->data);
1507
1480 - if (level == GENERATION_NUMBER_ZERO) {
1508 + if (gen == GENERATION_NUMBER_ZERO) {
1509 all_parents_computed = 0;
1510 commit_list_insert(parent->item, &list);
1511 break;
1512 }
1513
1486 - if (level > max_level)
1487 - max_level = level;
1514 + if (gen > max_gen)
1515 + max_gen = gen;
1516 }
1517
1518 if (all_parents_computed) {
1519 pop_commit(&list);
1492 -
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;
1520 + gen = compute_generation_from_max(
1521 + current, max_gen,
1522 + generation_version);
1523 + info->set_generation(current, gen, info->data);
1524 }
1525 }
1526 }
1527 +}
1528 +
1529 +static timestamp_t get_topo_level(struct commit *c, void *data)
1530 +{
1531 + struct write_commit_graph_context *ctx = data;
1532 + return *topo_level_slab_at(ctx->topo_levels, c);
1533 +}
1534 +
1535 +static void set_topo_level(struct commit *c, timestamp_t t, void *data)
1536 +{
1537 + struct write_commit_graph_context *ctx = data;
1538 + *topo_level_slab_at(ctx->topo_levels, c) = (uint32_t)t;
1539 +}
1540 +
1541 +static void compute_topological_levels(struct write_commit_graph_context *ctx)
1542 +{
1543 + struct compute_generation_info info = {
1544 + .r = ctx->r,
1545 + .commits = &ctx->commits,
1546 + .get_generation = get_topo_level,
1547 + .set_generation = set_topo_level,
1548 + .data = ctx,
1549 + };
1550 +
1551 + if (ctx->report_progress)
1552 + info.progress = ctx->progress
1553 + = start_delayed_progress(
1554 + _("Computing commit graph topological levels"),
1555 + ctx->commits.nr);
1556 +
1557 + compute_reachable_generation_numbers(&info, 1);
1558 +
1559 stop_progress(&ctx->progress);
1560 }
1561