diff options
| -rw-r--r-- | Documentation/config/maintenance.adoc | 9 | ||||
| -rw-r--r-- | Documentation/git-maintenance.adoc | 4 | ||||
| -rw-r--r-- | builtin/gc.c | 72 | ||||
| -rw-r--r-- | builtin/reflog.c | 153 | ||||
| -rw-r--r-- | reflog.c | 137 | ||||
| -rw-r--r-- | reflog.h | 35 | ||||
| -rwxr-xr-x | t/t7900-maintenance.sh | 18 |
7 files changed, 263 insertions, 165 deletions
diff --git a/Documentation/config/maintenance.adoc b/Documentation/config/maintenance.adoc index 42f9545da0..41536162a7 100644 --- a/Documentation/config/maintenance.adoc +++ b/Documentation/config/maintenance.adoc @@ -74,3 +74,12 @@ maintenance.incremental-repack.auto:: Otherwise, a positive value implies the command should run when the number of pack-files not in the multi-pack-index is at least the value of `maintenance.incremental-repack.auto`. The default value is 10. + +maintenance.reflog-expire.auto:: + This integer config option controls how often the `reflog-expire` task + should be run as part of `git maintenance run --auto`. If zero, then + the `reflog-expire` 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 + expired reflog entries in the "HEAD" reflog is at least the value of + `maintenance.loose-objects.auto`. The default value is 100. diff --git a/Documentation/git-maintenance.adoc b/Documentation/git-maintenance.adoc index c90b370b1f..3a1e2a69b6 100644 --- a/Documentation/git-maintenance.adoc +++ b/Documentation/git-maintenance.adoc @@ -162,6 +162,10 @@ pack-refs:: need to iterate across many references. See linkgit:git-pack-refs[1] for more information. +reflog-expire:: + The `reflog-expire` task deletes any entries in the reflog older than the + expiry threshold. See linkgit:git-reflog[1] for more information. + OPTIONS ------- --auto:: diff --git a/builtin/gc.c b/builtin/gc.c index 817081e1a5..d5c75be252 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -33,6 +33,7 @@ #include "pack.h" #include "pack-objects.h" #include "path.h" +#include "reflog.h" #include "blob.h" #include "tree.h" #include "promisor-remote.h" @@ -53,7 +54,6 @@ static const char * const builtin_gc_usage[] = { static timestamp_t gc_log_expire_time; -static struct strvec reflog = STRVEC_INIT; static struct strvec repack = STRVEC_INIT; static struct strvec prune = STRVEC_INIT; static struct strvec prune_worktrees = STRVEC_INIT; @@ -288,6 +288,58 @@ static int maintenance_task_pack_refs(struct maintenance_run_opts *opts, return run_command(&cmd); } +struct count_reflog_entries_data { + struct expire_reflog_policy_cb policy; + size_t count; + size_t limit; +}; + +static int count_reflog_entries(struct object_id *old_oid, struct object_id *new_oid, + const char *committer, timestamp_t timestamp, + int tz, const char *msg, void *cb_data) +{ + struct count_reflog_entries_data *data = cb_data; + if (should_expire_reflog_ent(old_oid, new_oid, committer, timestamp, tz, msg, &data->policy)) + data->count++; + return data->count >= data->limit; +} + +static int reflog_expire_condition(struct gc_config *cfg UNUSED) +{ + timestamp_t now = time(NULL); + struct count_reflog_entries_data data = { + .policy = { + .opts = REFLOG_EXPIRE_OPTIONS_INIT(now), + }, + }; + int limit = 100; + + git_config_get_int("maintenance.reflog-expire.auto", &limit); + if (!limit) + return 0; + if (limit < 0) + return 1; + data.limit = limit; + + repo_config(the_repository, reflog_expire_config, &data.policy.opts); + + reflog_expire_options_set_refname(&data.policy.opts, "HEAD"); + refs_for_each_reflog_ent(get_main_ref_store(the_repository), "HEAD", + count_reflog_entries, &data); + + reflog_expiry_cleanup(&data.policy); + return data.count >= data.limit; +} + +static int maintenance_task_reflog_expire(struct maintenance_run_opts *opts UNUSED, + struct gc_config *cfg UNUSED) +{ + struct child_process cmd = CHILD_PROCESS_INIT; + cmd.git_cmd = 1; + strvec_pushl(&cmd.args, "reflog", "expire", "--all", NULL); + return run_command(&cmd); +} + static int too_many_loose_objects(struct gc_config *cfg) { /* @@ -667,15 +719,8 @@ static void gc_before_repack(struct maintenance_run_opts *opts, if (cfg->pack_refs && maintenance_task_pack_refs(opts, cfg)) die(FAILED_RUN, "pack-refs"); - - if (cfg->prune_reflogs) { - struct child_process cmd = CHILD_PROCESS_INIT; - - cmd.git_cmd = 1; - strvec_pushv(&cmd.args, reflog.v); - if (run_command(&cmd)) - die(FAILED_RUN, reflog.v[0]); - } + if (cfg->prune_reflogs && maintenance_task_reflog_expire(opts, cfg)) + die(FAILED_RUN, "reflog"); } int cmd_gc(int argc, @@ -723,7 +768,6 @@ struct repository *repo UNUSED) show_usage_with_options_if_asked(argc, argv, builtin_gc_usage, builtin_gc_options); - strvec_pushl(&reflog, "reflog", "expire", "--all", NULL); strvec_pushl(&repack, "repack", "-d", "-l", NULL); strvec_pushl(&prune, "prune", "--expire", NULL); strvec_pushl(&prune_worktrees, "worktree", "prune", "--expire", NULL); @@ -1412,6 +1456,7 @@ enum maintenance_task_label { TASK_GC, TASK_COMMIT_GRAPH, TASK_PACK_REFS, + TASK_REFLOG_EXPIRE, /* Leave as final value */ TASK__COUNT @@ -1448,6 +1493,11 @@ static struct maintenance_task tasks[] = { maintenance_task_pack_refs, pack_refs_condition, }, + [TASK_REFLOG_EXPIRE] = { + "reflog-expire", + maintenance_task_reflog_expire, + reflog_expire_condition, + }, }; static int compare_tasks_by_selection(const void *a_, const void *b_) diff --git a/builtin/reflog.c b/builtin/reflog.c index a3652e69f1..3acaf3e32c 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -72,9 +72,6 @@ static const char *const reflog_usage[] = { NULL }; -static timestamp_t default_reflog_expire; -static timestamp_t default_reflog_expire_unreachable; - struct worktree_reflogs { struct worktree *worktree; struct string_list reflogs; @@ -100,131 +97,19 @@ static int collect_reflog(const char *ref, void *cb_data) return 0; } -static struct reflog_expire_cfg { - struct reflog_expire_cfg *next; - timestamp_t expire_total; - timestamp_t expire_unreachable; - char pattern[FLEX_ARRAY]; -} *reflog_expire_cfg, **reflog_expire_cfg_tail; - -static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len) -{ - struct reflog_expire_cfg *ent; - - if (!reflog_expire_cfg_tail) - reflog_expire_cfg_tail = &reflog_expire_cfg; - - for (ent = reflog_expire_cfg; ent; ent = ent->next) - if (!xstrncmpz(ent->pattern, pattern, len)) - return ent; - - FLEX_ALLOC_MEM(ent, pattern, pattern, len); - *reflog_expire_cfg_tail = ent; - reflog_expire_cfg_tail = &(ent->next); - return ent; -} - -/* expiry timer slot */ -#define EXPIRE_TOTAL 01 -#define EXPIRE_UNREACH 02 - -static int reflog_expire_config(const char *var, const char *value, - const struct config_context *ctx, void *cb) -{ - const char *pattern, *key; - size_t pattern_len; - timestamp_t expire; - int slot; - struct reflog_expire_cfg *ent; - - if (parse_config_key(var, "gc", &pattern, &pattern_len, &key) < 0) - return git_default_config(var, value, ctx, cb); - - if (!strcmp(key, "reflogexpire")) { - slot = EXPIRE_TOTAL; - if (git_config_expiry_date(&expire, var, value)) - return -1; - } else if (!strcmp(key, "reflogexpireunreachable")) { - slot = EXPIRE_UNREACH; - if (git_config_expiry_date(&expire, var, value)) - return -1; - } else - return git_default_config(var, value, ctx, cb); - - if (!pattern) { - switch (slot) { - case EXPIRE_TOTAL: - default_reflog_expire = expire; - break; - case EXPIRE_UNREACH: - default_reflog_expire_unreachable = expire; - break; - } - return 0; - } - - ent = find_cfg_ent(pattern, pattern_len); - if (!ent) - return -1; - switch (slot) { - case EXPIRE_TOTAL: - ent->expire_total = expire; - break; - case EXPIRE_UNREACH: - ent->expire_unreachable = expire; - break; - } - return 0; -} - -static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, const char *ref) -{ - struct reflog_expire_cfg *ent; - - if (cb->explicit_expiry == (EXPIRE_TOTAL|EXPIRE_UNREACH)) - return; /* both given explicitly -- nothing to tweak */ - - for (ent = reflog_expire_cfg; ent; ent = ent->next) { - if (!wildmatch(ent->pattern, ref, 0)) { - if (!(cb->explicit_expiry & EXPIRE_TOTAL)) - cb->expire_total = ent->expire_total; - if (!(cb->explicit_expiry & EXPIRE_UNREACH)) - cb->expire_unreachable = ent->expire_unreachable; - return; - } - } - - /* - * If unconfigured, make stash never expire - */ - if (!strcmp(ref, "refs/stash")) { - if (!(cb->explicit_expiry & EXPIRE_TOTAL)) - cb->expire_total = 0; - if (!(cb->explicit_expiry & EXPIRE_UNREACH)) - cb->expire_unreachable = 0; - return; - } - - /* Nothing matched -- use the default value */ - if (!(cb->explicit_expiry & EXPIRE_TOTAL)) - cb->expire_total = default_reflog_expire; - if (!(cb->explicit_expiry & EXPIRE_UNREACH)) - cb->expire_unreachable = default_reflog_expire_unreachable; -} - static int expire_unreachable_callback(const struct option *opt, const char *arg, int unset) { - struct cmd_reflog_expire_cb *cmd = opt->value; + struct reflog_expire_options *opts = opt->value; BUG_ON_OPT_NEG(unset); - if (parse_expiry_date(arg, &cmd->expire_unreachable)) + if (parse_expiry_date(arg, &opts->expire_unreachable)) die(_("invalid timestamp '%s' given to '--%s'"), arg, opt->long_name); - cmd->explicit_expiry |= EXPIRE_UNREACH; + opts->explicit_expiry |= REFLOG_EXPIRE_UNREACH; return 0; } @@ -232,15 +117,15 @@ static int expire_total_callback(const struct option *opt, const char *arg, int unset) { - struct cmd_reflog_expire_cb *cmd = opt->value; + struct reflog_expire_options *opts = opt->value; BUG_ON_OPT_NEG(unset); - if (parse_expiry_date(arg, &cmd->expire_total)) + if (parse_expiry_date(arg, &opts->expire_total)) die(_("invalid timestamp '%s' given to '--%s'"), arg, opt->long_name); - cmd->explicit_expiry |= EXPIRE_TOTAL; + opts->explicit_expiry |= REFLOG_EXPIRE_TOTAL; return 0; } @@ -285,8 +170,8 @@ static int cmd_reflog_list(int argc, const char **argv, const char *prefix, static int cmd_reflog_expire(int argc, const char **argv, const char *prefix, struct repository *repo UNUSED) { - struct cmd_reflog_expire_cb cmd = { 0 }; timestamp_t now = time(NULL); + struct reflog_expire_options opts = REFLOG_EXPIRE_OPTIONS_INIT(now); int i, status, do_all, single_worktree = 0; unsigned int flags = 0; int verbose = 0; @@ -301,15 +186,15 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix, N_("update the reference to the value of the top reflog entry"), EXPIRE_REFLOGS_UPDATE_REF), OPT_BOOL(0, "verbose", &verbose, N_("print extra information on screen")), - OPT_CALLBACK_F(0, "expire", &cmd, N_("timestamp"), + OPT_CALLBACK_F(0, "expire", &opts, N_("timestamp"), N_("prune entries older than the specified time"), PARSE_OPT_NONEG, expire_total_callback), - OPT_CALLBACK_F(0, "expire-unreachable", &cmd, N_("timestamp"), + OPT_CALLBACK_F(0, "expire-unreachable", &opts, N_("timestamp"), N_("prune entries older than <time> that are not reachable from the current tip of the branch"), PARSE_OPT_NONEG, expire_unreachable_callback), - OPT_BOOL(0, "stale-fix", &cmd.stalefix, + OPT_BOOL(0, "stale-fix", &opts.stalefix, N_("prune any reflog entries that point to broken commits")), OPT_BOOL(0, "all", &do_all, N_("process the reflogs of all references")), OPT_BOOL(0, "single-worktree", &single_worktree, @@ -317,17 +202,11 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix, OPT_END() }; - default_reflog_expire_unreachable = now - 30 * 24 * 3600; - default_reflog_expire = now - 90 * 24 * 3600; - git_config(reflog_expire_config, NULL); + git_config(reflog_expire_config, &opts); save_commit_buffer = 0; do_all = status = 0; - cmd.explicit_expiry = 0; - cmd.expire_total = default_reflog_expire; - cmd.expire_unreachable = default_reflog_expire_unreachable; - argc = parse_options(argc, argv, prefix, options, reflog_expire_usage, 0); if (verbose) @@ -338,7 +217,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix, * even in older repository. We cannot trust what's reachable * from reflog if the repository was pruned with older git. */ - if (cmd.stalefix) { + if (opts.stalefix) { struct rev_info revs; repo_init_revisions(the_repository, &revs, prefix); @@ -372,11 +251,11 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix, for_each_string_list_item(item, &collected.reflogs) { struct expire_reflog_policy_cb cb = { - .cmd = cmd, + .opts = opts, .dry_run = !!(flags & EXPIRE_REFLOGS_DRY_RUN), }; - set_reflog_expiry_param(&cb.cmd, item->string); + reflog_expire_options_set_refname(&cb.opts, item->string); status |= refs_reflog_expire(get_main_ref_store(the_repository), item->string, flags, reflog_expiry_prepare, @@ -389,13 +268,13 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix, for (i = 0; i < argc; i++) { char *ref; - struct expire_reflog_policy_cb cb = { .cmd = cmd }; + struct expire_reflog_policy_cb cb = { .opts = opts }; if (!repo_dwim_log(the_repository, argv[i], strlen(argv[i]), NULL, &ref)) { status |= error(_("reflog could not be found: '%s'"), argv[i]); continue; } - set_reflog_expiry_param(&cb.cmd, ref); + reflog_expire_options_set_refname(&cb.opts, ref); status |= refs_reflog_expire(get_main_ref_store(the_repository), ref, flags, reflog_expiry_prepare, @@ -2,13 +2,120 @@ #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" +#include "config.h" #include "gettext.h" #include "object-store-ll.h" +#include "parse-options.h" #include "reflog.h" #include "refs.h" #include "revision.h" #include "tree.h" #include "tree-walk.h" +#include "wildmatch.h" + +static struct reflog_expire_entry_option *find_cfg_ent(struct reflog_expire_options *opts, + const char *pattern, size_t len) +{ + struct reflog_expire_entry_option *ent; + + if (!opts->entries_tail) + opts->entries_tail = &opts->entries; + + for (ent = opts->entries; ent; ent = ent->next) + if (!xstrncmpz(ent->pattern, pattern, len)) + return ent; + + FLEX_ALLOC_MEM(ent, pattern, pattern, len); + *opts->entries_tail = ent; + opts->entries_tail = &(ent->next); + return ent; +} + +int reflog_expire_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) +{ + struct reflog_expire_options *opts = cb; + const char *pattern, *key; + size_t pattern_len; + timestamp_t expire; + int slot; + struct reflog_expire_entry_option *ent; + + if (parse_config_key(var, "gc", &pattern, &pattern_len, &key) < 0) + return git_default_config(var, value, ctx, cb); + + if (!strcmp(key, "reflogexpire")) { + slot = REFLOG_EXPIRE_TOTAL; + if (git_config_expiry_date(&expire, var, value)) + return -1; + } else if (!strcmp(key, "reflogexpireunreachable")) { + slot = REFLOG_EXPIRE_UNREACH; + if (git_config_expiry_date(&expire, var, value)) + return -1; + } else + return git_default_config(var, value, ctx, cb); + + if (!pattern) { + switch (slot) { + case REFLOG_EXPIRE_TOTAL: + opts->default_expire_total = expire; + break; + case REFLOG_EXPIRE_UNREACH: + opts->default_expire_unreachable = expire; + break; + } + return 0; + } + + ent = find_cfg_ent(opts, pattern, pattern_len); + if (!ent) + return -1; + switch (slot) { + case REFLOG_EXPIRE_TOTAL: + ent->expire_total = expire; + break; + case REFLOG_EXPIRE_UNREACH: + ent->expire_unreachable = expire; + break; + } + return 0; +} + +void reflog_expire_options_set_refname(struct reflog_expire_options *cb, + const char *ref) +{ + struct reflog_expire_entry_option *ent; + + if (cb->explicit_expiry == (REFLOG_EXPIRE_TOTAL|REFLOG_EXPIRE_UNREACH)) + return; /* both given explicitly -- nothing to tweak */ + + for (ent = cb->entries; ent; ent = ent->next) { + if (!wildmatch(ent->pattern, ref, 0)) { + if (!(cb->explicit_expiry & REFLOG_EXPIRE_TOTAL)) + cb->expire_total = ent->expire_total; + if (!(cb->explicit_expiry & REFLOG_EXPIRE_UNREACH)) + cb->expire_unreachable = ent->expire_unreachable; + return; + } + } + + /* + * If unconfigured, make stash never expire + */ + if (!strcmp(ref, "refs/stash")) { + if (!(cb->explicit_expiry & REFLOG_EXPIRE_TOTAL)) + cb->expire_total = 0; + if (!(cb->explicit_expiry & REFLOG_EXPIRE_UNREACH)) + cb->expire_unreachable = 0; + return; + } + + /* Nothing matched -- use the default value */ + if (!(cb->explicit_expiry & REFLOG_EXPIRE_TOTAL)) + cb->expire_total = cb->default_expire_total; + if (!(cb->explicit_expiry & REFLOG_EXPIRE_UNREACH)) + cb->expire_unreachable = cb->default_expire_unreachable; +} /* Remember to update object flag allocation in object.h */ #define INCOMPLETE (1u<<10) @@ -252,15 +359,15 @@ int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid, struct expire_reflog_policy_cb *cb = cb_data; struct commit *old_commit, *new_commit; - if (timestamp < cb->cmd.expire_total) + if (timestamp < cb->opts.expire_total) return 1; old_commit = new_commit = NULL; - if (cb->cmd.stalefix && + if (cb->opts.stalefix && (!keep_entry(&old_commit, ooid) || !keep_entry(&new_commit, noid))) return 1; - if (timestamp < cb->cmd.expire_unreachable) { + if (timestamp < cb->opts.expire_unreachable) { switch (cb->unreachable_expire_kind) { case UE_ALWAYS: return 1; @@ -272,7 +379,7 @@ int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid, } } - if (cb->cmd.recno && --(cb->cmd.recno) == 0) + if (cb->opts.recno && --(cb->opts.recno) == 0) return 1; return 0; @@ -331,7 +438,7 @@ void reflog_expiry_prepare(const char *refname, struct commit_list *elem; struct commit *commit = NULL; - if (!cb->cmd.expire_unreachable || is_head(refname)) { + if (!cb->opts.expire_unreachable || is_head(refname)) { cb->unreachable_expire_kind = UE_HEAD; } else { commit = lookup_commit_reference_gently(the_repository, @@ -341,7 +448,7 @@ void reflog_expiry_prepare(const char *refname, cb->unreachable_expire_kind = commit ? UE_NORMAL : UE_ALWAYS; } - if (cb->cmd.expire_unreachable <= cb->cmd.expire_total) + if (cb->opts.expire_unreachable <= cb->opts.expire_total) cb->unreachable_expire_kind = UE_ALWAYS; switch (cb->unreachable_expire_kind) { @@ -358,7 +465,7 @@ void reflog_expiry_prepare(const char *refname, /* For reflog_expiry_cleanup() below */ cb->tip_commit = commit; } - cb->mark_limit = cb->cmd.expire_total; + cb->mark_limit = cb->opts.expire_total; mark_reachable(cb); } @@ -390,7 +497,7 @@ int count_reflog_ent(struct object_id *ooid UNUSED, timestamp_t timestamp, int tz UNUSED, const char *message UNUSED, void *cb_data) { - struct cmd_reflog_expire_cb *cb = cb_data; + struct reflog_expire_options *cb = cb_data; if (!cb->expire_total || timestamp < cb->expire_total) cb->recno++; return 0; @@ -398,7 +505,7 @@ int count_reflog_ent(struct object_id *ooid UNUSED, int reflog_delete(const char *rev, enum expire_reflog_flags flags, int verbose) { - struct cmd_reflog_expire_cb cmd = { 0 }; + struct reflog_expire_options opts = { 0 }; int status = 0; reflog_expiry_should_prune_fn *should_prune_fn = should_expire_reflog_ent; const char *spec = strstr(rev, "@{"); @@ -421,17 +528,17 @@ int reflog_delete(const char *rev, enum expire_reflog_flags flags, int verbose) recno = strtoul(spec + 2, &ep, 10); if (*ep == '}') { - cmd.recno = -recno; + opts.recno = -recno; refs_for_each_reflog_ent(get_main_ref_store(the_repository), - ref, count_reflog_ent, &cmd); + ref, count_reflog_ent, &opts); } else { - cmd.expire_total = approxidate(spec + 2); + opts.expire_total = approxidate(spec + 2); refs_for_each_reflog_ent(get_main_ref_store(the_repository), - ref, count_reflog_ent, &cmd); - cmd.expire_total = 0; + ref, count_reflog_ent, &opts); + opts.expire_total = 0; } - cb.cmd = cmd; + cb.opts = opts; status |= refs_reflog_expire(get_main_ref_store(the_repository), ref, flags, reflog_expiry_prepare, @@ -2,13 +2,44 @@ #define REFLOG_H #include "refs.h" -struct cmd_reflog_expire_cb { +#define REFLOG_EXPIRE_TOTAL (1 << 0) +#define REFLOG_EXPIRE_UNREACH (1 << 1) + +struct reflog_expire_entry_option { + struct reflog_expire_entry_option *next; + timestamp_t expire_total; + timestamp_t expire_unreachable; + char pattern[FLEX_ARRAY]; +}; + +struct reflog_expire_options { + struct reflog_expire_entry_option *entries, **entries_tail; int stalefix; int explicit_expiry; + timestamp_t default_expire_total; timestamp_t expire_total; + timestamp_t default_expire_unreachable; timestamp_t expire_unreachable; int recno; }; +#define REFLOG_EXPIRE_OPTIONS_INIT(now) { \ + .default_expire_total = now - 30 * 24 * 3600, \ + .default_expire_unreachable = now - 90 * 24 * 3600, \ +} + +/* + * Parse the reflog expire configuration. This should be used with + * `repo_config()`. + */ +int reflog_expire_config(const char *var, const char *value, + const struct config_context *ctx, void *cb); + +/* + * Adapt the options so that they apply to the given refname. This applies any + * per-reference reflog expiry configuration that may exist to the options. + */ +void reflog_expire_options_set_refname(struct reflog_expire_options *cb, + const char *refname); struct expire_reflog_policy_cb { enum { @@ -18,7 +49,7 @@ struct expire_reflog_policy_cb { } unreachable_expire_kind; struct commit_list *mark_list; unsigned long mark_limit; - struct cmd_reflog_expire_cb cmd; + struct reflog_expire_options opts; struct commit *tip_commit; struct commit_list *tips; unsigned int dry_run:1; diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh index 834ddb5ad6..9b82e11c10 100755 --- a/t/t7900-maintenance.sh +++ b/t/t7900-maintenance.sh @@ -475,6 +475,24 @@ test_expect_success 'pack-refs task' ' test_subcommand git pack-refs --all --prune <pack-refs.txt ' +test_expect_success 'reflog-expire task' ' + GIT_TRACE2_EVENT="$(pwd)/reflog-expire.txt" \ + git maintenance run --task=reflog-expire && + test_subcommand git reflog expire --all <reflog-expire.txt +' + +test_expect_success 'reflog-expire task --auto only packs when exceeding limits' ' + git reflog expire --all --expire=now && + test_commit reflog-one && + test_commit reflog-two && + GIT_TRACE2_EVENT="$(pwd)/reflog-expire-auto.txt" \ + git -c maintenance.reflog-expire.auto=3 maintenance run --auto --task=reflog-expire && + test_subcommand ! git reflog expire --all <reflog-expire-auto.txt && + GIT_TRACE2_EVENT="$(pwd)/reflog-expire-auto.txt" \ + git -c maintenance.reflog-expire.auto=2 maintenance run --auto --task=reflog-expire && + test_subcommand git reflog expire --all <reflog-expire-auto.txt +' + test_expect_success '--auto and --schedule incompatible' ' test_must_fail git maintenance run --auto --schedule=daily 2>err && test_grep "at most one" err |
