Skip to content

Commit 0e994d9

Browse files
pks-tgitster
authored andcommitted
builtin/maintenance: extend "maintenance.strategy" to manual maintenance
The "maintenance.strategy" configuration allows users to configure how Git is supposed to perform repository maintenance. The idea is that we provide a set of high-level strategies that may be useful in different contexts, like for example when handling a large monorepo. Furthermore, the strategy can be tweaked by the user by overriding specific tasks. In its current form though, the strategy only applies to scheduled maintenance. This creates something of a gap, as scheduled and manual maintenance will now use _different_ strategies as the latter would continue to use git-gc(1) by default. This makes the strategies way less useful than they could be on the one hand. But even more importantly, the two different strategies might clash with one another, where one of the strategies performs maintenance in such a way that it discards benefits from the other strategy. So ideally, it should be possible to pick one strategy that then applies globally to all the different ways that we perform maintenance. This doesn't necessarily mean that the strategy always does the _same_ thing for every maintenance type. But it means that the strategy can configure the different types to work in tandem with each other. Change the meaning of "maintenance.strategy" accordingly so that the strategy is applied to both types, manual and scheduled. As preceding commits have introduced logic to run maintenance tasks depending on this type we can tweak strategies so that they perform those tasks depending on the context. Note that this raises the question of backwards compatibility: when the user has configured the "incremental" strategy we would have ignored that strategy beforehand. Instead, repository maintenance would have continued to use git-gc(1) by default. But luckily, we can match that behaviour by: - Keeping all current tasks of the incremental strategy as `MAINTENANCE_TYPE_SCHEDULED`. This ensures that those tasks will not run during manual maintenance. - Configuring the "gc" task so that it is invoked during manual maintenance. Like this, the user shouldn't observe any difference in behaviour. Signed-off-by: Patrick Steinhardt <[email protected]> Acked-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6a7d3ee commit 0e994d9

File tree

3 files changed

+74
-13
lines changed

3 files changed

+74
-13
lines changed

Documentation/config/maintenance.adoc

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,25 @@ detach.
1616

1717
maintenance.strategy::
1818
This string config option provides a way to specify one of a few
19-
recommended schedules for background maintenance. This only affects
20-
which tasks are run during `git maintenance run --schedule=X`
21-
commands, provided no `--task=<task>` arguments are provided.
22-
Further, if a `maintenance.<task>.schedule` config value is set,
23-
then that value is used instead of the one provided by
24-
`maintenance.strategy`. The possible strategy strings are:
19+
recommended strategies for repository maintenance. This affects
20+
which tasks are run during `git maintenance run`, provided no
21+
`--task=<task>` arguments are provided. This setting impacts manual
22+
maintenance, auto-maintenance as well as scheduled maintenance. The
23+
tasks that run may be different depending on the maintenance type.
2524
+
26-
* `none`: This default setting implies no tasks are run at any schedule.
25+
The maintenance strategy can be further tweaked by setting
26+
`maintenance.<task>.enabled` and `maintenance.<task>.schedule`. If set, these
27+
values are used instead of the defaults provided by `maintenance.strategy`.
28+
+
29+
The possible strategies are:
30+
+
31+
* `none`: This strategy implies no tasks are run at all. This is the default
32+
strategy for scheduled maintenance.
2733
* `incremental`: This setting optimizes for performing small maintenance
2834
activities that do not delete any data. This does not schedule the `gc`
2935
task, but runs the `prefetch` and `commit-graph` tasks hourly, the
3036
`loose-objects` and `incremental-repack` tasks daily, and the `pack-refs`
31-
task weekly.
37+
task weekly. Manual repository maintenance uses the `gc` task.
3238

3339
maintenance.<task>.enabled::
3440
This boolean config option controls whether the maintenance task

