Merge branch 'kn/maintenance-is-needed'
"git maintenance" command learned "is-needed" subcommand to tell if it is necessary to perform various maintenance tasks. * kn/maintenance-is-needed: maintenance: add 'is-needed' subcommand maintenance: add checking logic in `pack_refs_condition()` refs: add a `optimize_required` field to `struct ref_storage_be` reftable/stack: add function to check if optimization is required reftable/stack: return stack segments directlymain
commit
c62d2d3810
|
|
@ -12,6 +12,7 @@ SYNOPSIS
|
|||
'git maintenance' run [<options>]
|
||||
'git maintenance' start [--scheduler=<scheduler>]
|
||||
'git maintenance' (stop|register|unregister) [<options>]
|
||||
'git maintenance' is-needed [<options>]
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
|
@ -84,6 +85,16 @@ The `unregister` subcommand will report an error if the current repository
|
|||
is not already registered. Use the `--force` option to return success even
|
||||
when the current repository is not registered.
|
||||
|
||||
is-needed::
|
||||
Check whether maintenance needs to be run without actually running it.
|
||||
Exits with a 0 status code if maintenance needs to be run, 1 otherwise.
|
||||
Ideally used with the '--auto' flag.
|
||||
+
|
||||
If one or more `--task` options are specified, then those tasks are checked
|
||||
in that order. Otherwise, the tasks are determined by which
|
||||
`maintenance.<task>.enabled` config options are true. By default, only
|
||||
`maintenance.gc.enabled` is true.
|
||||
|
||||
TASKS
|
||||
-----
|
||||
|
||||
|
|
@ -183,6 +194,8 @@ OPTIONS
|
|||
in the `gc.auto` config setting, or when the number of pack-files
|
||||
exceeds the `gc.autoPackLimit` config setting. Not compatible with
|
||||
the `--schedule` option.
|
||||
When combined with the `is-needed` subcommand, check if the required
|
||||
thresholds are met without actually running maintenance.
|
||||
|
||||
--schedule::
|
||||
When combined with the `run` subcommand, run maintenance tasks
|
||||
|
|
|
|||
93
builtin/gc.c
93
builtin/gc.c
|
|
@ -36,6 +36,7 @@
|
|||
#include "reflog.h"
|
||||
#include "repack.h"
|
||||
#include "rerere.h"
|
||||
#include "revision.h"
|
||||
#include "blob.h"
|
||||
#include "tree.h"
|
||||
#include "promisor-remote.h"
|
||||
|
|
@ -286,12 +287,26 @@ static void maintenance_run_opts_release(struct maintenance_run_opts *opts)
|
|||
|
||||
static int pack_refs_condition(UNUSED struct gc_config *cfg)
|
||||
{
|
||||
/*
|
||||
* The auto-repacking logic for refs is handled by the ref backends and
|
||||
* exposed via `git pack-refs --auto`. We thus always return truish
|
||||
* here and let the backend decide for us.
|
||||
*/
|
||||
return 1;
|
||||
struct string_list included_refs = STRING_LIST_INIT_NODUP;
|
||||
struct ref_exclusions excludes = REF_EXCLUSIONS_INIT;
|
||||
struct refs_optimize_opts optimize_opts = {
|
||||
.exclusions = &excludes,
|
||||
.includes = &included_refs,
|
||||
.flags = REFS_OPTIMIZE_PRUNE | REFS_OPTIMIZE_AUTO,
|
||||
};
|
||||
bool required;
|
||||
|
||||
/* Check for all refs, similar to 'git refs optimize --all'. */
|
||||
string_list_append(optimize_opts.includes, "*");
|
||||
|
||||
if (refs_optimize_required(get_main_ref_store(the_repository),
|
||||
&optimize_opts, &required))
|
||||
return 0;
|
||||
|
||||
clear_ref_exclusions(&excludes);
|
||||
string_list_clear(&included_refs, 0);
|
||||
|
||||
return required;
|
||||
}
|
||||
|
||||
static int maintenance_task_pack_refs(struct maintenance_run_opts *opts,
|
||||
|
|
@ -1095,9 +1110,6 @@ static int maintenance_opt_schedule(const struct option *opt, const char *arg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Remember to update object flag allocation in object.h */
|
||||
#define SEEN (1u<<0)
|
||||
|
||||
struct cg_auto_data {
|
||||
int num_not_in_graph;
|
||||
int limit;
|
||||
|
|
@ -3444,7 +3456,67 @@ static int maintenance_stop(int argc, const char **argv, const char *prefix,
|
|||
return update_background_schedule(NULL, 0);
|
||||
}
|
||||
|
||||
static const char * const builtin_maintenance_usage[] = {
|
||||
static const char *const builtin_maintenance_is_needed_usage[] = {
|
||||
"git maintenance is-needed [--task=<task>] [--schedule]",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int maintenance_is_needed(int argc, const char **argv, const char *prefix,
|
||||
struct repository *repo UNUSED)
|
||||
{
|
||||
struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT;
|
||||
struct string_list selected_tasks = STRING_LIST_INIT_DUP;
|
||||
struct gc_config cfg = GC_CONFIG_INIT;
|
||||
struct option options[] = {
|
||||
OPT_BOOL(0, "auto", &opts.auto_flag,
|
||||
N_("run tasks based on the state of the repository")),
|
||||
OPT_CALLBACK_F(0, "task", &selected_tasks, N_("task"),
|
||||
N_("check a specific task"),
|
||||
PARSE_OPT_NONEG, task_option_parse),
|
||||
OPT_END()
|
||||
};
|
||||
bool is_needed = false;
|
||||
|
||||
argc = parse_options(argc, argv, prefix, options,
|
||||
builtin_maintenance_is_needed_usage,
|
||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||
if (argc)
|
||||
usage_with_options(builtin_maintenance_is_needed_usage, options);
|
||||
|
||||
gc_config(&cfg);
|
||||
initialize_task_config(&opts, &selected_tasks);
|
||||
|
||||
if (opts.auto_flag) {
|
||||
for (size_t i = 0; i < opts.tasks_nr; i++) {
|
||||
if (tasks[opts.tasks[i]].auto_condition &&
|
||||
tasks[opts.tasks[i]].auto_condition(&cfg)) {
|
||||
is_needed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* When not using --auto we always require maintenance right now.
|
||||
*
|
||||
* TODO: this certainly is too eager, as some maintenance tasks may
|
||||
* decide to not do anything because the data structures are already
|
||||
* fully optimized. We may eventually want to extend the auto
|
||||
* condition to also cover non-auto runs so that we can detect such
|
||||
* cases.
|
||||
*/
|
||||
is_needed = true;
|
||||
}
|
||||
|
||||
string_list_clear(&selected_tasks, 0);
|
||||
maintenance_run_opts_release(&opts);
|
||||
gc_config_release(&cfg);
|
||||
|
||||
if (is_needed)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char *const builtin_maintenance_usage[] = {
|
||||
N_("git maintenance <subcommand> [<options>]"),
|
||||
NULL,
|
||||
};
|
||||
|
|
@ -3461,6 +3533,7 @@ int cmd_maintenance(int argc,
|
|||
OPT_SUBCOMMAND("stop", &fn, maintenance_stop),
|
||||
OPT_SUBCOMMAND("register", &fn, maintenance_register),
|
||||
OPT_SUBCOMMAND("unregister", &fn, maintenance_unregister),
|
||||
OPT_SUBCOMMAND("is-needed", &fn, maintenance_is_needed),
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
|
|
|
|||
1
object.h
1
object.h
|
|
@ -80,7 +80,6 @@ void object_array_init(struct object_array *array);
|
|||
* list-objects-filter.c: 21
|
||||
* bloom.c: 2122
|
||||
* builtin/fsck.c: 0--3
|
||||
* builtin/gc.c: 0
|
||||
* builtin/index-pack.c: 2021
|
||||
* reflog.c: 10--12
|
||||
* builtin/show-branch.c: 0-------------------------------------------26
|
||||
|
|
|
|||
7
refs.c
7
refs.c
|
|
@ -2318,6 +2318,13 @@ int refs_optimize(struct ref_store *refs, struct refs_optimize_opts *opts)
|
|||
return refs->be->optimize(refs, opts);
|
||||
}
|
||||
|
||||
int refs_optimize_required(struct ref_store *refs,
|
||||
struct refs_optimize_opts *opts,
|
||||
bool *required)
|
||||
{
|
||||
return refs->be->optimize_required(refs, opts, required);
|
||||
}
|
||||
|
||||
int reference_get_peeled_oid(struct repository *repo,
|
||||
const struct reference *ref,
|
||||
struct object_id *peeled_oid)
|
||||
|
|
|
|||
7
refs.h
7
refs.h
|
|
@ -520,6 +520,13 @@ struct refs_optimize_opts {
|
|||
*/
|
||||
int refs_optimize(struct ref_store *refs, struct refs_optimize_opts *opts);
|
||||
|
||||
/*
|
||||
* Check if refs backend can be optimized by calling 'refs_optimize'.
|
||||
*/
|
||||
int refs_optimize_required(struct ref_store *ref_store,
|
||||
struct refs_optimize_opts *opts,
|
||||
bool *required);
|
||||
|
||||
/*
|
||||
* Setup reflog before using. Fill in err and return -1 on failure.
|
||||
*/
|
||||
|
|
|
|||
13
refs/debug.c
13
refs/debug.c
|
|
@ -132,6 +132,17 @@ static int debug_optimize(struct ref_store *ref_store, struct refs_optimize_opts
|
|||
return res;
|
||||
}
|
||||
|
||||
static int debug_optimize_required(struct ref_store *ref_store,
|
||||
struct refs_optimize_opts *opts,
|
||||
bool *required)
|
||||
{
|
||||
struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
|
||||
int res = drefs->refs->be->optimize_required(drefs->refs, opts, required);
|
||||
trace_printf_key(&trace_refs, "optimize_required: %s, res: %d\n",
|
||||
required ? "yes" : "no", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int debug_rename_ref(struct ref_store *ref_store, const char *oldref,
|
||||
const char *newref, const char *logmsg)
|
||||
{
|
||||
|
|
@ -440,6 +451,8 @@ struct ref_storage_be refs_be_debug = {
|
|||
.transaction_abort = debug_transaction_abort,
|
||||
|
||||
.optimize = debug_optimize,
|
||||
.optimize_required = debug_optimize_required,
|
||||
|
||||
.rename_ref = debug_rename_ref,
|
||||
.copy_ref = debug_copy_ref,
|
||||
|
||||
|
|
|
|||
|
|
@ -1512,6 +1512,16 @@ static int files_optimize(struct ref_store *ref_store,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int files_optimize_required(struct ref_store *ref_store,
|
||||
struct refs_optimize_opts *opts,
|
||||
bool *required)
|
||||
{
|
||||
struct files_ref_store *refs = files_downcast(ref_store, REF_STORE_READ,
|
||||
"optimize_required");
|
||||
*required = should_pack_refs(refs, opts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* People using contrib's git-new-workdir have .git/logs/refs ->
|
||||
* /some/other/path/.git/logs/refs, and that may live on another device.
|
||||
|
|
@ -3982,6 +3992,7 @@ struct ref_storage_be refs_be_files = {
|
|||
.transaction_abort = files_transaction_abort,
|
||||
|
||||
.optimize = files_optimize,
|
||||
.optimize_required = files_optimize_required,
|
||||
.rename_ref = files_rename_ref,
|
||||
.copy_ref = files_copy_ref,
|
||||
|
||||
|
|
|
|||
|
|
@ -1784,6 +1784,17 @@ static int packed_optimize(struct ref_store *ref_store UNUSED,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int packed_optimize_required(struct ref_store *ref_store UNUSED,
|
||||
struct refs_optimize_opts *opts UNUSED,
|
||||
bool *required)
|
||||
{
|
||||
/*
|
||||
* Packed refs are already optimized.
|
||||
*/
|
||||
*required = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_store UNUSED)
|
||||
{
|
||||
return empty_ref_iterator_begin();
|
||||
|
|
@ -2130,6 +2141,8 @@ struct ref_storage_be refs_be_packed = {
|
|||
.transaction_abort = packed_transaction_abort,
|
||||
|
||||
.optimize = packed_optimize,
|
||||
.optimize_required = packed_optimize_required,
|
||||
|
||||
.rename_ref = NULL,
|
||||
.copy_ref = NULL,
|
||||
|
||||
|
|
|
|||
|
|
@ -424,6 +424,11 @@ typedef int ref_transaction_commit_fn(struct ref_store *refs,
|
|||
|
||||
typedef int optimize_fn(struct ref_store *ref_store,
|
||||
struct refs_optimize_opts *opts);
|
||||
|
||||
typedef int optimize_required_fn(struct ref_store *ref_store,
|
||||
struct refs_optimize_opts *opts,
|
||||
bool *required);
|
||||
|
||||
typedef int rename_ref_fn(struct ref_store *ref_store,
|
||||
const char *oldref, const char *newref,
|
||||
const char *logmsg);
|
||||
|
|
@ -549,6 +554,7 @@ struct ref_storage_be {
|
|||
ref_transaction_abort_fn *transaction_abort;
|
||||
|
||||
optimize_fn *optimize;
|
||||
optimize_required_fn *optimize_required;
|
||||
rename_ref_fn *rename_ref;
|
||||
copy_ref_fn *copy_ref;
|
||||
|
||||
|
|
|
|||
|
|
@ -1733,6 +1733,29 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int reftable_be_optimize_required(struct ref_store *ref_store,
|
||||
struct refs_optimize_opts *opts,
|
||||
bool *required)
|
||||
{
|
||||
struct reftable_ref_store *refs = reftable_be_downcast(ref_store, REF_STORE_READ,
|
||||
"optimize_refs_required");
|
||||
struct reftable_stack *stack;
|
||||
bool use_heuristics = false;
|
||||
|
||||
if (refs->err)
|
||||
return refs->err;
|
||||
|
||||
stack = refs->worktree_backend.stack;
|
||||
if (!stack)
|
||||
stack = refs->main_backend.stack;
|
||||
|
||||
if (opts->flags & REFS_OPTIMIZE_AUTO)
|
||||
use_heuristics = true;
|
||||
|
||||
return reftable_stack_compaction_required(stack, use_heuristics,
|
||||
required);
|
||||
}
|
||||
|
||||
struct write_create_symref_arg {
|
||||
struct reftable_ref_store *refs;
|
||||
struct reftable_stack *stack;
|
||||
|
|
@ -2756,6 +2779,8 @@ struct ref_storage_be refs_be_reftable = {
|
|||
.transaction_abort = reftable_be_transaction_abort,
|
||||
|
||||
.optimize = reftable_be_optimize,
|
||||
.optimize_required = reftable_be_optimize_required,
|
||||
|
||||
.rename_ref = reftable_be_rename_ref,
|
||||
.copy_ref = reftable_be_copy_ref,
|
||||
|
||||
|
|
|
|||
|
|
@ -123,6 +123,17 @@ struct reftable_log_expiry_config {
|
|||
int reftable_stack_compact_all(struct reftable_stack *st,
|
||||
struct reftable_log_expiry_config *config);
|
||||
|
||||
/*
|
||||
* Check if compaction is required.
|
||||
*
|
||||
* When `use_heuristics` is false, check if all tables can be compacted to a
|
||||
* single table. If true, use heuristics to determine if the tables need to be
|
||||
* compacted to maintain geometric progression.
|
||||
*/
|
||||
int reftable_stack_compaction_required(struct reftable_stack *st,
|
||||
bool use_heuristics,
|
||||
bool *required);
|
||||
|
||||
/* heuristically compact unbalanced table stack. */
|
||||
int reftable_stack_auto_compact(struct reftable_stack *st);
|
||||
|
||||
|
|
|
|||
|
|
@ -1626,7 +1626,8 @@ struct segment suggest_compaction_segment(uint64_t *sizes, size_t n,
|
|||
return seg;
|
||||
}
|
||||
|
||||
static uint64_t *stack_table_sizes_for_compaction(struct reftable_stack *st)
|
||||
static int stack_segments_for_compaction(struct reftable_stack *st,
|
||||
struct segment *seg)
|
||||
{
|
||||
int version = (st->opts.hash_id == REFTABLE_HASH_SHA1) ? 1 : 2;
|
||||
int overhead = header_size(version) - 1;
|
||||
|
|
@ -1634,31 +1635,63 @@ static uint64_t *stack_table_sizes_for_compaction(struct reftable_stack *st)
|
|||
|
||||
REFTABLE_CALLOC_ARRAY(sizes, st->merged->tables_len);
|
||||
if (!sizes)
|
||||
return NULL;
|
||||
return REFTABLE_OUT_OF_MEMORY_ERROR;
|
||||
|
||||
for (size_t i = 0; i < st->merged->tables_len; i++)
|
||||
sizes[i] = st->tables[i]->size - overhead;
|
||||
|
||||
return sizes;
|
||||
*seg = suggest_compaction_segment(sizes, st->merged->tables_len,
|
||||
st->opts.auto_compaction_factor);
|
||||
reftable_free(sizes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int update_segment_if_compaction_required(struct reftable_stack *st,
|
||||
struct segment *seg,
|
||||
bool use_geometric,
|
||||
bool *required)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (st->merged->tables_len < 2) {
|
||||
*required = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!use_geometric) {
|
||||
*required = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = stack_segments_for_compaction(st, seg);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*required = segment_size(seg) > 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reftable_stack_compaction_required(struct reftable_stack *st,
|
||||
bool use_heuristics,
|
||||
bool *required)
|
||||
{
|
||||
struct segment seg;
|
||||
return update_segment_if_compaction_required(st, &seg, use_heuristics,
|
||||
required);
|
||||
}
|
||||
|
||||
int reftable_stack_auto_compact(struct reftable_stack *st)
|
||||
{
|
||||
struct segment seg;
|
||||
uint64_t *sizes;
|
||||
bool required;
|
||||
int err;
|
||||
|
||||
if (st->merged->tables_len < 2)
|
||||
return 0;
|
||||
err = update_segment_if_compaction_required(st, &seg, true, &required);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
sizes = stack_table_sizes_for_compaction(st);
|
||||
if (!sizes)
|
||||
return REFTABLE_OUT_OF_MEMORY_ERROR;
|
||||
|
||||
seg = suggest_compaction_segment(sizes, st->merged->tables_len,
|
||||
st->opts.auto_compaction_factor);
|
||||
reftable_free(sizes);
|
||||
|
||||
if (segment_size(&seg) > 0)
|
||||
if (required)
|
||||
return stack_compact_range(st, seg.start, seg.end - 1,
|
||||
NULL, STACK_COMPACT_RANGE_BEST_EFFORT);
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,9 @@ test_expect_success 'run [--auto|--quiet]' '
|
|||
git maintenance run --auto 2>/dev/null &&
|
||||
GIT_TRACE2_EVENT="$(pwd)/run-no-quiet.txt" \
|
||||
git maintenance run --no-quiet 2>/dev/null &&
|
||||
git maintenance is-needed &&
|
||||
test_subcommand git gc --quiet --no-detach --skip-foreground-tasks <run-no-auto.txt &&
|
||||
! git maintenance is-needed --auto &&
|
||||
test_subcommand ! git gc --auto --quiet --no-detach --skip-foreground-tasks <run-auto.txt &&
|
||||
test_subcommand git gc --no-quiet --no-detach --skip-foreground-tasks <run-no-quiet.txt
|
||||
'
|
||||
|
|
@ -180,6 +182,11 @@ test_expect_success 'commit-graph auto condition' '
|
|||
|
||||
test_commit first &&
|
||||
|
||||
! git -c maintenance.commit-graph.auto=0 \
|
||||
maintenance is-needed --auto --task=commit-graph &&
|
||||
git -c maintenance.commit-graph.auto=1 \
|
||||
maintenance is-needed --auto --task=commit-graph &&
|
||||
|
||||
GIT_TRACE2_EVENT="$(pwd)/cg-zero-means-no.txt" \
|
||||
git -c maintenance.commit-graph.auto=0 $COMMAND &&
|
||||
GIT_TRACE2_EVENT="$(pwd)/cg-one-satisfied.txt" \
|
||||
|
|
@ -290,16 +297,23 @@ test_expect_success 'maintenance.loose-objects.auto' '
|
|||
git -c maintenance.loose-objects.auto=1 maintenance \
|
||||
run --auto --task=loose-objects 2>/dev/null &&
|
||||
test_subcommand ! git prune-packed --quiet <trace-lo1.txt &&
|
||||
|
||||
printf data-A | git hash-object -t blob --stdin -w &&
|
||||
! git -c maintenance.loose-objects.auto=2 \
|
||||
maintenance is-needed --auto --task=loose-objects &&
|
||||
GIT_TRACE2_EVENT="$(pwd)/trace-loA" \
|
||||
git -c maintenance.loose-objects.auto=2 \
|
||||
maintenance run --auto --task=loose-objects 2>/dev/null &&
|
||||
test_subcommand ! git prune-packed --quiet <trace-loA &&
|
||||
|
||||
printf data-B | git hash-object -t blob --stdin -w &&
|
||||
git -c maintenance.loose-objects.auto=2 \
|
||||
maintenance is-needed --auto --task=loose-objects &&
|
||||
GIT_TRACE2_EVENT="$(pwd)/trace-loB" \
|
||||
git -c maintenance.loose-objects.auto=2 \
|
||||
maintenance run --auto --task=loose-objects 2>/dev/null &&
|
||||
test_subcommand git prune-packed --quiet <trace-loB &&
|
||||
|
||||
GIT_TRACE2_EVENT="$(pwd)/trace-loC" \
|
||||
git -c maintenance.loose-objects.auto=2 \
|
||||
maintenance run --auto --task=loose-objects 2>/dev/null &&
|
||||
|
|
@ -421,10 +435,13 @@ run_incremental_repack_and_verify () {
|
|||
test_commit A &&
|
||||
git repack -adk &&
|
||||
git multi-pack-index write &&
|
||||
! git -c maintenance.incremental-repack.auto=1 \
|
||||
maintenance is-needed --auto --task=incremental-repack &&
|
||||
GIT_TRACE2_EVENT="$(pwd)/midx-init.txt" git \
|
||||
-c maintenance.incremental-repack.auto=1 \
|
||||
maintenance run --auto --task=incremental-repack 2>/dev/null &&
|
||||
test_subcommand ! git multi-pack-index write --no-progress <midx-init.txt &&
|
||||
|
||||
test_commit B &&
|
||||
git pack-objects --revs .git/objects/pack/pack <<-\EOF &&
|
||||
HEAD
|
||||
|
|
@ -434,11 +451,14 @@ run_incremental_repack_and_verify () {
|
|||
-c maintenance.incremental-repack.auto=2 \
|
||||
maintenance run --auto --task=incremental-repack 2>/dev/null &&
|
||||
test_subcommand ! git multi-pack-index write --no-progress <trace-A &&
|
||||
|
||||
test_commit C &&
|
||||
git pack-objects --revs .git/objects/pack/pack <<-\EOF &&
|
||||
HEAD
|
||||
^HEAD~1
|
||||
EOF
|
||||
git -c maintenance.incremental-repack.auto=2 \
|
||||
maintenance is-needed --auto --task=incremental-repack &&
|
||||
GIT_TRACE2_EVENT=$(pwd)/trace-B git \
|
||||
-c maintenance.incremental-repack.auto=2 \
|
||||
maintenance run --auto --task=incremental-repack 2>/dev/null &&
|
||||
|
|
@ -655,9 +675,15 @@ 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 -c maintenance.reflog-expire.auto=3 \
|
||||
maintenance is-needed --auto --task=reflog-expire &&
|
||||
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 -c maintenance.reflog-expire.auto=2 \
|
||||
maintenance is-needed --auto --task=reflog-expire &&
|
||||
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
|
||||
|
|
@ -684,6 +710,7 @@ test_expect_success 'worktree-prune task --auto only prunes with prunable worktr
|
|||
test_expect_worktree_prune ! git maintenance run --auto --task=worktree-prune &&
|
||||
mkdir .git/worktrees &&
|
||||
: >.git/worktrees/abc &&
|
||||
git maintenance is-needed --auto --task=worktree-prune &&
|
||||
test_expect_worktree_prune git maintenance run --auto --task=worktree-prune
|
||||
'
|
||||
|
||||
|
|
@ -700,22 +727,7 @@ test_expect_success 'worktree-prune task with --auto honors maintenance.worktree
|
|||
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 &&
|
||||
git -c maintenance.worktree-prune.auto=3 maintenance is-needed --auto --task=worktree-prune &&
|
||||
test_expect_worktree_prune git -c maintenance.worktree-prune.auto=3 maintenance run --auto --task=worktree-prune
|
||||
'
|
||||
|
||||
|
|
@ -724,11 +736,13 @@ test_expect_success 'worktree-prune task honors gc.worktreePruneExpire' '
|
|||
rm -rf worktree &&
|
||||
|
||||
rm -f worktree-prune.txt &&
|
||||
! git -c gc.worktreePruneExpire=1.week.ago maintenance is-needed --auto --task=worktree-prune &&
|
||||
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 -c gc.worktreePruneExpire=now maintenance is-needed --auto --task=worktree-prune &&
|
||||
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
|
||||
|
|
@ -753,10 +767,13 @@ test_expect_success 'rerere-gc task without --auto always collects garbage' '
|
|||
|
||||
test_expect_success 'rerere-gc task with --auto only prunes with prunable entries' '
|
||||
test_when_finished "rm -rf .git/rr-cache" &&
|
||||
! git maintenance is-needed --auto --task=rerere-gc &&
|
||||
test_expect_rerere_gc ! git maintenance run --auto --task=rerere-gc &&
|
||||
mkdir .git/rr-cache &&
|
||||
! git maintenance is-needed --auto --task=rerere-gc &&
|
||||
test_expect_rerere_gc ! git maintenance run --auto --task=rerere-gc &&
|
||||
: >.git/rr-cache/entry &&
|
||||
git maintenance is-needed --auto --task=rerere-gc &&
|
||||
test_expect_rerere_gc git maintenance run --auto --task=rerere-gc
|
||||
'
|
||||
|
||||
|
|
@ -764,17 +781,22 @@ test_expect_success 'rerere-gc task with --auto honors maintenance.rerere-gc.aut
|
|||
test_when_finished "rm -rf .git/rr-cache" &&
|
||||
|
||||
# A negative value should always prune.
|
||||
git -c maintenance.rerere-gc.auto=-1 maintenance is-needed --auto --task=rerere-gc &&
|
||||
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.
|
||||
! git -c maintenance.rerere-gc.auto=9000 maintenance is-needed --auto --task=rerere-gc &&
|
||||
test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=9000 maintenance run --auto --task=rerere-gc &&
|
||||
mkdir .git/rr-cache &&
|
||||
! git -c maintenance.rerere-gc.auto=9000 maintenance is-needed --auto --task=rerere-gc &&
|
||||
test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=9000 maintenance run --auto --task=rerere-gc &&
|
||||
: >.git/rr-cache/entry-1 &&
|
||||
git -c maintenance.rerere-gc.auto=9000 maintenance is-needed --auto --task=rerere-gc &&
|
||||
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 &&
|
||||
! git -c maintenance.rerere-gc.auto=0 maintenance is-needed --auto --task=rerere-gc &&
|
||||
test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=0 maintenance run --auto --task=rerere-gc
|
||||
'
|
||||
|
||||
|
|
|
|||
|
|
@ -1067,6 +1067,7 @@ void test_reftable_stack__add_performs_auto_compaction(void)
|
|||
.value_type = REFTABLE_REF_SYMREF,
|
||||
.value.symref = (char *) "master",
|
||||
};
|
||||
bool required = false;
|
||||
char buf[128];
|
||||
|
||||
/*
|
||||
|
|
@ -1087,10 +1088,17 @@ void test_reftable_stack__add_performs_auto_compaction(void)
|
|||
* auto compaction is disabled. When enabled, we should merge
|
||||
* all tables in the stack.
|
||||
*/
|
||||
if (i != n)
|
||||
cl_assert_equal_i(reftable_stack_compaction_required(st, true, &required), 0);
|
||||
if (i != n) {
|
||||
cl_assert_equal_i(st->merged->tables_len, i + 1);
|
||||
else
|
||||
if (i < 1)
|
||||
cl_assert_equal_b(required, false);
|
||||
else
|
||||
cl_assert_equal_b(required, true);
|
||||
} else {
|
||||
cl_assert_equal_i(st->merged->tables_len, 1);
|
||||
cl_assert_equal_b(required, false);
|
||||
}
|
||||
}
|
||||
|
||||
reftable_stack_destroy(st);
|
||||
|
|
|
|||
Loading…
Reference in New Issue