Skip to content

Commit 091fc89

Browse files
pks-tgitster
authored andcommitted
builtin/maintenance: introduce "rerere-gc" task
While git-gc(1) knows to garbage collect the rerere cache, git-maintenance(1) does not yet have a task for this cleanup. Introduce a new "rerere-gc" task to plug this gap. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f7bc30f commit 091fc89

File tree

4 files changed

+107
-0
lines changed

4 files changed

+107
-0
lines changed

Documentation/config/maintenance.adoc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,14 @@ maintenance.reflog-expire.auto::
8484
expired reflog entries in the "HEAD" reflog is at least the value of
8585
`maintenance.loose-objects.auto`. The default value is 100.
8686

87+
maintenance.rerere-gc.auto::
88+
This integer config option controls how often the `rerere-gc` task
89+
should be run as part of `git maintenance run --auto`. If zero, then
90+
the `rerere-gc` task will not run with the `--auto` option. A negative
91+
value will force the task to run every time. Otherwise, a positive
92+
value implies the command should run when the number of prunable rerere
93+
entries exceeds the value. The default value is 20.
94+
8795
maintenance.worktree-prune.auto::
8896
This integer config option controls how often the `worktree-prune` task
8997
should be run as part of `git maintenance run --auto`. If zero, then

Documentation/git-maintenance.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ reflog-expire::
166166
The `reflog-expire` task deletes any entries in the reflog older than the
167167
expiry threshold. See linkgit:git-reflog[1] for more information.
168168

169+
rerere-gc::
170+
The `rerere-gc` task invokes garbage collection for stale entries in
171+
the rerere cache. See linkgit:git-rerere[1] for more information.
172+
169173
worktree-prune::
170174
The `worktree-prune` task deletes stale or broken worktrees. See
171175
linkit:git-worktree[1] for more information.

builtin/gc.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "builtin.h"
1717
#include "abspath.h"
1818
#include "date.h"
19+
#include "dir.h"
1920
#include "environment.h"
2021
#include "hex.h"
2122
#include "config.h"
@@ -33,6 +34,7 @@
3334
#include "pack-objects.h"
3435
#include "path.h"
3536
#include "reflog.h"
37+
#include "rerere.h"
3638
#include "blob.h"
3739
#include "tree.h"
3840
#include "promisor-remote.h"
@@ -394,6 +396,39 @@ static int maintenance_task_rerere_gc(struct maintenance_run_opts *opts UNUSED,
394396
return run_command(&rerere_cmd);
395397
}
396398

399+
static int rerere_gc_condition(struct gc_config *cfg UNUSED)
400+
{
401+
struct strbuf path = STRBUF_INIT;
402+
struct string_list prunable_dirs = STRING_LIST_INIT_DUP;
403+
struct rerere_id *prunable_entries = NULL;
404+
size_t prunable_entries_nr;
405+
int should_gc = 0;
406+
int limit = 20;
407+
408+
git_config_get_int("maintenance.rerere-gc.auto", &limit);
409+
if (limit <= 0) {
410+
should_gc = limit < 0;
411+
goto out;
412+
}
413+
414+
/* Skip garbage collecting the rerere cache in case rerere is disabled. */
415+
repo_git_path_replace(the_repository, &path, "rr-cache");
416+
if (!is_directory(path.buf))
417+
goto out;
418+
419+
if (rerere_collect_stale_entries(the_repository, &prunable_dirs,
420+
&prunable_entries, &prunable_entries_nr) < 0)
421+
goto out;
422+
423+
should_gc = prunable_entries_nr >= limit;
424+
425+
out:
426+
string_list_clear(&prunable_dirs, 0);
427+
free(prunable_entries);
428+
strbuf_release(&path);
429+
return should_gc;
430+
}
431+
397432
static int too_many_loose_objects(struct gc_config *cfg)
398433
{
399434
/*
@@ -1512,6 +1547,7 @@ enum maintenance_task_label {
15121547
TASK_PACK_REFS,
15131548
TASK_REFLOG_EXPIRE,
15141549
TASK_WORKTREE_PRUNE,
1550+
TASK_RERERE_GC,
15151551

15161552
/* Leave as final value */
15171553
TASK__COUNT
@@ -1558,6 +1594,11 @@ static struct maintenance_task tasks[] = {
15581594
maintenance_task_worktree_prune,
15591595
worktree_prune_condition,
15601596
},
1597+
[TASK_RERERE_GC] = {
1598+
"rerere-gc",
1599+
maintenance_task_rerere_gc,
1600+
rerere_gc_condition,
1601+
},
15611602
};
15621603

15631604
static int compare_tasks_by_selection(const void *a_, const void *b_)

t/t7900-maintenance.sh

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,60 @@ test_expect_success 'worktree-prune task honors gc.worktreePruneExpire' '
564564
test_path_is_missing .git/worktrees/worktree
565565
'
566566

567+
setup_stale_rerere_entry () {
568+
rr=.git/rr-cache/"$(printf "%0$(test_oid hexsz)d" "$1")" &&
569+
mkdir -p "$rr" &&
570+
>"$rr/preimage" &&
571+
>"$rr/postimage" &&
572+
573+
test-tool chmtime ="$((-61 * 86400))" "$rr/preimage" &&
574+
test-tool chmtime ="$((-61 * 86400))" "$rr/postimage"
575+
}
576+
577+
test_expect_rerere_gc () {
578+
negate=
579+
if test "$1" = "!"
580+
then
581+
negate="!"
582+
shift
583+
fi
584+
585+
rm -f "rerere-gc.txt" &&
586+
GIT_TRACE2_EVENT="$(pwd)/rerere-gc.txt" "$@" &&
587+
test_subcommand $negate git rerere gc <rerere-gc.txt
588+
}
589+
590+
test_expect_success 'rerere-gc task without --auto always collects garbage' '
591+
test_expect_rerere_gc git maintenance run --task=rerere-gc
592+
'
593+
594+
test_expect_success 'rerere-gc task with --auto only prunes with prunable entries' '
595+
test_expect_rerere_gc ! git maintenance run --auto --task=rerere-gc &&
596+
for i in $(test_seq 19)
597+
do
598+
setup_stale_rerere_entry $i || return 1
599+
done &&
600+
test_expect_rerere_gc ! git maintenance run --auto --task=rerere-gc &&
601+
setup_stale_rerere_entry 20 &&
602+
test_expect_rerere_gc git maintenance run --auto --task=rerere-gc
603+
'
604+
605+
test_expect_success 'rerere-gc task with --auto honors maintenance.rerere-gc.auto' '
606+
# A negative value should always prune.
607+
test_expect_rerere_gc git -c maintenance.rerere-gc.auto=-1 maintenance run --auto --task=rerere-gc &&
608+
609+
for i in $(test_seq 20)
610+
do
611+
setup_stale_rerere_entry $i || return 1
612+
done &&
613+
614+
# Zero should never prune.
615+
test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=0 maintenance run --auto --task=rerere-gc &&
616+
# A positive value should require at least this many stale rerere entries.
617+
test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=21 maintenance run --auto --task=rerere-gc &&
618+
test_expect_rerere_gc git -c maintenance.rerere-gc.auto=10 maintenance run --auto --task=rerere-gc
619+
'
620+
567621
test_expect_success '--auto and --schedule incompatible' '
568622
test_must_fail git maintenance run --auto --schedule=daily 2>err &&
569623
test_grep "at most one" err

0 commit comments

Comments
 (0)