Merge branch 'ds/scalar-no-maintenance'

Two "scalar" subcommands that adds a repository that hasn't been
under "scalar"'s control are taught an option not to enable the
scheduled maintenance on it.

* ds/scalar-no-maintenance:
  scalar reconfigure: improve --maintenance docs
  scalar reconfigure: add --maintenance=<mode> option
  scalar clone: add --no-maintenance option
  scalar register: add --no-maintenance option
  scalar: customize register_dir()'s behavior
This commit is contained in:
Junio C Hamano 2025-05-23 15:34:07 -07:00
commit 95c79efb8d
4 changed files with 113 additions and 20 deletions

View File

@ -9,12 +9,12 @@ SYNOPSIS
--------
[verse]
scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]
[--[no-]src] <url> [<enlistment>]
[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]
scalar list
scalar register [<enlistment>]
scalar register [--[no-]maintenance] [<enlistment>]
scalar unregister [<enlistment>]
scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [<enlistment>]
scalar reconfigure [ --all | <enlistment> ]
scalar reconfigure [--maintenance=(enable|disable|keep)] [ --all | <enlistment> ]
scalar diagnose [<enlistment>]
scalar delete <enlistment>
@ -97,6 +97,11 @@ cloning. If the HEAD at the remote did not point at any branch when
A sparse-checkout is initialized by default. This behavior can be
turned off via `--full-clone`.
--[no-]maintenance::
By default, `scalar clone` configures the enlistment to use Git's
background maintenance feature. Use the `--no-maintenance` to skip
this configuration.
List
~~~~
@ -117,6 +122,12 @@ Note: when this subcommand is called in a worktree that is called `src/`, its
parent directory is considered to be the Scalar enlistment. If the worktree is
_not_ called `src/`, it itself will be considered to be the Scalar enlistment.
--[no-]maintenance::
By default, `scalar register` configures the enlistment to use Git's
background maintenance feature. Use the `--no-maintenance` to skip
this configuration. This does not disable any maintenance that may
already be enabled in other ways.
Unregister
~~~~~~~~~~
@ -149,8 +160,18 @@ After a Scalar upgrade, or when the configuration of a Scalar enlistment
was somehow corrupted or changed by mistake, this subcommand allows to
reconfigure the enlistment.
With the `--all` option, all enlistments currently registered with Scalar
will be reconfigured. Use this option after each Scalar upgrade.
--all::
When `--all` is specified, reconfigure all enlistments currently
registered with Scalar by the `scalar.repo` config key. Use this
option after each upgrade to get the latest features.
--maintenance=(enable|disable|keep)::
By default, Scalar configures the enlistment to use Git's
background maintenance feature; this is the same as using the
`enable` value for this option. Use the `disable` value to
remove each considered enlistment from background maintenance.
Use `keep' to leave the background maintenance configuration
untouched for these repositories.
Diagnose
~~~~~~~~

View File

@ -209,6 +209,12 @@ static int set_recommended_config(int reconfigure)
return 0;
}
/**
* Enable or disable the maintenance mode for the current repository:
*
* * If 'enable' is nonzero, run 'git maintenance start'.
* * If 'enable' is zero, run 'git maintenance unregister --force'.
*/
static int toggle_maintenance(int enable)
{
return run_git("maintenance",
@ -259,7 +265,15 @@ static int stop_fsmonitor_daemon(void)
return 0;
}
static int register_dir(void)
/**
* Register the current directory as a Scalar enlistment, and set the
* recommended configuration.
*
* * If 'maintenance' is non-zero, then enable background maintenance.
* * If 'maintenance' is zero, then leave background maintenance as it is
* currently configured.
*/
static int register_dir(int maintenance)
{
if (add_or_remove_enlistment(1))
return error(_("could not add enlistment"));
@ -267,8 +281,9 @@ static int register_dir(void)
if (set_recommended_config(0))
return error(_("could not set recommended config"));
if (toggle_maintenance(1))
warning(_("could not turn on maintenance"));
if (maintenance &&
toggle_maintenance(maintenance))
warning(_("could not toggle maintenance"));
if (have_fsmonitor_support() && start_fsmonitor_daemon()) {
return error(_("could not start the FSMonitor daemon"));
@ -411,7 +426,7 @@ static int cmd_clone(int argc, const char **argv)
const char *branch = NULL;
char *branch_to_free = NULL;
int full_clone = 0, single_branch = 0, show_progress = isatty(2);
int src = 1, tags = 1;
int src = 1, tags = 1, maintenance = 1;
struct option clone_options[] = {
OPT_STRING('b', "branch", &branch, N_("<branch>"),
N_("branch to checkout after clone")),
@ -424,11 +439,13 @@ static int cmd_clone(int argc, const char **argv)
N_("create repository within 'src' directory")),
OPT_BOOL(0, "tags", &tags,
N_("specify if tags should be fetched during clone")),
OPT_BOOL(0, "maintenance", &maintenance,
N_("specify if background maintenance should be enabled")),
OPT_END(),
};
const char * const clone_usage[] = {
N_("scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n"
"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]"),
"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]"),
NULL
};
const char *url;
@ -550,7 +567,8 @@ static int cmd_clone(int argc, const char **argv)
if (res)
goto cleanup;
res = register_dir();
/* If --no-maintenance, then skip maintenance command entirely. */
res = register_dir(maintenance);
cleanup:
free(branch_to_free);
@ -597,11 +615,14 @@ static int cmd_list(int argc, const char **argv UNUSED)
static int cmd_register(int argc, const char **argv)
{
int maintenance = 1;
struct option options[] = {
OPT_BOOL(0, "maintenance", &maintenance,
N_("specify if background maintenance should be enabled")),
OPT_END(),
};
const char * const usage[] = {
N_("scalar register [<enlistment>]"),
N_("scalar register [--[no-]maintenance] [<enlistment>]"),
NULL
};
@ -610,7 +631,8 @@ static int cmd_register(int argc, const char **argv)
setup_enlistment_directory(argc, argv, usage, options, NULL);
return register_dir();
/* If --no-maintenance, then leave maintenance as-is. */
return register_dir(maintenance);
}
static int get_scalar_repos(const char *key, const char *value,
@ -646,13 +668,19 @@ static int remove_deleted_enlistment(struct strbuf *path)
static int cmd_reconfigure(int argc, const char **argv)
{
int all = 0;
const char *maintenance_str = NULL;
int maintenance = 1; /* Enable maintenance by default. */
struct option options[] = {
OPT_BOOL('a', "all", &all,
N_("reconfigure all registered enlistments")),
OPT_STRING(0, "maintenance", &maintenance_str,
N_("(enable|disable|keep)"),
N_("signal how to adjust background maintenance")),
OPT_END(),
};
const char * const usage[] = {
N_("scalar reconfigure [--all | <enlistment>]"),
N_("scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | <enlistment>]"),
NULL
};
struct string_list scalar_repos = STRING_LIST_INIT_DUP;
@ -672,6 +700,18 @@ static int cmd_reconfigure(int argc, const char **argv)
usage_msg_opt(_("--all or <enlistment>, but not both"),
usage, options);
if (maintenance_str) {
if (!strcmp(maintenance_str, "enable"))
maintenance = 1;
else if (!strcmp(maintenance_str, "disable"))
maintenance = 0;
else if (!strcmp(maintenance_str, "keep"))
maintenance = -1;
else
die(_("unknown mode for --maintenance option: %s"),
maintenance_str);
}
git_config(get_scalar_repos, &scalar_repos);
for (size_t i = 0; i < scalar_repos.nr; i++) {
@ -736,7 +776,8 @@ static int cmd_reconfigure(int argc, const char **argv)
the_repository = old_repo;
repo_clear(&r);
if (toggle_maintenance(1) >= 0)
if (maintenance >= 0 &&
toggle_maintenance(maintenance) >= 0)
succeeded = 1;
loop_end:
@ -803,13 +844,13 @@ static int cmd_run(int argc, const char **argv)
strbuf_release(&buf);
if (i == 0)
return register_dir();
return register_dir(1);
if (i > 0)
return run_git("maintenance", "run",
"--task", tasks[i].task, NULL);
if (register_dir())
if (register_dir(1))
return -1;
for (i = 1; tasks[i].arg; i++)
if (run_git("maintenance", "run",

View File

@ -108,7 +108,7 @@ test_expect_success 'scalar register warns when background maintenance fails' '
git init register-repo &&
GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \
scalar register register-repo 2>err &&
grep "could not turn on maintenance" err
grep "could not toggle maintenance" err
'
test_expect_success 'scalar unregister' '
@ -129,6 +129,17 @@ test_expect_success 'scalar unregister' '
scalar unregister vanish
'
test_expect_success 'scalar register --no-maintenance' '
git init register-no-maint &&
event_log="$(pwd)/no-maint.event" &&
GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \
GIT_TRACE2_EVENT="$event_log" \
GIT_TRACE2_EVENT_DEPTH=100 \
scalar register --no-maintenance register-no-maint 2>err &&
test_must_be_empty err &&
test_subcommand ! git maintenance unregister --force <no-maint.event
'
test_expect_success 'set up repository to clone' '
test_commit first &&
test_commit second &&
@ -199,7 +210,18 @@ test_expect_success 'scalar reconfigure' '
GIT_TRACE2_EVENT="$(pwd)/reconfigure" scalar reconfigure -a &&
test_path_is_file one/src/cron.txt &&
test true = "$(git -C one/src config core.preloadIndex)" &&
test_subcommand git maintenance start <reconfigure
test_subcommand git maintenance start <reconfigure &&
test_subcommand ! git maintenance unregister --force <reconfigure &&
GIT_TRACE2_EVENT="$(pwd)/reconfigure-maint-disable" \
scalar reconfigure -a --maintenance=disable &&
test_subcommand ! git maintenance start <reconfigure-maint-disable &&
test_subcommand git maintenance unregister --force <reconfigure-maint-disable &&
GIT_TRACE2_EVENT="$(pwd)/reconfigure-maint-keep" \
scalar reconfigure --maintenance=keep -a &&
test_subcommand ! git maintenance start <reconfigure-maint-keep &&
test_subcommand ! git maintenance unregister --force <reconfigure-maint-keep
'
test_expect_success 'scalar reconfigure --all with includeIf.onbranch' '

View File

@ -177,7 +177,16 @@ test_expect_success 'progress without tty' '
test_expect_success 'scalar clone warns when background maintenance fails' '
GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \
scalar clone "file://$(pwd)/to-clone" maint-fail 2>err &&
grep "could not turn on maintenance" err
grep "could not toggle maintenance" err
'
test_expect_success 'scalar clone --no-maintenance' '
GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \
GIT_TRACE2_EVENT="$(pwd)/no-maint.event" \
GIT_TRACE2_EVENT_DEPTH=100 \
scalar clone --no-maintenance "file://$(pwd)/to-clone" no-maint 2>err &&
! grep "could not toggle maintenance" err &&
test_subcommand ! git maintenance unregister --force <no-maint.event
'
test_expect_success '`scalar clone --no-src`' '