@matheusbsbs / matheus-bagliano / commits / fdbde82fe5
Fork 0

builtin/commit-graph.c: introduce split strategy 'no-merge'

In the previous commit, we laid the groundwork for supporting different splitting strategies. In this commit, we introduce the first splitting strategy: 'no-merge'. Passing '--split=no-merge' is useful for callers which wish to write a new incremental commit-graph, but do not want to spend effort condensing the incremental chain [1]. Previously, this was possible by passing '--size-multiple=0', but this no longer the case following 63020f175f (commit-graph: prefer default size_mult when given zero, 2020-01-02). When '--split=no-merge' is given, the commit-graph machinery will never condense an existing chain, and it will always write a new incremental. [1]: This might occur when, for example, a server administrator running some program after each push may want to ensure that each job runs proportional in time to the size of the push, and does not "jump" when the commit-graph machinery decides to trigger a merge. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Taylor Blau committed Apr 13, 2020 at 22:04 UTC fdbde82fe523374b3c5d1f0f01f3c43dcaca9465
5 files changed +36 -9
Documentation/git-commit-graph.txt
+5
@@ -63,6 +63,11 @@ chain of multiple commit-graph files stored in
63 strategy and other splitting options. The new commits not already in the
64 commit-graph are added in a new "tip" file. This file is merged with the
65 existing file if the following merge conditions are met:
66 +* If `--split=no-merge` is specified, a merge is never performed, and
67 +the remaining options are ignored. A bare `--split` defers to the
68 +remaining options. (Note that merging a chain of commit graphs replaces
69 +the existing chain with a length-1 chain where the first and only
70 +incremental holds the entire graph).
71 +
72 * If `--size-multiple=<X>` is not specified, let `X` equal 2. If the new
73 tip file would have `N` commits and the previous tip has `M` commits and
builtin/commit-graph.c
+6 -1
@@ -118,11 +118,16 @@ static struct split_commit_graph_opts split_opts;
118 static int write_option_parse_split(const struct option *opt, const char *arg,
119 int unset)
120 {
121 + enum commit_graph_split_flags *flags = opt->value;
122 +
123 opts.split = 1;
124 if (!arg)
125 return 0;
126
125 - die(_("unrecognized --split argument, %s"), arg);
127 + if (!strcmp(arg, "no-merge"))
128 + *flags = COMMIT_GRAPH_SPLIT_MERGE_PROHIBITED;
129 + else
130 + die(_("unrecognized --split argument, %s"), arg);
131
132 return 0;
133 }
commit-graph.c
+12 -7
@@ -1529,6 +1529,7 @@ static void split_graph_merge_strategy(struct write_commit_graph_context *ctx)
1529 {
1530 struct commit_graph *g;
1531 uint32_t num_commits;
1532 + enum commit_graph_split_flags flags = COMMIT_GRAPH_SPLIT_UNSPECIFIED;
1533 uint32_t i;
1534
1535 int max_commits = 0;
@@ -1539,21 +1540,25 @@ static void split_graph_merge_strategy(struct write_commit_graph_context *ctx)
1540
1541 if (ctx->split_opts->size_multiple)
1542 size_mult = ctx->split_opts->size_multiple;
1543 +
1544 + flags = ctx->split_opts->flags;
1545 }
1546
1547 g = ctx->r->objects->commit_graph;
1548 num_commits = ctx->commits.nr;
1549 ctx->num_commit_graphs_after = ctx->num_commit_graphs_before + 1;
1550
1548 - while (g && (g->num_commits <= size_mult * num_commits ||
1549 - (max_commits && num_commits > max_commits))) {
1550 - if (g->odb != ctx->odb)
1551 - break;
1551 + if (flags != COMMIT_GRAPH_SPLIT_MERGE_PROHIBITED) {
1552 + while (g && (g->num_commits <= size_mult * num_commits ||
1553 + (max_commits && num_commits > max_commits))) {
1554 + if (g->odb != ctx->odb)
1555 + break;
1556
1553 - num_commits += g->num_commits;
1554 - g = g->base_graph;
1557 + num_commits += g->num_commits;
1558 + g = g->base_graph;
1559
1556 - ctx->num_commit_graphs_after--;
1560 + ctx->num_commit_graphs_after--;
1561 + }
1562 }
1563
1564 ctx->new_base_graph = g;
commit-graph.h
+2 -1
@@ -83,7 +83,8 @@ enum commit_graph_write_flags {
83 };
84
85 enum commit_graph_split_flags {
86 - COMMIT_GRAPH_SPLIT_UNSPECIFIED = 0
86 + COMMIT_GRAPH_SPLIT_UNSPECIFIED = 0,
87 + COMMIT_GRAPH_SPLIT_MERGE_PROHIBITED = 1
88 };
89
90 struct split_commit_graph_opts {
t/t5324-split-commit-graph.sh
+11
@@ -344,4 +344,15 @@ test_expect_success 'split across alternate where alternate is not split' '
344 test_cmp commit-graph .git/objects/info/commit-graph
345 '
346
347 +test_expect_success '--split=no-merge always writes an incremental' '
348 + test_when_finished rm -rf a b &&
349 + rm -rf $graphdir $infodir/commit-graph &&
350 + git reset --hard commits/2 &&
351 + git rev-list HEAD~1 >a &&
352 + git rev-list HEAD >b &&
353 + git commit-graph write --split --stdin-commits <a &&
354 + git commit-graph write --split=no-merge --stdin-commits <b &&
355 + test_line_count = 2 $graphdir/commit-graph-chain
356 +'
357 +
358 test_done