@@ -30,7 +30,9 @@ SUBCOMMANDS
-----------
run::
- Run one or more maintenance tasks.
+ Run one or more maintenance tasks. If one or more `--task=<task>`
+ options are specified, then those tasks are run in the provided
+ order. Otherwise, only the `gc` task is run.
TASKS
-----
@@ -73,6 +75,10 @@ OPTIONS
--quiet::
Do not report progress or other information over `stderr`.
+--task=<task>::
+ If this option is specified one or more times, then only run the
+ specified tasks in the specified order.
+
GIT
---
Part of the linkgit:git[1] suite
@@ -791,7 +791,9 @@ typedef int maintenance_task_fn(struct maintenance_opts *opts);
struct maintenance_task {
const char *name;
maintenance_task_fn *fn;
- unsigned enabled:1;
+ unsigned enabled:1,
+ selected:1;
+ int selected_order;
};
enum maintenance_task_label {
@@ -814,13 +816,32 @@ static struct maintenance_task tasks[] = {
},
};
+static int compare_tasks_by_selection(const void *a_, const void *b_)
+{
+ const struct maintenance_task *a, *b;
+
+ a = (const struct maintenance_task *)&a_;
+ b = (const struct maintenance_task *)&b_;
+
+ return b->selected_order - a->selected_order;
+}
+
static int maintenance_run(struct maintenance_opts *opts)
{
- int i;
+ int i, found_selected = 0;
int result = 0;
+ for (i = 0; !found_selected && i < TASK__COUNT; i++)
+ found_selected = tasks[i].selected;
+
+ if (found_selected)
+ QSORT(tasks, TASK__COUNT, compare_tasks_by_selection);
+
for (i = 0; i < TASK__COUNT; i++) {
- if (!tasks[i].enabled)
+ if (found_selected && !tasks[i].selected)
+ continue;
+
+ if (!found_selected && !tasks[i].enabled)
continue;
if (tasks[i].fn(opts)) {
@@ -832,6 +853,37 @@ static int maintenance_run(struct maintenance_opts *opts)
return result;
}
+static int task_option_parse(const struct option *opt,
+ const char *arg, int unset)
+{
+ int i, num_selected = 0;
+ struct maintenance_task *task = NULL;
+
+ BUG_ON_OPT_NEG(unset);
+
+ for (i = 0; i < TASK__COUNT; i++) {
+ num_selected += tasks[i].selected;
+ if (!strcasecmp(tasks[i].name, arg)) {
+ task = &tasks[i];
+ }
+ }
+
+ if (!task) {
+ error(_("'%s' is not a valid task"), arg);
+ return 1;
+ }
+
+ if (task->selected) {
+ error(_("task '%s' cannot be selected multiple times"), arg);
+ return 1;
+ }
+
+ task->selected = 1;
+ task->selected_order = num_selected + 1;
+
+ return 0;
+}
+
int cmd_maintenance(int argc, const char **argv, const char *prefix)
{
static struct maintenance_opts opts;
@@ -840,6 +892,9 @@ int cmd_maintenance(int argc, const char **argv, const char *prefix)
N_("run tasks based on the state of the repository")),
OPT_BOOL(0, "quiet", &opts.quiet,
N_("do not report progress or other information over stderr")),
+ OPT_CALLBACK_F(0, "task", NULL, N_("task"),
+ N_("run a specific task"),
+ PARSE_OPT_NONEG, task_option_parse),
OPT_END()
};
@@ -23,4 +23,31 @@ test_expect_success 'run [--auto|--quiet]' '
test_subcommand git gc --no-quiet <run-no-quiet.txt
'
+test_expect_success 'run --task=<task>' '
+ GIT_TRACE2_EVENT="$(pwd)/run-commit-graph.txt" \
+ git maintenance run --task=commit-graph 2>/dev/null &&
+ GIT_TRACE2_EVENT="$(pwd)/run-gc.txt" \
+ git maintenance run --task=gc 2>/dev/null &&
+ GIT_TRACE2_EVENT="$(pwd)/run-commit-graph.txt" \
+ git maintenance run --task=commit-graph 2>/dev/null &&
+ GIT_TRACE2_EVENT="$(pwd)/run-both.txt" \
+ git maintenance run --task=commit-graph --task=gc 2>/dev/null &&
+ test_subcommand ! git gc --quiet <run-commit-graph.txt &&
+ test_subcommand git gc --quiet <run-gc.txt &&
+ test_subcommand git gc --quiet <run-both.txt &&
+ test_subcommand git commit-graph write --split --reachable --no-progress <run-commit-graph.txt &&
+ test_subcommand ! git commit-graph write --split --reachable --no-progress <run-gc.txt &&
+ test_subcommand git commit-graph write --split --reachable --no-progress <run-both.txt
+'
+
+test_expect_success 'run --task=bogus' '
+ test_must_fail git maintenance run --task=bogus 2>err &&
+ test_i18ngrep "is not a valid task" err
+'
+
+test_expect_success 'run --task duplicate' '
+ test_must_fail git maintenance run --task=gc --task=gc 2>err &&
+ test_i18ngrep "cannot be selected multiple times" err
+'
+
test_done