builtin/gc.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1873,6 +1873,20 @@ static const struct maintenance_strategy incremental_strategy = {
18731873
.type = MAINTENANCE_TYPE_SCHEDULED,
18741874
.schedule = SCHEDULE_WEEKLY,
18751875
},
1876+
/*
1877+
* Historically, the "incremental" strategy was only available
1878+
* in the context of scheduled maintenance when set up via
1879+
* "maintenance.strategy". We have later expanded that config
1880+
* to also cover manual maintenance.
1881+
*
1882+
* To retain backwards compatibility with the previous status
1883+
* quo we thus run git-gc(1) in case manual maintenance was
1884+
* requested. This is the same as the default strategy, which
1885+
* would have been in use beforehand.
1886+
*/
1887+
[TASK_GC] = {
1888+
.type = MAINTENANCE_TYPE_MANUAL,
1889+
},
18761890
},
18771891
};
18781892

@@ -1916,19 +1930,20 @@ static void initialize_task_config(struct maintenance_run_opts *opts,
19161930
* - Unscheduled maintenance uses our default strategy.
19171931
*
19181932
* Both of these are affected by the gitconfig though, which may
1919-
* override specific aspects of our strategy.
1933+
* override specific aspects of our strategy. Furthermore, both
1934+
* strategies can be overridden by setting "maintenance.strategy".
19201935
*/
19211936
if (opts->schedule) {
1922-
if (!repo_config_get_string_tmp(the_repository, "maintenance.strategy", &config_str))
1923-
strategy = parse_maintenance_strategy(config_str);
1924-
else
1925-
strategy = none_strategy;
1937+
strategy = none_strategy;
19261938
type = MAINTENANCE_TYPE_SCHEDULED;
19271939
} else {
19281940
strategy = default_strategy;
19291941
type = MAINTENANCE_TYPE_MANUAL;
19301942
}
19311943

1944+
if (!repo_config_get_string_tmp(the_repository, "maintenance.strategy", &config_str))
1945+
strategy = parse_maintenance_strategy(config_str);
1946+
19321947
for (size_t i = 0; i < TASK__COUNT; i++) {
19331948
int config_value;
19341949

t/t7900-maintenance.sh

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,46 @@ test_expect_success 'maintenance.strategy inheritance' '
886886
<modified-daily.txt
887887
'
888888

889+
test_strategy () {
890+
STRATEGY="$1"
891+
shift
892+
893+
cat >expect &&
894+
rm -f trace2.txt &&
895+
GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
896+
git -c maintenance.strategy=$STRATEGY maintenance run --quiet "$@" &&
897+
sed -n 's/{"event":"child_start","sid":"[^/"]*",.*,"argv":\["\(.*\)\"]}/\1/p' <trace2.txt |
898+
sed 's/","/ /g' >actual
899+
test_cmp expect actual
900+
}
901+
902+
test_expect_success 'maintenance.strategy is respected' '
903+
test_when_finished "rm -rf repo" &&
904+
git init repo &&
905+
(
906+
cd repo &&
907+
test_commit initial &&
908+
909+
test_must_fail git -c maintenance.strategy=unknown maintenance run 2>err &&
910+
test_grep "unknown maintenance strategy: .unknown." err &&
911+
912+
test_strategy incremental <<-\EOF &&
913+
git pack-refs --all --prune
914+
git reflog expire --all
915+
git gc --quiet --no-detach --skip-foreground-tasks
916+
EOF
917+
918+
test_strategy incremental --schedule=weekly <<-\EOF
919+
git pack-refs --all --prune
920+
git prune-packed --quiet
921+
git multi-pack-index write --no-progress
922+
git multi-pack-index expire --no-progress
923+
git multi-pack-index repack --no-progress --batch-size=1
924+
git commit-graph write --split --reachable --no-progress
925+
EOF
926+
)
927+
'
928+
889929
test_expect_success 'register and unregister' '
890930
test_when_finished git config --global --unset-all maintenance.repo &&
891931

0 commit comments

Comments
 (0)