Skip to content

Commit 98077d0

Browse files
pks-tgitster
authored andcommitted
run-command: fix detaching when running auto maintenance
In the past, we used to execute `git gc --auto` as part of our automatic housekeeping routines. As git-gc(1) may require quite some time to perform the housekeeping, it knows to detach itself and run in the background so that the user can continue their work. Eventually, we refactored our automatic housekeeping to instead use the more flexible git-maintenance(1) command. The upside of this new infra is that the user can configure which maintenance tasks are performed, at least to a certain degree. So while it continues to run git-gc(1) by default, it can also be adapted to e.g. use git-multi-pack-index(1) for maintenance of the object database. The auto-detach of the new infra is somewhat broken though once the user configures non-standard tasks. The problem is essentially that we detach at the wrong level in the process hierarchy: git-maintenance(1) never detaches itself, but instead it continues to be git-gc(1) which does. When configured to only run the git-gc(1) maintenance task, then the result is basically the same as before. But when configured to run other tasks, then git-maintenance(1) will wait for these to run to completion. Even worse, it may be that git-gc(1) runs concurrently with other housekeeping tasks, stomping on each others feet. Fix this bug by asking git-gc(1) to not detach when it is being invoked via git-maintenance(1). Instead, git-maintenance(1) now respects a new config "maintenance.autoDetach", the equivalent of "gc.autoDetach", and detaches itself into the background when running as part of our auto maintenance. This should continue to behave the same for all users which use the git-gc(1) task, only. For others though, it means that we now properly perform all tasks in the background. The default behaviour of git-maintenance(1) when executed by the user does not change, it will remain in the foreground unless they pass the `--detach` option. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent a6affd3 commit 98077d0

File tree

6 files changed

+62
-14
lines changed

6 files changed

+62
-14
lines changed

Documentation/config/gc.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ use, it'll affect how the auto pack limit works.
4040

4141
gc.autoDetach::
4242
Make `git gc --auto` return immediately and run in the background
43-
if the system supports it. Default is true.
43+
if the system supports it. Default is true. This config variable acts
44+
as a fallback in case `maintenance.autoDetach` is not set.
4445

4546
gc.bigPackThreshold::
4647
If non-zero, all non-cruft packs larger than this limit are kept

Documentation/config/maintenance.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@ maintenance.auto::
33
`git maintenance run --auto` after doing their normal work. Defaults
44
to true.
55

6+
maintenance.autoDetach::
7+
Many Git commands trigger automatic maintenance after they have
8+
written data into the repository. This boolean config option
9+
controls whether this automatic maintenance shall happen in the
10+
foreground or whether the maintenance process shall detach and
11+
continue to run in the background.
12+
+
13+
If unset, the value of `gc.autoDetach` is used as a fallback. Defaults
14+
to true if both are unset, meaning that the maintenance process will
15+
detach.
16+
617
maintenance.strategy::
718
This string config option provides a way to specify one of a few
819
recommended schedules for background maintenance. This only affects

builtin/gc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,7 @@ static int maintenance_task_gc(struct maintenance_run_opts *opts,
10631063
strvec_push(&child.args, "--quiet");
10641064
else
10651065
strvec_push(&child.args, "--no-quiet");
1066+
strvec_push(&child.args, "--no-detach");
10661067

10671068
return run_command(&child);
10681069
}

run-command.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1808,16 +1808,26 @@ void run_processes_parallel(const struct run_process_parallel_opts *opts)
18081808

18091809
int prepare_auto_maintenance(int quiet, struct child_process *maint)
18101810
{
1811-
int enabled;
1811+
int enabled, auto_detach;
18121812

18131813
if (!git_config_get_bool("maintenance.auto", &enabled) &&
18141814
!enabled)
18151815
return 0;
18161816

1817+
/*
1818+
* When `maintenance.autoDetach` isn't set, then we fall back to
1819+
* honoring `gc.autoDetach`. This is somewhat weird, but required to
1820+
* retain behaviour from when we used to run git-gc(1) here.
1821+
*/
1822+
if (git_config_get_bool("maintenance.autodetach", &auto_detach) &&
1823+
git_config_get_bool("gc.autodetach", &auto_detach))
1824+
auto_detach = 1;
1825+
18171826
maint->git_cmd = 1;
18181827
maint->close_object_store = 1;
18191828
strvec_pushl(&maint->args, "maintenance", "run", "--auto", NULL);
18201829
strvec_push(&maint->args, quiet ? "--quiet" : "--no-quiet");
1830+
strvec_push(&maint->args, auto_detach ? "--detach" : "--no-detach");
18211831

18221832
return 1;
18231833
}

