Merge branch 'ps/maintenance-missing-tasks'
Make repository clean-up tasks "gc" can do available to "git maintenance" front-end. * ps/maintenance-missing-tasks: builtin/maintenance: introduce "rerere-gc" task builtin/gc: move rerere garbage collection into separate function builtin/maintenance: introduce "worktree-prune" task builtin/gc: move pruning of worktrees into a separate function builtin/gc: remove global variables where it is trivial to do builtin/gc: fix indentation of `cmd_gc()` parameters
This commit is contained in:
@@ -83,3 +83,20 @@ maintenance.reflog-expire.auto::
|
|||||||
positive value implies the command should run when the number of
|
positive value implies the command should run when the number of
|
||||||
expired reflog entries in the "HEAD" reflog is at least the value of
|
expired reflog entries in the "HEAD" reflog is at least the value of
|
||||||
`maintenance.loose-objects.auto`. The default value is 100.
|
`maintenance.loose-objects.auto`. The default value is 100.
|
||||||
|
|
||||||
|
maintenance.rerere-gc.auto::
|
||||||
|
This integer config option controls how often the `rerere-gc` task
|
||||||
|
should be run as part of `git maintenance run --auto`. If zero, then
|
||||||
|
the `rerere-gc` task will not run with the `--auto` option. A negative
|
||||||
|
value will force the task to run every time. Otherwise, any positive
|
||||||
|
value implies the command will run when the "rr-cache" directory exists
|
||||||
|
and has at least one entry, regardless of whether it is stale or not.
|
||||||
|
This heuristic may be refined in the future. The default value is 1.
|
||||||
|
|
||||||
|
maintenance.worktree-prune.auto::
|
||||||
|
This integer config option controls how often the `worktree-prune` task
|
||||||
|
should be run as part of `git maintenance run --auto`. If zero, then
|
||||||
|
the `worktree-prune` task will not run with the `--auto` option. A
|
||||||
|
negative value will force the task to run every time. Otherwise, a
|
||||||
|
positive value implies the command should run when the number of
|
||||||
|
prunable worktrees exceeds the value. The default value is 1.
|
||||||
|
|||||||
@@ -166,6 +166,14 @@ reflog-expire::
|
|||||||
The `reflog-expire` task deletes any entries in the reflog older than the
|
The `reflog-expire` task deletes any entries in the reflog older than the
|
||||||
expiry threshold. See linkgit:git-reflog[1] for more information.
|
expiry threshold. See linkgit:git-reflog[1] for more information.
|
||||||
|
|
||||||
|
rerere-gc::
|
||||||
|
The `rerere-gc` task invokes garbage collection for stale entries in
|
||||||
|
the rerere cache. See linkgit:git-rerere[1] for more information.
|
||||||
|
|
||||||
|
worktree-prune::
|
||||||
|
The `worktree-prune` task deletes stale or broken worktrees. See
|
||||||
|
linkit:git-worktree[1] for more information.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
--auto::
|
--auto::
|
||||||
|
|||||||
148
builtin/gc.c
148
builtin/gc.c
@@ -16,6 +16,7 @@
|
|||||||
#include "builtin.h"
|
#include "builtin.h"
|
||||||
#include "abspath.h"
|
#include "abspath.h"
|
||||||
#include "date.h"
|
#include "date.h"
|
||||||
|
#include "dir.h"
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
#include "hex.h"
|
#include "hex.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@@ -33,6 +34,7 @@
|
|||||||
#include "pack-objects.h"
|
#include "pack-objects.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
#include "reflog.h"
|
#include "reflog.h"
|
||||||
|
#include "rerere.h"
|
||||||
#include "blob.h"
|
#include "blob.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
#include "promisor-remote.h"
|
#include "promisor-remote.h"
|
||||||
@@ -43,6 +45,7 @@
|
|||||||
#include "hook.h"
|
#include "hook.h"
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
#include "trace2.h"
|
#include "trace2.h"
|
||||||
|
#include "worktree.h"
|
||||||
|
|
||||||
#define FAILED_RUN "failed to run %s"
|
#define FAILED_RUN "failed to run %s"
|
||||||
|
|
||||||
@@ -52,15 +55,9 @@ static const char * const builtin_gc_usage[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static timestamp_t gc_log_expire_time;
|
static timestamp_t gc_log_expire_time;
|
||||||
|
|
||||||
static struct strvec repack = STRVEC_INIT;
|
static struct strvec repack = STRVEC_INIT;
|
||||||
static struct strvec prune = STRVEC_INIT;
|
|
||||||
static struct strvec prune_worktrees = STRVEC_INIT;
|
|
||||||
static struct strvec rerere = STRVEC_INIT;
|
|
||||||
|
|
||||||
static struct tempfile *pidfile;
|
static struct tempfile *pidfile;
|
||||||
static struct lock_file log_lock;
|
static struct lock_file log_lock;
|
||||||
|
|
||||||
static struct string_list pack_garbage = STRING_LIST_INIT_DUP;
|
static struct string_list pack_garbage = STRING_LIST_INIT_DUP;
|
||||||
|
|
||||||
static void clean_pack_garbage(void)
|
static void clean_pack_garbage(void)
|
||||||
@@ -339,6 +336,94 @@ static int maintenance_task_reflog_expire(struct maintenance_run_opts *opts UNUS
|
|||||||
return run_command(&cmd);
|
return run_command(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int maintenance_task_worktree_prune(struct maintenance_run_opts *opts UNUSED,
|
||||||
|
struct gc_config *cfg)
|
||||||
|
{
|
||||||
|
struct child_process prune_worktrees_cmd = CHILD_PROCESS_INIT;
|
||||||
|
|
||||||
|
prune_worktrees_cmd.git_cmd = 1;
|
||||||
|
strvec_pushl(&prune_worktrees_cmd.args, "worktree", "prune", "--expire", NULL);
|
||||||
|
strvec_push(&prune_worktrees_cmd.args, cfg->prune_worktrees_expire);
|
||||||
|
|
||||||
|
return run_command(&prune_worktrees_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int worktree_prune_condition(struct gc_config *cfg)
|
||||||
|
{
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
int should_prune = 0, limit = 1;
|
||||||
|
timestamp_t expiry_date;
|
||||||
|
struct dirent *d;
|
||||||
|
DIR *dir = NULL;
|
||||||
|
|
||||||
|
git_config_get_int("maintenance.worktree-prune.auto", &limit);
|
||||||
|
if (limit <= 0) {
|
||||||
|
should_prune = limit < 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parse_expiry_date(cfg->prune_worktrees_expire, &expiry_date))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
dir = opendir(repo_git_path_replace(the_repository, &buf, "worktrees"));
|
||||||
|
if (!dir)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
while (limit && (d = readdir_skip_dot_and_dotdot(dir))) {
|
||||||
|
char *wtpath;
|
||||||
|
strbuf_reset(&buf);
|
||||||
|
if (should_prune_worktree(d->d_name, &buf, &wtpath, expiry_date))
|
||||||
|
limit--;
|
||||||
|
free(wtpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
should_prune = !limit;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (dir)
|
||||||
|
closedir(dir);
|
||||||
|
strbuf_release(&buf);
|
||||||
|
return should_prune;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int maintenance_task_rerere_gc(struct maintenance_run_opts *opts UNUSED,
|
||||||
|
struct gc_config *cfg UNUSED)
|
||||||
|
{
|
||||||
|
struct child_process rerere_cmd = CHILD_PROCESS_INIT;
|
||||||
|
rerere_cmd.git_cmd = 1;
|
||||||
|
strvec_pushl(&rerere_cmd.args, "rerere", "gc", NULL);
|
||||||
|
return run_command(&rerere_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rerere_gc_condition(struct gc_config *cfg UNUSED)
|
||||||
|
{
|
||||||
|
struct strbuf path = STRBUF_INIT;
|
||||||
|
int should_gc = 0, limit = 1;
|
||||||
|
DIR *dir = NULL;
|
||||||
|
|
||||||
|
git_config_get_int("maintenance.rerere-gc.auto", &limit);
|
||||||
|
if (limit <= 0) {
|
||||||
|
should_gc = limit < 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We skip garbage collection in case we either have no "rr-cache"
|
||||||
|
* directory or when it doesn't contain at least one entry.
|
||||||
|
*/
|
||||||
|
repo_git_path_replace(the_repository, &path, "rr-cache");
|
||||||
|
dir = opendir(path.buf);
|
||||||
|
if (!dir)
|
||||||
|
goto out;
|
||||||
|
should_gc = !!readdir_skip_dot_and_dotdot(dir);
|
||||||
|
|
||||||
|
out:
|
||||||
|
strbuf_release(&path);
|
||||||
|
if (dir)
|
||||||
|
closedir(dir);
|
||||||
|
return should_gc;
|
||||||
|
}
|
||||||
|
|
||||||
static int too_many_loose_objects(struct gc_config *cfg)
|
static int too_many_loose_objects(struct gc_config *cfg)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -728,9 +813,9 @@ static void gc_before_repack(struct maintenance_run_opts *opts,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int cmd_gc(int argc,
|
int cmd_gc(int argc,
|
||||||
const char **argv,
|
const char **argv,
|
||||||
const char *prefix,
|
const char *prefix,
|
||||||
struct repository *repo UNUSED)
|
struct repository *repo UNUSED)
|
||||||
{
|
{
|
||||||
int aggressive = 0;
|
int aggressive = 0;
|
||||||
int quiet = 0;
|
int quiet = 0;
|
||||||
@@ -740,7 +825,6 @@ struct repository *repo UNUSED)
|
|||||||
int daemonized = 0;
|
int daemonized = 0;
|
||||||
int keep_largest_pack = -1;
|
int keep_largest_pack = -1;
|
||||||
timestamp_t dummy;
|
timestamp_t dummy;
|
||||||
struct child_process rerere_cmd = CHILD_PROCESS_INIT;
|
|
||||||
struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT;
|
struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT;
|
||||||
struct gc_config cfg = GC_CONFIG_INIT;
|
struct gc_config cfg = GC_CONFIG_INIT;
|
||||||
const char *prune_expire_sentinel = "sentinel";
|
const char *prune_expire_sentinel = "sentinel";
|
||||||
@@ -779,9 +863,6 @@ struct repository *repo UNUSED)
|
|||||||
builtin_gc_usage, builtin_gc_options);
|
builtin_gc_usage, builtin_gc_options);
|
||||||
|
|
||||||
strvec_pushl(&repack, "repack", "-d", "-l", NULL);
|
strvec_pushl(&repack, "repack", "-d", "-l", NULL);
|
||||||
strvec_pushl(&prune, "prune", "--expire", NULL);
|
|
||||||
strvec_pushl(&prune_worktrees, "worktree", "prune", "--expire", NULL);
|
|
||||||
strvec_pushl(&rerere, "rerere", "gc", NULL);
|
|
||||||
|
|
||||||
gc_config(&cfg);
|
gc_config(&cfg);
|
||||||
|
|
||||||
@@ -907,34 +988,27 @@ struct repository *repo UNUSED)
|
|||||||
if (cfg.prune_expire) {
|
if (cfg.prune_expire) {
|
||||||
struct child_process prune_cmd = CHILD_PROCESS_INIT;
|
struct child_process prune_cmd = CHILD_PROCESS_INIT;
|
||||||
|
|
||||||
|
strvec_pushl(&prune_cmd.args, "prune", "--expire", NULL);
|
||||||
/* run `git prune` even if using cruft packs */
|
/* run `git prune` even if using cruft packs */
|
||||||
strvec_push(&prune, cfg.prune_expire);
|
strvec_push(&prune_cmd.args, cfg.prune_expire);
|
||||||
if (quiet)
|
if (quiet)
|
||||||
strvec_push(&prune, "--no-progress");
|
strvec_push(&prune_cmd.args, "--no-progress");
|
||||||
if (repo_has_promisor_remote(the_repository))
|
if (repo_has_promisor_remote(the_repository))
|
||||||
strvec_push(&prune,
|
strvec_push(&prune_cmd.args,
|
||||||
"--exclude-promisor-objects");
|
"--exclude-promisor-objects");
|
||||||
prune_cmd.git_cmd = 1;
|
prune_cmd.git_cmd = 1;
|
||||||
strvec_pushv(&prune_cmd.args, prune.v);
|
|
||||||
if (run_command(&prune_cmd))
|
if (run_command(&prune_cmd))
|
||||||
die(FAILED_RUN, prune.v[0]);
|
die(FAILED_RUN, prune_cmd.args.v[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg.prune_worktrees_expire) {
|
if (cfg.prune_worktrees_expire &&
|
||||||
struct child_process prune_worktrees_cmd = CHILD_PROCESS_INIT;
|
maintenance_task_worktree_prune(&opts, &cfg))
|
||||||
|
die(FAILED_RUN, "worktree");
|
||||||
|
|
||||||
strvec_push(&prune_worktrees, cfg.prune_worktrees_expire);
|
if (maintenance_task_rerere_gc(&opts, &cfg))
|
||||||
prune_worktrees_cmd.git_cmd = 1;
|
die(FAILED_RUN, "rerere");
|
||||||
strvec_pushv(&prune_worktrees_cmd.args, prune_worktrees.v);
|
|
||||||
if (run_command(&prune_worktrees_cmd))
|
|
||||||
die(FAILED_RUN, prune_worktrees.v[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
rerere_cmd.git_cmd = 1;
|
|
||||||
strvec_pushv(&rerere_cmd.args, rerere.v);
|
|
||||||
if (run_command(&rerere_cmd))
|
|
||||||
die(FAILED_RUN, rerere.v[0]);
|
|
||||||
|
|
||||||
report_garbage = report_pack_garbage;
|
report_garbage = report_pack_garbage;
|
||||||
reprepare_packed_git(the_repository);
|
reprepare_packed_git(the_repository);
|
||||||
@@ -1467,6 +1541,8 @@ enum maintenance_task_label {
|
|||||||
TASK_COMMIT_GRAPH,
|
TASK_COMMIT_GRAPH,
|
||||||
TASK_PACK_REFS,
|
TASK_PACK_REFS,
|
||||||
TASK_REFLOG_EXPIRE,
|
TASK_REFLOG_EXPIRE,
|
||||||
|
TASK_WORKTREE_PRUNE,
|
||||||
|
TASK_RERERE_GC,
|
||||||
|
|
||||||
/* Leave as final value */
|
/* Leave as final value */
|
||||||
TASK__COUNT
|
TASK__COUNT
|
||||||
@@ -1508,6 +1584,16 @@ static struct maintenance_task tasks[] = {
|
|||||||
maintenance_task_reflog_expire,
|
maintenance_task_reflog_expire,
|
||||||
reflog_expire_condition,
|
reflog_expire_condition,
|
||||||
},
|
},
|
||||||
|
[TASK_WORKTREE_PRUNE] = {
|
||||||
|
"worktree-prune",
|
||||||
|
maintenance_task_worktree_prune,
|
||||||
|
worktree_prune_condition,
|
||||||
|
},
|
||||||
|
[TASK_RERERE_GC] = {
|
||||||
|
"rerere-gc",
|
||||||
|
maintenance_task_rerere_gc,
|
||||||
|
rerere_gc_condition,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int compare_tasks_by_selection(const void *a_, const void *b_)
|
static int compare_tasks_by_selection(const void *a_, const void *b_)
|
||||||
|
|||||||
@@ -493,6 +493,121 @@ test_expect_success 'reflog-expire task --auto only packs when exceeding limits'
|
|||||||
test_subcommand git reflog expire --all <reflog-expire-auto.txt
|
test_subcommand git reflog expire --all <reflog-expire-auto.txt
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_worktree_prune () {
|
||||||
|
negate=
|
||||||
|
if test "$1" = "!"
|
||||||
|
then
|
||||||
|
negate="!"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "worktree-prune.txt" &&
|
||||||
|
GIT_TRACE2_EVENT="$(pwd)/worktree-prune.txt" "$@" &&
|
||||||
|
test_subcommand $negate git worktree prune --expire 3.months.ago <worktree-prune.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
test_expect_success 'worktree-prune task without --auto always prunes' '
|
||||||
|
test_expect_worktree_prune git maintenance run --task=worktree-prune
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'worktree-prune task --auto only prunes with prunable worktree' '
|
||||||
|
test_expect_worktree_prune ! git maintenance run --auto --task=worktree-prune &&
|
||||||
|
mkdir .git/worktrees &&
|
||||||
|
: >.git/worktrees/abc &&
|
||||||
|
test_expect_worktree_prune git maintenance run --auto --task=worktree-prune
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'worktree-prune task with --auto honors maintenance.worktree-prune.auto' '
|
||||||
|
# A negative value should always prune.
|
||||||
|
test_expect_worktree_prune git -c maintenance.worktree-prune.auto=-1 maintenance run --auto --task=worktree-prune &&
|
||||||
|
|
||||||
|
mkdir .git/worktrees &&
|
||||||
|
: >.git/worktrees/first &&
|
||||||
|
: >.git/worktrees/second &&
|
||||||
|
: >.git/worktrees/third &&
|
||||||
|
|
||||||
|
# Zero should never prune.
|
||||||
|
test_expect_worktree_prune ! git -c maintenance.worktree-prune.auto=0 maintenance run --auto --task=worktree-prune &&
|
||||||
|
# A positive value should require at least this many prunable worktrees.
|
||||||
|
test_expect_worktree_prune ! git -c maintenance.worktree-prune.auto=4 maintenance run --auto --task=worktree-prune &&
|
||||||
|
test_expect_worktree_prune git -c maintenance.worktree-prune.auto=3 maintenance run --auto --task=worktree-prune
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'worktree-prune task with --auto honors maintenance.worktree-prune.auto' '
|
||||||
|
# A negative value should always prune.
|
||||||
|
test_expect_worktree_prune git -c maintenance.worktree-prune.auto=-1 maintenance run --auto --task=worktree-prune &&
|
||||||
|
|
||||||
|
mkdir .git/worktrees &&
|
||||||
|
: >.git/worktrees/first &&
|
||||||
|
: >.git/worktrees/second &&
|
||||||
|
: >.git/worktrees/third &&
|
||||||
|
|
||||||
|
# Zero should never prune.
|
||||||
|
test_expect_worktree_prune ! git -c maintenance.worktree-prune.auto=0 maintenance run --auto --task=worktree-prune &&
|
||||||
|
# A positive value should require at least this many prunable worktrees.
|
||||||
|
test_expect_worktree_prune ! git -c maintenance.worktree-prune.auto=4 maintenance run --auto --task=worktree-prune &&
|
||||||
|
test_expect_worktree_prune git -c maintenance.worktree-prune.auto=3 maintenance run --auto --task=worktree-prune
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'worktree-prune task honors gc.worktreePruneExpire' '
|
||||||
|
git worktree add worktree &&
|
||||||
|
rm -rf worktree &&
|
||||||
|
|
||||||
|
rm -f worktree-prune.txt &&
|
||||||
|
GIT_TRACE2_EVENT="$(pwd)/worktree-prune.txt" git -c gc.worktreePruneExpire=1.week.ago maintenance run --auto --task=worktree-prune &&
|
||||||
|
test_subcommand ! git worktree prune --expire 1.week.ago <worktree-prune.txt &&
|
||||||
|
test_path_is_dir .git/worktrees/worktree &&
|
||||||
|
|
||||||
|
rm -f worktree-prune.txt &&
|
||||||
|
GIT_TRACE2_EVENT="$(pwd)/worktree-prune.txt" git -c gc.worktreePruneExpire=now maintenance run --auto --task=worktree-prune &&
|
||||||
|
test_subcommand git worktree prune --expire now <worktree-prune.txt &&
|
||||||
|
test_path_is_missing .git/worktrees/worktree
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_rerere_gc () {
|
||||||
|
negate=
|
||||||
|
if test "$1" = "!"
|
||||||
|
then
|
||||||
|
negate="!"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "rerere-gc.txt" &&
|
||||||
|
GIT_TRACE2_EVENT="$(pwd)/rerere-gc.txt" "$@" &&
|
||||||
|
test_subcommand $negate git rerere gc <rerere-gc.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
test_expect_success 'rerere-gc task without --auto always collects garbage' '
|
||||||
|
test_expect_rerere_gc git maintenance run --task=rerere-gc
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'rerere-gc task with --auto only prunes with prunable entries' '
|
||||||
|
test_when_finished "rm -rf .git/rr-cache" &&
|
||||||
|
test_expect_rerere_gc ! git maintenance run --auto --task=rerere-gc &&
|
||||||
|
mkdir .git/rr-cache &&
|
||||||
|
test_expect_rerere_gc ! git maintenance run --auto --task=rerere-gc &&
|
||||||
|
: >.git/rr-cache/entry &&
|
||||||
|
test_expect_rerere_gc git maintenance run --auto --task=rerere-gc
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'rerere-gc task with --auto honors maintenance.rerere-gc.auto' '
|
||||||
|
test_when_finished "rm -rf .git/rr-cache" &&
|
||||||
|
|
||||||
|
# A negative value should always prune.
|
||||||
|
test_expect_rerere_gc git -c maintenance.rerere-gc.auto=-1 maintenance run --auto --task=rerere-gc &&
|
||||||
|
|
||||||
|
# A positive value prunes when there is at least one entry.
|
||||||
|
test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=9000 maintenance run --auto --task=rerere-gc &&
|
||||||
|
mkdir .git/rr-cache &&
|
||||||
|
test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=9000 maintenance run --auto --task=rerere-gc &&
|
||||||
|
: >.git/rr-cache/entry-1 &&
|
||||||
|
test_expect_rerere_gc git -c maintenance.rerere-gc.auto=9000 maintenance run --auto --task=rerere-gc &&
|
||||||
|
|
||||||
|
# Zero should never prune.
|
||||||
|
: >.git/rr-cache/entry-1 &&
|
||||||
|
test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=0 maintenance run --auto --task=rerere-gc
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success '--auto and --schedule incompatible' '
|
test_expect_success '--auto and --schedule incompatible' '
|
||||||
test_must_fail git maintenance run --auto --schedule=daily 2>err &&
|
test_must_fail git maintenance run --auto --schedule=daily 2>err &&
|
||||||
test_grep "at most one" err
|
test_grep "at most one" err
|
||||||
|
|||||||
Reference in New Issue
Block a user