Skip to content

Commit 283621a

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 255251c commit 283621a

File tree

4 files changed

+94
-0
lines changed

4 files changed

+94
-0
lines changed

Documentation/config/maintenance.adoc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@ 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, any positive
92+
value implies the command will run when the "rr-cache" directory exists
93+
and has at least one entry, regardless of whether it is stale or not.
94+
This heuristic may be refined in the future. The default value is 1.
95+
8796
maintenance.worktree-prune.auto::
8897
This integer config option controls how often the `worktree-prune` task
8998
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: 37 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"
@@ -393,6 +395,35 @@ static int maintenance_task_rerere_gc(struct maintenance_run_opts *opts UNUSED,
393395
return run_command(&rerere_cmd);
394396
}
395397

398+
static int rerere_gc_condition(struct gc_config *cfg UNUSED)
399+
{
400+
struct strbuf path = STRBUF_INIT;
401+
int should_gc = 0, limit = 1;
402+
DIR *dir = NULL;
403+
404+
git_config_get_int("maintenance.rerere-gc.auto", &limit);
405+
if (limit <= 0) {
406+
should_gc = limit < 0;
407+
goto out;
408+
}
409+
410+
/*
411+
* We skip garbage collection in case we either have no "rr-cache"
412+
* directory or when it doesn't contain at least one entry.
413+
*/
414+
repo_git_path_replace(the_repository, &path, "rr-cache");
415+
dir = opendir(path.buf);
416+
if (!dir)
417+
goto out;
418+
should_gc = !!readdir_skip_dot_and_dotdot(dir);
419+
420+
out:
421+
strbuf_release(&path);
422+
if (dir)
423+
closedir(dir);
424+
return should_gc;
425+
}
426+
396427
static int too_many_loose_objects(struct gc_config *cfg)
397428
{
398429
/*
@@ -1511,6 +1542,7 @@ enum maintenance_task_label {
15111542
TASK_PACK_REFS,
15121543
TASK_REFLOG_EXPIRE,
15131544
TASK_WORKTREE_PRUNE,
1545+
TASK_RERERE_GC,
15141546

15151547
/* Leave as final value */
15161548
TASK__COUNT
@@ -1557,6 +1589,11 @@ static struct maintenance_task tasks[] = {
15571589
maintenance_task_worktree_prune,
15581590
worktree_prune_condition,
15591591
},
1592+
[TASK_RERERE_GC] = {
1593+
"rerere-gc",
1594+
maintenance_task_rerere_gc,
1595+
rerere_gc_condition,
1596+
},
15601597
};
15611598

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

t/t7900-maintenance.sh

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

567+
test_expect_rerere_gc () {
568+
negate=
569+
if test "$1" = "!"
570+
then
571+
negate="!"
572+
shift
573+
fi
574+
575+
rm -f "rerere-gc.txt" &&
576+
GIT_TRACE2_EVENT="$(pwd)/rerere-gc.txt" "$@" &&
577+
test_subcommand $negate git rerere gc <rerere-gc.txt
578+
}
579+
580+
test_expect_success 'rerere-gc task without --auto always collects garbage' '
581+
test_expect_rerere_gc git maintenance run --task=rerere-gc
582+
'
583+
584+
test_expect_success 'rerere-gc task with --auto only prunes with prunable entries' '
585+
test_when_finished "rm -rf .git/rr-cache" &&
586+
test_expect_rerere_gc ! git maintenance run --auto --task=rerere-gc &&
587+
mkdir .git/rr-cache &&
588+
test_expect_rerere_gc ! git maintenance run --auto --task=rerere-gc &&
589+
: >.git/rr-cache/entry &&
590+
test_expect_rerere_gc git maintenance run --auto --task=rerere-gc
591+
'
592+
593+
test_expect_success 'rerere-gc task with --auto honors maintenance.rerere-gc.auto' '
594+
test_when_finished "rm -rf .git/rr-cache" &&
595+
596+
# A negative value should always prune.
597+
test_expect_rerere_gc git -c maintenance.rerere-gc.auto=-1 maintenance run --auto --task=rerere-gc &&
598+
599+
# A positive value prunes when there is at least one entry.
600+
test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=9000 maintenance run --auto --task=rerere-gc &&
601+
mkdir .git/rr-cache &&
602+
test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=9000 maintenance run --auto --task=rerere-gc &&
603+
: >.git/rr-cache/entry-1 &&
604+
test_expect_rerere_gc git -c maintenance.rerere-gc.auto=9000 maintenance run --auto --task=rerere-gc &&
605+
606+
# Zero should never prune.
607+
: >.git/rr-cache/entry-1 &&
608+
test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=0 maintenance run --auto --task=rerere-gc
609+
'
610+
567611
test_expect_success '--auto and --schedule incompatible' '
568612
test_must_fail git maintenance run --auto --schedule=daily 2>err &&
569613
test_grep "at most one" err

0 commit comments

Comments
 (0)