t/t5616-partial-clone.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ test_expect_success 'fetch --refetch triggers repacking' '
229229
230230
GIT_TRACE2_EVENT="$PWD/trace1.event" \
231231
git -C pc1 fetch --refetch origin &&
232-
test_subcommand git maintenance run --auto --no-quiet <trace1.event &&
232+
test_subcommand git maintenance run --auto --no-quiet --detach <trace1.event &&
233233
grep \"param\":\"gc.autopacklimit\",\"value\":\"1\" trace1.event &&
234234
grep \"param\":\"maintenance.incremental-repack.auto\",\"value\":\"-1\" trace1.event &&
235235
@@ -238,7 +238,7 @@ test_expect_success 'fetch --refetch triggers repacking' '
238238
-c gc.autoPackLimit=0 \
239239
-c maintenance.incremental-repack.auto=1234 \
240240
-C pc1 fetch --refetch origin &&
241-
test_subcommand git maintenance run --auto --no-quiet <trace2.event &&
241+
test_subcommand git maintenance run --auto --no-quiet --detach <trace2.event &&
242242
grep \"param\":\"gc.autopacklimit\",\"value\":\"0\" trace2.event &&
243243
grep \"param\":\"maintenance.incremental-repack.auto\",\"value\":\"-1\" trace2.event &&
244244
@@ -247,7 +247,7 @@ test_expect_success 'fetch --refetch triggers repacking' '
247247
-c gc.autoPackLimit=1234 \
248248
-c maintenance.incremental-repack.auto=0 \
249249
-C pc1 fetch --refetch origin &&
250-
test_subcommand git maintenance run --auto --no-quiet <trace3.event &&
250+
test_subcommand git maintenance run --auto --no-quiet --detach <trace3.event &&
251251
grep \"param\":\"gc.autopacklimit\",\"value\":\"1\" trace3.event &&
252252
grep \"param\":\"maintenance.incremental-repack.auto\",\"value\":\"0\" trace3.event
253253
'

t/t7900-maintenance.sh

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,47 @@ test_expect_success 'run [--auto|--quiet]' '
4949
git maintenance run --auto 2>/dev/null &&
5050
GIT_TRACE2_EVENT="$(pwd)/run-no-quiet.txt" \
5151
git maintenance run --no-quiet 2>/dev/null &&
52-
test_subcommand git gc --quiet <run-no-auto.txt &&
53-
test_subcommand ! git gc --auto --quiet <run-auto.txt &&
54-
test_subcommand git gc --no-quiet <run-no-quiet.txt
52+
test_subcommand git gc --quiet --no-detach <run-no-auto.txt &&
53+
test_subcommand ! git gc --auto --quiet --no-detach <run-auto.txt &&
54+
test_subcommand git gc --no-quiet --no-detach <run-no-quiet.txt
5555
'
5656

5757
test_expect_success 'maintenance.auto config option' '
5858
GIT_TRACE2_EVENT="$(pwd)/default" git commit --quiet --allow-empty -m 1 &&
59-
test_subcommand git maintenance run --auto --quiet <default &&
59+
test_subcommand git maintenance run --auto --quiet --detach <default &&
6060
GIT_TRACE2_EVENT="$(pwd)/true" \
6161
git -c maintenance.auto=true \
6262
commit --quiet --allow-empty -m 2 &&
63-
test_subcommand git maintenance run --auto --quiet <true &&
63+
test_subcommand git maintenance run --auto --quiet --detach <true &&
6464
GIT_TRACE2_EVENT="$(pwd)/false" \
6565
git -c maintenance.auto=false \
6666
commit --quiet --allow-empty -m 3 &&
67-
test_subcommand ! git maintenance run --auto --quiet <false
67+
test_subcommand ! git maintenance run --auto --quiet --detach <false
68+
'
69+
70+
for cfg in maintenance.autoDetach gc.autoDetach
71+
do
72+
test_expect_success "$cfg=true config option" '
73+
test_when_finished "rm -f trace" &&
74+
test_config $cfg true &&
75+
GIT_TRACE2_EVENT="$(pwd)/trace" git commit --quiet --allow-empty -m 1 &&
76+
test_subcommand git maintenance run --auto --quiet --detach <trace
77+
'
78+
79+
test_expect_success "$cfg=false config option" '
80+
test_when_finished "rm -f trace" &&
81+
test_config $cfg false &&
82+
GIT_TRACE2_EVENT="$(pwd)/trace" git commit --quiet --allow-empty -m 1 &&
83+
test_subcommand git maintenance run --auto --quiet --no-detach <trace
84+
'
85+
done
86+
87+
test_expect_success "maintenance.autoDetach overrides gc.autoDetach" '
88+
test_when_finished "rm -f trace" &&
89+
test_config maintenance.autoDetach false &&
90+
test_config gc.autoDetach true &&
91+
GIT_TRACE2_EVENT="$(pwd)/trace" git commit --quiet --allow-empty -m 1 &&
92+
test_subcommand git maintenance run --auto --quiet --no-detach <trace
6893
'
6994

7095
test_expect_success 'register uses XDG_CONFIG_HOME config if it exists' '
@@ -129,9 +154,9 @@ test_expect_success 'run --task=<task>' '
129154
git maintenance run --task=commit-graph 2>/dev/null &&
130155
GIT_TRACE2_EVENT="$(pwd)/run-both.txt" \
131156
git maintenance run --task=commit-graph --task=gc 2>/dev/null &&
132-
test_subcommand ! git gc --quiet <run-commit-graph.txt &&
133-
test_subcommand git gc --quiet <run-gc.txt &&
134-
test_subcommand git gc --quiet <run-both.txt &&
157+
test_subcommand ! git gc --quiet --no-detach <run-commit-graph.txt &&
158+
test_subcommand git gc --quiet --no-detach <run-gc.txt &&
159+
test_subcommand git gc --quiet --no-detach <run-both.txt &&
135160
test_subcommand git commit-graph write --split --reachable --no-progress <run-commit-graph.txt &&
136161
test_subcommand ! git commit-graph write --split --reachable --no-progress <run-gc.txt &&
137162
test_subcommand git commit-graph write --split --reachable --no-progress <run-both.txt

0 commit comments

Comments
 (0)