зеркало из https://github.com/microsoft/git.git
maintenance: add --schedule option and config
Maintenance currently triggers when certain data-size thresholds are met, such as number of pack-files or loose objects. Users may want to run certain maintenance tasks based on frequency instead. For example, a user may want to perform a 'prefetch' task every hour, or 'gc' task every day. To help these users, update the 'git maintenance run' command to include a '--schedule=<frequency>' option. The allowed frequencies are 'hourly', 'daily', and 'weekly'. These values are also allowed in a new config value 'maintenance.<task>.schedule'. The 'git maintenance run --schedule=<frequency>' checks the '*.schedule' config value for each enabled task to see if the configured frequency is at least as frequent as the frequency from the '--schedule' argument. We use the following order, for full clarity: 'hourly' > 'daily' > 'weekly' Use new 'enum schedule_priority' to track these values numerically. The following cron table would run the scheduled tasks with the correct frequencies: 0 1-23 * * * git -C <repo> maintenance run --schedule=hourly 0 0 * * 1-6 git -C <repo> maintenance run --schedule=daily 0 0 * * 0 git -C <repo> maintenance run --schedule=weekly This cron schedule will run --schedule=hourly every hour except at midnight. This avoids a concurrent run with the --schedule=daily that runs at midnight every day except the first day of the week. This avoids a concurrent run with the --schedule=weekly that runs at midnight on the first day of the week. Since --schedule=daily also runs the 'hourly' tasks and --schedule=weekly runs the 'hourly' and 'daily' tasks, we will still see all tasks run with the proper frequencies. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
1942d48380
Коммит
b08ff1fee0
|
@ -10,6 +10,11 @@ maintenance.<task>.enabled::
|
|||
`--task` option exists. By default, only `maintenance.gc.enabled`
|
||||
is true.
|
||||
|
||||
maintenance.<task>.schedule::
|
||||
This config option controls whether or not the given `<task>` runs
|
||||
during a `git maintenance run --schedule=<frequency>` command. The
|
||||
value must be one of "hourly", "daily", or "weekly".
|
||||
|
||||
maintenance.commit-graph.auto::
|
||||
This integer config option controls how often the `commit-graph` task
|
||||
should be run as part of `git maintenance run --auto`. If zero, then
|
||||
|
|
|
@ -110,7 +110,18 @@ OPTIONS
|
|||
only if certain thresholds are met. For example, the `gc` task
|
||||
runs when the number of loose objects exceeds the number stored
|
||||
in the `gc.auto` config setting, or when the number of pack-files
|
||||
exceeds the `gc.autoPackLimit` config setting.
|
||||
exceeds the `gc.autoPackLimit` config setting. Not compatible with
|
||||
the `--schedule` option.
|
||||
|
||||
--schedule::
|
||||
When combined with the `run` subcommand, run maintenance tasks
|
||||
only if certain time conditions are met, as specified by the
|
||||
`maintenance.<task>.schedule` config value for each `<task>`.
|
||||
This config value specifies a number of seconds since the last
|
||||
time that task ran, according to the `maintenance.<task>.lastRun`
|
||||
config value. The tasks that are tested are those provided by
|
||||
the `--task=<task>` option(s) or those with
|
||||
`maintenance.<task>.enabled` set to true.
|
||||
|
||||
--quiet::
|
||||
Do not report progress or other information over `stderr`.
|
||||
|
|
64
builtin/gc.c
64
builtin/gc.c
|
@ -703,14 +703,51 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const char * const builtin_maintenance_run_usage[] = {
|
||||
N_("git maintenance run [--auto] [--[no-]quiet] [--task=<task>]"),
|
||||
static const char *const builtin_maintenance_run_usage[] = {
|
||||
N_("git maintenance run [--auto] [--[no-]quiet] [--task=<task>] [--schedule]"),
|
||||
NULL
|
||||
};
|
||||
|
||||
enum schedule_priority {
|
||||
SCHEDULE_NONE = 0,
|
||||
SCHEDULE_WEEKLY = 1,
|
||||
SCHEDULE_DAILY = 2,
|
||||
SCHEDULE_HOURLY = 3,
|
||||
};
|
||||
|
||||
static enum schedule_priority parse_schedule(const char *value)
|
||||
{
|
||||
if (!value)
|
||||
return SCHEDULE_NONE;
|
||||
if (!strcasecmp(value, "hourly"))
|
||||
return SCHEDULE_HOURLY;
|
||||
if (!strcasecmp(value, "daily"))
|
||||
return SCHEDULE_DAILY;
|
||||
if (!strcasecmp(value, "weekly"))
|
||||
return SCHEDULE_WEEKLY;
|
||||
return SCHEDULE_NONE;
|
||||
}
|
||||
|
||||
static int maintenance_opt_schedule(const struct option *opt, const char *arg,
|
||||
int unset)
|
||||
{
|
||||
enum schedule_priority *priority = opt->value;
|
||||
|
||||
if (unset)
|
||||
die(_("--no-schedule is not allowed"));
|
||||
|
||||
*priority = parse_schedule(arg);
|
||||
|
||||
if (!*priority)
|
||||
die(_("unrecognized --schedule argument '%s'"), arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct maintenance_run_opts {
|
||||
int auto_flag;
|
||||
int quiet;
|
||||
enum schedule_priority schedule;
|
||||
};
|
||||
|
||||
/* Remember to update object flag allocation in object.h */
|
||||
|
@ -1158,6 +1195,8 @@ struct maintenance_task {
|
|||
maintenance_auto_fn *auto_condition;
|
||||
unsigned enabled:1;
|
||||
|
||||
enum schedule_priority schedule;
|
||||
|
||||
/* -1 if not selected. */
|
||||
int selected_order;
|
||||
};
|
||||
|
@ -1253,6 +1292,9 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts)
|
|||
!tasks[i].auto_condition()))
|
||||
continue;
|
||||
|
||||
if (opts->schedule && tasks[i].schedule < opts->schedule)
|
||||
continue;
|
||||
|
||||
trace2_region_enter("maintenance", tasks[i].name, r);
|
||||
if (tasks[i].fn(opts)) {
|
||||
error(_("task '%s' failed"), tasks[i].name);
|
||||
|
@ -1273,13 +1315,23 @@ static void initialize_task_config(void)
|
|||
|
||||
for (i = 0; i < TASK__COUNT; i++) {
|
||||
int config_value;
|
||||
char *config_str;
|
||||
|
||||
strbuf_setlen(&config_name, 0);
|
||||
strbuf_reset(&config_name);
|
||||
strbuf_addf(&config_name, "maintenance.%s.enabled",
|
||||
tasks[i].name);
|
||||
|
||||
if (!git_config_get_bool(config_name.buf, &config_value))
|
||||
tasks[i].enabled = config_value;
|
||||
|
||||
strbuf_reset(&config_name);
|
||||
strbuf_addf(&config_name, "maintenance.%s.schedule",
|
||||
tasks[i].name);
|
||||
|
||||
if (!git_config_get_string(config_name.buf, &config_str)) {
|
||||
tasks[i].schedule = parse_schedule(config_str);
|
||||
free(config_str);
|
||||
}
|
||||
}
|
||||
|
||||
strbuf_release(&config_name);
|
||||
|
@ -1323,6 +1375,9 @@ static int maintenance_run(int argc, const char **argv, const char *prefix)
|
|||
struct option builtin_maintenance_run_options[] = {
|
||||
OPT_BOOL(0, "auto", &opts.auto_flag,
|
||||
N_("run tasks based on the state of the repository")),
|
||||
OPT_CALLBACK(0, "schedule", &opts.schedule, N_("frequency"),
|
||||
N_("run tasks based on frequency"),
|
||||
maintenance_opt_schedule),
|
||||
OPT_BOOL(0, "quiet", &opts.quiet,
|
||||
N_("do not report progress or other information over stderr")),
|
||||
OPT_CALLBACK_F(0, "task", NULL, N_("task"),
|
||||
|
@ -1343,6 +1398,9 @@ static int maintenance_run(int argc, const char **argv, const char *prefix)
|
|||
builtin_maintenance_run_usage,
|
||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||
|
||||
if (opts.auto_flag && opts.schedule)
|
||||
die(_("use at most one of --auto and --schedule=<frequency>"));
|
||||
|
||||
if (argc != 0)
|
||||
usage_with_options(builtin_maintenance_run_usage,
|
||||
builtin_maintenance_run_options);
|
||||
|
|
|
@ -260,4 +260,44 @@ test_expect_success 'maintenance.incremental-repack.auto' '
|
|||
test_subcommand git multi-pack-index write --no-progress <trace-B
|
||||
'
|
||||
|
||||
test_expect_success '--auto and --schedule incompatible' '
|
||||
test_must_fail git maintenance run --auto --schedule=daily 2>err &&
|
||||
test_i18ngrep "at most one" err
|
||||
'
|
||||
|
||||
test_expect_success 'invalid --schedule value' '
|
||||
test_must_fail git maintenance run --schedule=annually 2>err &&
|
||||
test_i18ngrep "unrecognized --schedule" err
|
||||
'
|
||||
|
||||
test_expect_success '--schedule inheritance weekly -> daily -> hourly' '
|
||||
git config maintenance.loose-objects.enabled true &&
|
||||
git config maintenance.loose-objects.schedule hourly &&
|
||||
git config maintenance.commit-graph.enabled true &&
|
||||
git config maintenance.commit-graph.schedule daily &&
|
||||
git config maintenance.incremental-repack.enabled true &&
|
||||
git config maintenance.incremental-repack.schedule weekly &&
|
||||
|
||||
GIT_TRACE2_EVENT="$(pwd)/hourly.txt" \
|
||||
git maintenance run --schedule=hourly 2>/dev/null &&
|
||||
test_subcommand git prune-packed --quiet <hourly.txt &&
|
||||
test_subcommand ! git commit-graph write --split --reachable \
|
||||
--no-progress <hourly.txt &&
|
||||
test_subcommand ! git multi-pack-index write --no-progress <hourly.txt &&
|
||||
|
||||
GIT_TRACE2_EVENT="$(pwd)/daily.txt" \
|
||||
git maintenance run --schedule=daily 2>/dev/null &&
|
||||
test_subcommand git prune-packed --quiet <daily.txt &&
|
||||
test_subcommand git commit-graph write --split --reachable \
|
||||
--no-progress <daily.txt &&
|
||||
test_subcommand ! git multi-pack-index write --no-progress <daily.txt &&
|
||||
|
||||
GIT_TRACE2_EVENT="$(pwd)/weekly.txt" \
|
||||
git maintenance run --schedule=weekly 2>/dev/null &&
|
||||
test_subcommand git prune-packed --quiet <weekly.txt &&
|
||||
test_subcommand git commit-graph write --split --reachable \
|
||||
--no-progress <weekly.txt &&
|
||||
test_subcommand git multi-pack-index write --no-progress <weekly.txt
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
Загрузка…
Ссылка в новой задаче