{"thread":{"id":"63372","subject":"[PATCH 0/2] scalar: add --no-maintenance option","startedAt":"2025-04-30T10:24:43Z","lastAt":"2025-05-16T16:36:44Z","messageCount":30,"participants":["Derrick Stolee via GitGitGadget","Junio C Hamano","Derrick Stolee","Patrick Steinhardt"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"517004","messageId":"pull.1913.git.1746008680.gitgitgadget@gmail.com","threadId":"63372","inReplyTo":null,"subject":"[PATCH 0/2] scalar: add --no-maintenance option","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-30T10:24:38Z","receivedAt":"2025-04-30T10:24:43Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"These patches add a new --no-maintenance option to the scalar register and\nscalar clone commands. My motivation is based on setting up Scalar clones in\nautomated environments that set up a repo onto a disk image for use later.\nIf background maintenance runs during later setup steps, then this\nintroduces a variable that is unexpected at minimum and disruptive at worst.\nThe disruption comes in if the automation has steps to run git maintenance\nrun --task=<X> commands but those commands are blocked due to the\nmaintenance.lock file.\n\nFunctionally, these leave the default behavior as-is but allow disabling the\ngit maintenance start step when users opt-in to this difference. The idea of\nScalar is to recommend the best practices for a typical user, but allowing\ncustomization for expert users.\n\nThanks, -Stolee\n\nDerrick Stolee (2):\n  scalar register: add --no-maintenance option\n  scalar clone: add --no-maintenance option\n\n Documentation/scalar.adoc | 15 +++++++++++++--\n scalar.c                  | 23 ++++++++++++++---------\n t/t9210-scalar.sh         |  7 +++++++\n t/t9211-scalar-clone.sh   |  6 ++++++\n 4 files changed, 40 insertions(+), 11 deletions(-)\n\n\nbase-commit: f65182a99e545d2f2bc22e6c1c2da192133b16a3\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1913%2Fderrickstolee%2Fscalar-no-maintenance-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1913/derrickstolee/scalar-no-maintenance-v1\nPull-Request: https://github.com/gitgitgadget/git/pull/1913\n-- \ngitgitgadget\n"},{"id":"517005","messageId":"4910bacd0524a29186e673a174a47cd46ac95b5e.1746008680.git.gitgitgadget@gmail.com","threadId":"63372","inReplyTo":"pull.1913.git.1746008680.gitgitgadget@gmail.com","subject":"[PATCH 1/2] scalar register: add --no-maintenance option","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-30T10:24:39Z","receivedAt":"2025-04-30T10:24:44Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <stolee@gmail.com>\n\nWhen registering a repository with Scalar to get the latest opinionated\nconfiguration, the 'scalar register' command will also set up background\nmaintenance. This is a recommended feature for most user scenarios.\n\nHowever, this is not always recommended in some scenarios where\nbackground modifications may interfere with foreground activities.\nSpecifically, setting up a clone for use in automation may require doing\ncertain maintenance steps in the foreground that could become blocked by\nconcurrent background maintenance operations.\n\nAllow the user to specify --no-maintenance to 'scalar register'. This\nrequires updating the method prototype for register_dir(), so use the\ndefault of enabling this value when otherwise specified.\n\nSigned-off-by: Derrick Stolee <stolee@gmail.com>\n---\n Documentation/scalar.adoc |  8 +++++++-\n scalar.c                  | 17 ++++++++++-------\n t/t9210-scalar.sh         |  7 +++++++\n 3 files changed, 24 insertions(+), 8 deletions(-)\n\ndiff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc\nindex 7e4259c6743f..b2b244a86499 100644\n--- a/Documentation/scalar.adoc\n+++ b/Documentation/scalar.adoc\n@@ -11,7 +11,7 @@ SYNOPSIS\n scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n \t[--[no-]src] <url> [<enlistment>]\n scalar list\n-scalar register [<enlistment>]\n+scalar register [--[no-]maintenance] [<enlistment>]\n scalar unregister [<enlistment>]\n scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [<enlistment>]\n scalar reconfigure [ --all | <enlistment> ]\n@@ -117,6 +117,12 @@ Note: when this subcommand is called in a worktree that is called `src/`, its\n parent directory is considered to be the Scalar enlistment. If the worktree is\n _not_ called `src/`, it itself will be considered to be the Scalar enlistment.\n \n+--[no-]maintenance::\n+\tBy default, `scalar register` configures the enlistment to use Git's\n+\tbackground maintenance feature. Use the `--no-maintenance` to skip\n+\tthis configuration. This does not disable any maintenance that may\n+\talready be enabled in other ways.\n+\n Unregister\n ~~~~~~~~~~\n \ndiff --git a/scalar.c b/scalar.c\nindex d359f08bb8e2..2a21fd55f39b 100644\n--- a/scalar.c\n+++ b/scalar.c\n@@ -259,7 +259,7 @@ static int stop_fsmonitor_daemon(void)\n \treturn 0;\n }\n \n-static int register_dir(void)\n+static int register_dir(int maintenance)\n {\n \tif (add_or_remove_enlistment(1))\n \t\treturn error(_(\"could not add enlistment\"));\n@@ -267,7 +267,7 @@ static int register_dir(void)\n \tif (set_recommended_config(0))\n \t\treturn error(_(\"could not set recommended config\"));\n \n-\tif (toggle_maintenance(1))\n+\tif (toggle_maintenance(maintenance))\n \t\twarning(_(\"could not turn on maintenance\"));\n \n \tif (have_fsmonitor_support() && start_fsmonitor_daemon()) {\n@@ -550,7 +550,7 @@ static int cmd_clone(int argc, const char **argv)\n \tif (res)\n \t\tgoto cleanup;\n \n-\tres = register_dir();\n+\tres = register_dir(1);\n \n cleanup:\n \tfree(branch_to_free);\n@@ -597,11 +597,14 @@ static int cmd_list(int argc, const char **argv UNUSED)\n \n static int cmd_register(int argc, const char **argv)\n {\n+\tint maintenance = 1;\n \tstruct option options[] = {\n+\t\tOPT_BOOL(0, \"maintenance\", &maintenance,\n+\t\t\t N_(\"specify if background maintenance should be enabled\")),\n \t\tOPT_END(),\n \t};\n \tconst char * const usage[] = {\n-\t\tN_(\"scalar register [<enlistment>]\"),\n+\t\tN_(\"scalar register [--[no-]maintenance] [<enlistment>]\"),\n \t\tNULL\n \t};\n \n@@ -610,7 +613,7 @@ static int cmd_register(int argc, const char **argv)\n \n \tsetup_enlistment_directory(argc, argv, usage, options, NULL);\n \n-\treturn register_dir();\n+\treturn register_dir(maintenance);\n }\n \n static int get_scalar_repos(const char *key, const char *value,\n@@ -803,13 +806,13 @@ static int cmd_run(int argc, const char **argv)\n \tstrbuf_release(&buf);\n \n \tif (i == 0)\n-\t\treturn register_dir();\n+\t\treturn register_dir(1);\n \n \tif (i > 0)\n \t\treturn run_git(\"maintenance\", \"run\",\n \t\t\t       \"--task\", tasks[i].task, NULL);\n \n-\tif (register_dir())\n+\tif (register_dir(1))\n \t\treturn -1;\n \tfor (i = 1; tasks[i].arg; i++)\n \t\tif (run_git(\"maintenance\", \"run\",\ndiff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh\nindex a81662713eb8..a488f72de9fe 100755\n--- a/t/t9210-scalar.sh\n+++ b/t/t9210-scalar.sh\n@@ -129,6 +129,13 @@ test_expect_success 'scalar unregister' '\n \tscalar unregister vanish\n '\n \n+test_expect_success 'scalar register --no-maintenance' '\n+\tgit init register-no-maint &&\n+\tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n+\t\tscalar register --no-maintenance register-no-maint 2>err &&\n+\ttest_must_be_empty err\n+'\n+\n test_expect_success 'set up repository to clone' '\n \ttest_commit first &&\n \ttest_commit second &&\n-- \ngitgitgadget\n\n"},{"id":"517006","messageId":"7ab1914b8305c6d67f70660d1278085c2e370302.1746008680.git.gitgitgadget@gmail.com","threadId":"63372","inReplyTo":"pull.1913.git.1746008680.gitgitgadget@gmail.com","subject":"[PATCH 2/2] scalar clone: add --no-maintenance option","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-30T10:24:40Z","receivedAt":"2025-04-30T10:24:45Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <stolee@gmail.com>\n\nWhen creating a new enlistment via 'scalar clone', the default is to set\nup situations that work for most user scenarios. Background maintenance\nis one of those highly-recommended options for most users.\n\nHowever, when using 'scalar clone' to create an enlistment in a\ndifferent situation, such as prepping a VM image, it may be valuable to\ndisable background maintenance so the manual maintenance steps do not\nget blocked by concurrent background maintenance activities.\n\nAdd a new --no-maintenance option to 'scalar clone'.\n\nSigned-off-by: Derrick Stolee <stolee@gmail.com>\n---\n Documentation/scalar.adoc | 7 ++++++-\n scalar.c                  | 8 +++++---\n t/t9211-scalar-clone.sh   | 6 ++++++\n 3 files changed, 17 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc\nindex b2b244a86499..7753df3b4352 100644\n--- a/Documentation/scalar.adoc\n+++ b/Documentation/scalar.adoc\n@@ -9,7 +9,7 @@ SYNOPSIS\n --------\n [verse]\n scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n-\t[--[no-]src] <url> [<enlistment>]\n+\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]\n scalar list\n scalar register [--[no-]maintenance] [<enlistment>]\n scalar unregister [<enlistment>]\n@@ -97,6 +97,11 @@ cloning. If the HEAD at the remote did not point at any branch when\n \tA sparse-checkout is initialized by default. This behavior can be\n \tturned off via `--full-clone`.\n \n+--[no-]maintenance::\n+\tBy default, `scalar clone` configures the enlistment to use Git's\n+\tbackground maintenance feature. Use the `--no-maintenance` to skip\n+\tthis configuration.\n+\n List\n ~~~~\n \ndiff --git a/scalar.c b/scalar.c\nindex 2a21fd55f39b..90ea4da11b40 100644\n--- a/scalar.c\n+++ b/scalar.c\n@@ -411,7 +411,7 @@ static int cmd_clone(int argc, const char **argv)\n \tconst char *branch = NULL;\n \tchar *branch_to_free = NULL;\n \tint full_clone = 0, single_branch = 0, show_progress = isatty(2);\n-\tint src = 1, tags = 1;\n+\tint src = 1, tags = 1, maintenance = 1;\n \tstruct option clone_options[] = {\n \t\tOPT_STRING('b', \"branch\", &branch, N_(\"<branch>\"),\n \t\t\t   N_(\"branch to checkout after clone\")),\n@@ -424,11 +424,13 @@ static int cmd_clone(int argc, const char **argv)\n \t\t\t N_(\"create repository within 'src' directory\")),\n \t\tOPT_BOOL(0, \"tags\", &tags,\n \t\t\t N_(\"specify if tags should be fetched during clone\")),\n+\t\tOPT_BOOL(0, \"maintenance\", &maintenance,\n+\t\t\t N_(\"specify if background maintenance should be enabled\")),\n \t\tOPT_END(),\n \t};\n \tconst char * const clone_usage[] = {\n \t\tN_(\"scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\\n\"\n-\t\t   \"\\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]\"),\n+\t\t   \"\\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]\"),\n \t\tNULL\n \t};\n \tconst char *url;\n@@ -550,7 +552,7 @@ static int cmd_clone(int argc, const char **argv)\n \tif (res)\n \t\tgoto cleanup;\n \n-\tres = register_dir(1);\n+\tres = register_dir(maintenance);\n \n cleanup:\n \tfree(branch_to_free);\ndiff --git a/t/t9211-scalar-clone.sh b/t/t9211-scalar-clone.sh\nindex 01f71910f533..b9c130db6056 100755\n--- a/t/t9211-scalar-clone.sh\n+++ b/t/t9211-scalar-clone.sh\n@@ -180,6 +180,12 @@ test_expect_success 'scalar clone warns when background maintenance fails' '\n \tgrep \"could not turn on maintenance\" err\n '\n \n+test_expect_success 'scalar clone --no-maintenance' '\n+\tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n+\t\tscalar clone --no-maintenance \"file://$(pwd)/to-clone\" no-maint 2>err &&\n+\t! grep \"could not turn on maintenance\" err\n+'\n+\n test_expect_success '`scalar clone --no-src`' '\n \tscalar clone --src \"file://$(pwd)/to-clone\" with-src &&\n \tscalar clone --no-src \"file://$(pwd)/to-clone\" without-src &&\n-- \ngitgitgadget\n"},{"id":"517033","messageId":"xmqq8qnh1jjg.fsf@gitster.g","threadId":"63372","inReplyTo":"pull.1913.git.1746008680.gitgitgadget@gmail.com","subject":"Re: [PATCH 0/2] scalar: add --no-maintenance option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-04-30T20:28:03Z","receivedAt":"2025-04-30T20:28:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> These patches add a new --no-maintenance option to the scalar register and\n> scalar clone commands. My motivation is based on setting up Scalar clones in\n> automated environments that set up a repo onto a disk image for use later.\n> If background maintenance runs during later setup steps, then this\n> introduces a variable that is unexpected at minimum and disruptive at worst.\n> The disruption comes in if the automation has steps to run git maintenance\n> run --task=<X> commands but those commands are blocked due to the\n> maintenance.lock file.\n>\n> Functionally, these leave the default behavior as-is but allow disabling the\n> git maintenance start step when users opt-in to this difference. The idea of\n> Scalar is to recommend the best practices for a typical user, but allowing\n> customization for expert users.\n\nThe feature itself I do not have any objections to and I found the\nreasoning given above very sound.\n\nWith these two patches, we still have an unconditional call to\ntoggle_maintenance(1) in cmd_reconfigure().  Shoudln't the call be\nat least removed, which would mean that reconfiguring would not\nchange the auto-maintenance states, or made controllable from the\ncommand line of \"maintenance reconfigure\"?\n\nIt somehow looks to me that the real culprit of making the result of\napplying two patches still unsatisfactory is the original design to\nhave the toggle_maintenance() call made from inside register_dir()\nin the first place.  Shouldn't a much higher layer entry points like\ncmd_register() and cmd_clone() be where the decision is made if\nmaintenance task should be set up (or not set up) by calling\ntoggle_maintenance(), leaving the register_dir() responsible only\nfor \"enlist the directory to the system\"?\n\nIOW it feels to me that enabling (and now optionally disabling)\nmaintenance is tied too deeply into the act of enlisting a\ndirectory; if we need to disable maintenance (and a mode to add\nenlistment without enabling maintenance), it is a sign that it\nshouldn't be a parameter into the register_dir() function that\ncontrols what register_dir() does, and rather it should be done by\nletting the caller who calls register_dir() decide to call (or not)\ntoggle_maintenance().\n\nThanks.\n\n"},{"id":"517043","messageId":"d3659baa-054e-4a31-a851-5471968aed07@gmail.com","threadId":"63372","inReplyTo":"xmqq8qnh1jjg.fsf@gitster.g","subject":"Re: [PATCH 0/2] scalar: add --no-maintenance option","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2025-05-01T13:21:16Z","receivedAt":"2025-05-01T13:21:18Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 4/30/2025 4:28 PM, Junio C Hamano wrote:\n> \"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n> \n>> These patches add a new --no-maintenance option to the scalar register and\n>> scalar clone commands. My motivation is based on setting up Scalar clones in\n>> automated environments that set up a repo onto a disk image for use later.\n>> If background maintenance runs during later setup steps, then this\n>> introduces a variable that is unexpected at minimum and disruptive at worst.\n>> The disruption comes in if the automation has steps to run git maintenance\n>> run --task=<X> commands but those commands are blocked due to the\n>> maintenance.lock file.\n>>\n>> Functionally, these leave the default behavior as-is but allow disabling the\n>> git maintenance start step when users opt-in to this difference. The idea of\n>> Scalar is to recommend the best practices for a typical user, but allowing\n>> customization for expert users.\n> \n> The feature itself I do not have any objections to and I found the\n> reasoning given above very sound.\n> \n> With these two patches, we still have an unconditional call to\n> toggle_maintenance(1) in cmd_reconfigure().  Shoudln't the call be\n> at least removed, which would mean that reconfiguring would not\n> change the auto-maintenance states, or made controllable from the\n> command line of \"maintenance reconfigure\"?\n\nI agree that this was a miss on my part. Thanks for the careful eye.\n \n> It somehow looks to me that the real culprit of making the result of\n> applying two patches still unsatisfactory is the original design to\n> have the toggle_maintenance() call made from inside register_dir()\n> in the first place.  Shouldn't a much higher layer entry points like\n> cmd_register() and cmd_clone() be where the decision is made if\n> maintenance task should be set up (or not set up) by calling\n> toggle_maintenance(), leaving the register_dir() responsible only\n> for \"enlist the directory to the system\"?\n> \n> IOW it feels to me that enabling (and now optionally disabling)\n> maintenance is tied too deeply into the act of enlisting a\n> directory; if we need to disable maintenance (and a mode to add\n> enlistment without enabling maintenance), it is a sign that it\n> shouldn't be a parameter into the register_dir() function that\n> controls what register_dir() does, and rather it should be done by\n> letting the caller who calls register_dir() decide to call (or not)\n> toggle_maintenance().\nI will continue thinking about this while playing with different\noptions for a v2. My gut reaction is that register_dir() is our\ncentralized way to \"set up recommended configuration\" which includes\nconfig options and background maintenance. We're now introducing a\nway to customize this centralized operation based on decentralized\noptions, hence a new option to the method.\n\nIs the right solution to move the toggle_maintenance() out of\nregister_dir()? If this is the only way we plan to customize the\nconfig, then yes. Otherwise, the second or third customization will\nstart to lead to copied logic through these three locations.\n\nAgain, I'm mostly thinking out loud here before I go and dig into\nthe code. I'll report back with v2.\n\nThanks,\n-Stolee\n\n"},{"id":"517053","messageId":"xmqqh624xp4j.fsf@gitster.g","threadId":"63372","inReplyTo":"d3659baa-054e-4a31-a851-5471968aed07@gmail.com","subject":"Re: [PATCH 0/2] scalar: add --no-maintenance option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-05-01T16:38:36Z","receivedAt":"2025-05-01T16:38:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Derrick Stolee <stolee@gmail.com> writes:\n\n> Is the right solution to move the toggle_maintenance() out of\n> register_dir()? If this is the only way we plan to customize the\n> config, then yes. Otherwise, the second or third customization will\n> start to lead to copied logic through these three locations.\n\nIt is mostly philosophical, I think, but I actually think the\ncallers that are allowed to be different is a good thing.  The\ncallers can pass different parameters to register_dir(), but the\ndistinction between these different callers would become more subtle\nand not immediately obvious to readers.  With an explicit call to\ntoggle_maintenance() at each callsite, it becomes more obvious to\nsee who sets up the maintenance job and how.\n\nIf this is and will stay the only way, I would not care too much\neither way, but if we are planning to extend, then I would say that\nit is more important to allow callers to be more explicit.\n\nBesides, you'd need to call toggle_maintenance() to disable it in a\ncaller outside register_dir(), so it is not like you can hide the\ntweaks from readers of the code and make it appear to be simpler.\nThey need to be aware of what goes on anyway.\n\n\n\n\n"},{"id":"517057","messageId":"xmqq7c30xkdx.fsf@gitster.g","threadId":"63372","inReplyTo":"xmqqh624xp4j.fsf@gitster.g","subject":"Re: [PATCH 0/2] scalar: add --no-maintenance option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-05-01T18:20:58Z","receivedAt":"2025-05-01T18:21:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> It is mostly philosophical, I think, ...\n\nIn other words, I think making each helper function do one thing and\none thing well is a good thing, and \"register\" should focus on\nregistering the new repository to the system.\n\nBy the way, it is excellent that the new option honors the positive\nform (i.e. \"clone --maintenance\" and \"clone --no-maintenance\").  I\nwas re-reading the patches and was pleasantly surprised, as I would\nhave forgotten to do so while focusing too much on the shiny new\nfeature of being able to disable if I were doing these patches.\n"},{"id":"517101","messageId":"aBSNN6Z3Vve6c6Bm@pks.im","threadId":"63372","inReplyTo":"4910bacd0524a29186e673a174a47cd46ac95b5e.1746008680.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 1/2] scalar register: add --no-maintenance option","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-05-02T09:15:35Z","receivedAt":"2025-05-02T09:15:39Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Apr 30, 2025 at 10:24:39AM +0000, Derrick Stolee via GitGitGadget wrote:\n> diff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc\n> index 7e4259c6743f..b2b244a86499 100644\n> --- a/Documentation/scalar.adoc\n> +++ b/Documentation/scalar.adoc\n> @@ -11,7 +11,7 @@ SYNOPSIS\n>  scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n>  \t[--[no-]src] <url> [<enlistment>]\n>  scalar list\n> -scalar register [<enlistment>]\n> +scalar register [--[no-]maintenance] [<enlistment>]\n>  scalar unregister [<enlistment>]\n>  scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [<enlistment>]\n>  scalar reconfigure [ --all | <enlistment> ]\n> @@ -117,6 +117,12 @@ Note: when this subcommand is called in a worktree that is called `src/`, its\n>  parent directory is considered to be the Scalar enlistment. If the worktree is\n>  _not_ called `src/`, it itself will be considered to be the Scalar enlistment.\n>  \n> +--[no-]maintenance::\n> +\tBy default, `scalar register` configures the enlistment to use Git's\n> +\tbackground maintenance feature. Use the `--no-maintenance` to skip\n> +\tthis configuration. This does not disable any maintenance that may\n> +\talready be enabled in other ways.\n> +\n>  Unregister\n>  ~~~~~~~~~~\n>  \n> diff --git a/scalar.c b/scalar.c\n> index d359f08bb8e2..2a21fd55f39b 100644\n> --- a/scalar.c\n> +++ b/scalar.c\n> @@ -259,7 +259,7 @@ static int stop_fsmonitor_daemon(void)\n>  \treturn 0;\n>  }\n>  \n> -static int register_dir(void)\n> +static int register_dir(int maintenance)\n>  {\n>  \tif (add_or_remove_enlistment(1))\n>  \t\treturn error(_(\"could not add enlistment\"));\n> @@ -267,7 +267,7 @@ static int register_dir(void)\n>  \tif (set_recommended_config(0))\n>  \t\treturn error(_(\"could not set recommended config\"));\n>  \n> -\tif (toggle_maintenance(1))\n> +\tif (toggle_maintenance(maintenance))\n>  \t\twarning(_(\"could not turn on maintenance\"));\n>  \n>  \tif (have_fsmonitor_support() && start_fsmonitor_daemon()) {\n\nIsn't this change contrary to what the docs say? `toggle_maintenance(0)`\nwould cause us to execute `git maintenance unregister --force`, which\nderegisters maintenance for us.\n\n> @@ -597,11 +597,14 @@ static int cmd_list(int argc, const char **argv UNUSED)\n>  \n>  static int cmd_register(int argc, const char **argv)\n>  {\n> +\tint maintenance = 1;\n>  \tstruct option options[] = {\n> +\t\tOPT_BOOL(0, \"maintenance\", &maintenance,\n> +\t\t\t N_(\"specify if background maintenance should be enabled\")),\n\nMaybe s/if/whether/? Might just be me not being a native speaker,\nthough.\n\n> diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh\n> index a81662713eb8..a488f72de9fe 100755\n> --- a/t/t9210-scalar.sh\n> +++ b/t/t9210-scalar.sh\n> @@ -129,6 +129,13 @@ test_expect_success 'scalar unregister' '\n>  \tscalar unregister vanish\n>  '\n>  \n> +test_expect_success 'scalar register --no-maintenance' '\n> +\tgit init register-no-maint &&\n> +\tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n> +\t\tscalar register --no-maintenance register-no-maint 2>err &&\n> +\ttest_must_be_empty err\n> +'\n> +\n\nWe should probably have a test that verifies that we don't deregister\nmaintenance.\n\nPatrick\n"},{"id":"517118","messageId":"b9a4dbf2-0064-4933-985f-b34dcb133030@gmail.com","threadId":"63372","inReplyTo":"aBSNN6Z3Vve6c6Bm@pks.im","subject":"Re: [PATCH 1/2] scalar register: add --no-maintenance option","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2025-05-02T15:01:00Z","receivedAt":"2025-05-02T15:01:02Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 5/2/2025 5:15 AM, Patrick Steinhardt wrote:\n> On Wed, Apr 30, 2025 at 10:24:39AM +0000, Derrick Stolee via GitGitGadget wrote:\n>> diff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc\n>> index 7e4259c6743f..b2b244a86499 100644\n>> --- a/Documentation/scalar.adoc\n>> +++ b/Documentation/scalar.adoc\n>> @@ -11,7 +11,7 @@ SYNOPSIS\n>>  scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n>>  \t[--[no-]src] <url> [<enlistment>]\n>>  scalar list\n>> -scalar register [<enlistment>]\n>> +scalar register [--[no-]maintenance] [<enlistment>]\n>>  scalar unregister [<enlistment>]\n>>  scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [<enlistment>]\n>>  scalar reconfigure [ --all | <enlistment> ]\n>> @@ -117,6 +117,12 @@ Note: when this subcommand is called in a worktree that is called `src/`, its\n>>  parent directory is considered to be the Scalar enlistment. If the worktree is\n>>  _not_ called `src/`, it itself will be considered to be the Scalar enlistment.\n>>  \n>> +--[no-]maintenance::\n>> +\tBy default, `scalar register` configures the enlistment to use Git's\n>> +\tbackground maintenance feature. Use the `--no-maintenance` to skip\n>> +\tthis configuration. This does not disable any maintenance that may\n>> +\talready be enabled in other ways.\n\n>> -\tif (toggle_maintenance(1))\n>> +\tif (toggle_maintenance(maintenance))\n>>  \t\twarning(_(\"could not turn on maintenance\"));\n>>  \n>>  \tif (have_fsmonitor_support() && start_fsmonitor_daemon()) {\n> \n> Isn't this change contrary to what the docs say? `toggle_maintenance(0)`\n> would cause us to execute `git maintenance unregister --force`, which\n> deregisters maintenance for us.\n\nYou are right. I've confirmed this using 'test_subcommand' in my test, so I'll\nplumb the ability to skip toggle_maintenance() in certain cases. I'll carefully\ndocument this in code as well.\n\nThanks for the careful eye. \n>> @@ -597,11 +597,14 @@ static int cmd_list(int argc, const char **argv UNUSED)\n>>  \n>>  static int cmd_register(int argc, const char **argv)\n>>  {\n>> +\tint maintenance = 1;\n>>  \tstruct option options[] = {\n>> +\t\tOPT_BOOL(0, \"maintenance\", &maintenance,\n>> +\t\t\t N_(\"specify if background maintenance should be enabled\")),\n> \n> Maybe s/if/whether/? Might just be me not being a native speaker,\n> though.\n\nI like your choice here.\n\n>> diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh\n>> index a81662713eb8..a488f72de9fe 100755\n>> --- a/t/t9210-scalar.sh\n>> +++ b/t/t9210-scalar.sh\n>> @@ -129,6 +129,13 @@ test_expect_success 'scalar unregister' '\n>>  \tscalar unregister vanish\n>>  '\n>>  \n>> +test_expect_success 'scalar register --no-maintenance' '\n>> +\tgit init register-no-maint &&\n>> +\tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n>> +\t\tscalar register --no-maintenance register-no-maint 2>err &&\n>> +\ttest_must_be_empty err\n>> +'\n>> +\n> \n> We should probably have a test that verifies that we don't deregister\n> maintenance.\nYes, will do. The currently-passing test that confirms the unregister is\nhappening would look like this:\n\ntest_expect_success 'scalar register --no-maintenance' '\n\tgit init register-no-maint &&\n\tevent_log=\"$(pwd)/no-maint.event\" &&\n\tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n\tGIT_TRACE2_EVENT=\"$event_log\" \\\n\tGIT_TRACE2_EVENT_DEPTH=100 \\\n\t\tscalar register --no-maintenance register-no-maint 2>err &&\n\ttest_must_be_empty err &&\n\ttest_subcommand git maintenance unregister --force <no-maint.event\n'When using test_subcommand, it's really important to verify that this kindof test passes before changing the behavior and turning the test into a\nnegation, since it's easier to accidentally \"pass\" a negative test if the\ntest is malformed.\n\nThanks,\n-Stolee\n\n\n"},{"id":"517260","messageId":"pull.1913.v2.git.1746458844.gitgitgadget@gmail.com","threadId":"63372","inReplyTo":"pull.1913.git.1746008680.gitgitgadget@gmail.com","subject":"[PATCH v2 0/4] scalar: add --no-maintenance option","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-05-05T15:27:20Z","receivedAt":"2025-05-05T15:27:27Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"These patches add a new --no-maintenance option to the scalar register and\nscalar clone commands. My motivation is based on setting up Scalar clones in\nautomated environments that set up a repo onto a disk image for use later.\nIf background maintenance runs during later setup steps, then this\nintroduces a variable that is unexpected at minimum and disruptive at worst.\nThe disruption comes in if the automation has steps to run git maintenance\nrun --task=<X> commands but those commands are blocked due to the\nmaintenance.lock file.\n\nFunctionally, these leave the default behavior as-is but allow disabling the\ngit maintenance start step when users opt-in to this difference. The idea of\nScalar is to recommend the best practices for a typical user, but allowing\ncustomization for expert users.\n\n\nUpdates in v2\n=============\n\n * The previous use of toggle_maintenance() in register_dir() would run the\n   'git maintenance unregister --force' command. There is a new patch 1 that\n   is explicit about whether this should or should not happen and new tests\n   are added to verify this behavior in the later patches.\n * A new patch 4 adds the --[no-]maintenance option to scalar reconfigure.\n\nThanks, -Stolee\n\nDerrick Stolee (4):\n  scalar: customize register_dir()'s behavior\n  scalar register: add --no-maintenance option\n  scalar clone: add --no-maintenance option\n  scalar reconfigure: add --no-maintenance option\n\n Documentation/scalar.adoc | 29 ++++++++++++++++++----\n scalar.c                  | 51 +++++++++++++++++++++++++++++----------\n t/t9210-scalar.sh         | 20 +++++++++++++--\n t/t9211-scalar-clone.sh   | 11 ++++++++-\n 4 files changed, 90 insertions(+), 21 deletions(-)\n\n\nbase-commit: f65182a99e545d2f2bc22e6c1c2da192133b16a3\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1913%2Fderrickstolee%2Fscalar-no-maintenance-v2\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1913/derrickstolee/scalar-no-maintenance-v2\nPull-Request: https://github.com/gitgitgadget/git/pull/1913\n\nRange-diff vs v1:\n\n -:  ----------- > 1:  f3a3cfe3ef1 scalar: customize register_dir()'s behavior\n 1:  4910bacd052 ! 2:  1b99a559520 scalar register: add --no-maintenance option\n     @@ Documentation/scalar.adoc: Note: when this subcommand is called in a worktree th\n       \n      \n       ## scalar.c ##\n     -@@ scalar.c: static int stop_fsmonitor_daemon(void)\n     - \treturn 0;\n     - }\n     - \n     --static int register_dir(void)\n     -+static int register_dir(int maintenance)\n     - {\n     - \tif (add_or_remove_enlistment(1))\n     - \t\treturn error(_(\"could not add enlistment\"));\n     -@@ scalar.c: static int register_dir(void)\n     - \tif (set_recommended_config(0))\n     - \t\treturn error(_(\"could not set recommended config\"));\n     - \n     --\tif (toggle_maintenance(1))\n     -+\tif (toggle_maintenance(maintenance))\n     - \t\twarning(_(\"could not turn on maintenance\"));\n     - \n     - \tif (have_fsmonitor_support() && start_fsmonitor_daemon()) {\n     -@@ scalar.c: static int cmd_clone(int argc, const char **argv)\n     - \tif (res)\n     - \t\tgoto cleanup;\n     - \n     --\tres = register_dir();\n     -+\tres = register_dir(1);\n     - \n     - cleanup:\n     - \tfree(branch_to_free);\n      @@ scalar.c: static int cmd_list(int argc, const char **argv UNUSED)\n       \n       static int cmd_register(int argc, const char **argv)\n     @@ scalar.c: static int cmd_register(int argc, const char **argv)\n       \n       \tsetup_enlistment_directory(argc, argv, usage, options, NULL);\n       \n     --\treturn register_dir();\n     +-\treturn register_dir(1);\n     ++\t/* If --no-maintenance, then leave maintenance as-is. */\n      +\treturn register_dir(maintenance);\n       }\n       \n       static int get_scalar_repos(const char *key, const char *value,\n     -@@ scalar.c: static int cmd_run(int argc, const char **argv)\n     - \tstrbuf_release(&buf);\n     - \n     - \tif (i == 0)\n     --\t\treturn register_dir();\n     -+\t\treturn register_dir(1);\n     - \n     - \tif (i > 0)\n     - \t\treturn run_git(\"maintenance\", \"run\",\n     - \t\t\t       \"--task\", tasks[i].task, NULL);\n     - \n     --\tif (register_dir())\n     -+\tif (register_dir(1))\n     - \t\treturn -1;\n     - \tfor (i = 1; tasks[i].arg; i++)\n     - \t\tif (run_git(\"maintenance\", \"run\",\n      \n       ## t/t9210-scalar.sh ##\n     +@@ t/t9210-scalar.sh: test_expect_success 'scalar register warns when background maintenance fails' '\n     + \tgit init register-repo &&\n     + \tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n     + \t\tscalar register register-repo 2>err &&\n     +-\tgrep \"could not turn on maintenance\" err\n     ++\tgrep \"could not toggle maintenance\" err\n     + '\n     + \n     + test_expect_success 'scalar unregister' '\n      @@ t/t9210-scalar.sh: test_expect_success 'scalar unregister' '\n       \tscalar unregister vanish\n       '\n       \n      +test_expect_success 'scalar register --no-maintenance' '\n      +\tgit init register-no-maint &&\n     ++\tevent_log=\"$(pwd)/no-maint.event\" &&\n      +\tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n     ++\tGIT_TRACE2_EVENT=\"$event_log\" \\\n     ++\tGIT_TRACE2_EVENT_DEPTH=100 \\\n      +\t\tscalar register --no-maintenance register-no-maint 2>err &&\n     -+\ttest_must_be_empty err\n     ++\ttest_must_be_empty err &&\n     ++\ttest_subcommand ! git maintenance unregister --force <no-maint.event\n      +'\n      +\n       test_expect_success 'set up repository to clone' '\n 2:  7ab1914b830 ! 3:  e52b1282d93 scalar clone: add --no-maintenance option\n     @@ scalar.c: static int cmd_clone(int argc, const char **argv)\n       \t\tgoto cleanup;\n       \n      -\tres = register_dir(1);\n     ++\t/* If --no-maintenance, then skip maintenance command entirely. */\n      +\tres = register_dir(maintenance);\n       \n       cleanup:\n       \tfree(branch_to_free);\n      \n       ## t/t9211-scalar-clone.sh ##\n     -@@ t/t9211-scalar-clone.sh: test_expect_success 'scalar clone warns when background maintenance fails' '\n     - \tgrep \"could not turn on maintenance\" err\n     - '\n     - \n     +@@ t/t9211-scalar-clone.sh: test_expect_success 'progress without tty' '\n     + test_expect_success 'scalar clone warns when background maintenance fails' '\n     + \tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n     + \t\tscalar clone \"file://$(pwd)/to-clone\" maint-fail 2>err &&\n     +-\tgrep \"could not turn on maintenance\" err\n     ++\tgrep \"could not toggle maintenance\" err\n     ++'\n     ++\n      +test_expect_success 'scalar clone --no-maintenance' '\n      +\tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n     ++\tGIT_TRACE2_EVENT=\"$(pwd)/no-maint.event\" \\\n     ++\tGIT_TRACE2_EVENT_DEPTH=100 \\\n      +\t\tscalar clone --no-maintenance \"file://$(pwd)/to-clone\" no-maint 2>err &&\n     -+\t! grep \"could not turn on maintenance\" err\n     -+'\n     -+\n     ++\t! grep \"could not toggle maintenance\" err &&\n     ++\ttest_subcommand ! git maintenance unregister --force <no-maint.event\n     + '\n     + \n       test_expect_success '`scalar clone --no-src`' '\n     - \tscalar clone --src \"file://$(pwd)/to-clone\" with-src &&\n     - \tscalar clone --no-src \"file://$(pwd)/to-clone\" without-src &&\n -:  ----------- > 4:  6fac9c4c394 scalar reconfigure: add --no-maintenance option\n\n-- \ngitgitgadget\n"},{"id":"517259","messageId":"f3a3cfe3ef1404a98ee8113e98a25fd19cec3215.1746458844.git.gitgitgadget@gmail.com","threadId":"63372","inReplyTo":"pull.1913.v2.git.1746458844.gitgitgadget@gmail.com","subject":"[PATCH v2 1/4] scalar: customize register_dir()'s behavior","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-05-05T15:27:21Z","receivedAt":"2025-05-05T15:27:28Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <stolee@gmail.com>\n\nIn advance of adding a --[no-]maintenance option to several 'scalar'\nsubcommands, extend the register_dir() method to include an option for\nhow it should handle background maintenance.\n\nIt's important that we understand the context of toggle_maintenance()\nthat will enable _or disable_ maintenance depending on its input value.\nAdd a doc comment with this information.\n\nSimilarly, update register_dir() to either enable maintenance or leave\nit alone.\n\nSigned-off-by: Derrick Stolee <stolee@gmail.com>\n---\n scalar.c | 29 ++++++++++++++++++++++-------\n 1 file changed, 22 insertions(+), 7 deletions(-)\n\ndiff --git a/scalar.c b/scalar.c\nindex d359f08bb8e2..b20b063471a6 100644\n--- a/scalar.c\n+++ b/scalar.c\n@@ -209,6 +209,12 @@ static int set_recommended_config(int reconfigure)\n \treturn 0;\n }\n \n+/**\n+ * Enable or disable the maintenance mode for the current repository:\n+ *\n+ * * If 'enable' is nonzero, run 'git maintenance start'.\n+ * * If 'enable' is zero, run 'git maintenance unregister --force'.\n+ */\n static int toggle_maintenance(int enable)\n {\n \treturn run_git(\"maintenance\",\n@@ -259,7 +265,15 @@ static int stop_fsmonitor_daemon(void)\n \treturn 0;\n }\n \n-static int register_dir(void)\n+/**\n+ * Register the current directory as a Scalar enlistment, and set the\n+ * recommended configuration.\n+ *\n+ * * If 'maintenance' is non-zero, then enable background maintenance.\n+ * * If 'maintenance' is zero, then leave background maintenance as it is\n+ *   currently configured.\n+ */\n+static int register_dir(int maintenance)\n {\n \tif (add_or_remove_enlistment(1))\n \t\treturn error(_(\"could not add enlistment\"));\n@@ -267,8 +281,9 @@ static int register_dir(void)\n \tif (set_recommended_config(0))\n \t\treturn error(_(\"could not set recommended config\"));\n \n-\tif (toggle_maintenance(1))\n-\t\twarning(_(\"could not turn on maintenance\"));\n+\tif (maintenance &&\n+\t    toggle_maintenance(maintenance))\n+\t\twarning(_(\"could not toggle maintenance\"));\n \n \tif (have_fsmonitor_support() && start_fsmonitor_daemon()) {\n \t\treturn error(_(\"could not start the FSMonitor daemon\"));\n@@ -550,7 +565,7 @@ static int cmd_clone(int argc, const char **argv)\n \tif (res)\n \t\tgoto cleanup;\n \n-\tres = register_dir();\n+\tres = register_dir(1);\n \n cleanup:\n \tfree(branch_to_free);\n@@ -610,7 +625,7 @@ static int cmd_register(int argc, const char **argv)\n \n \tsetup_enlistment_directory(argc, argv, usage, options, NULL);\n \n-\treturn register_dir();\n+\treturn register_dir(1);\n }\n \n static int get_scalar_repos(const char *key, const char *value,\n@@ -803,13 +818,13 @@ static int cmd_run(int argc, const char **argv)\n \tstrbuf_release(&buf);\n \n \tif (i == 0)\n-\t\treturn register_dir();\n+\t\treturn register_dir(1);\n \n \tif (i > 0)\n \t\treturn run_git(\"maintenance\", \"run\",\n \t\t\t       \"--task\", tasks[i].task, NULL);\n \n-\tif (register_dir())\n+\tif (register_dir(1))\n \t\treturn -1;\n \tfor (i = 1; tasks[i].arg; i++)\n \t\tif (run_git(\"maintenance\", \"run\",\n-- \ngitgitgadget\n\n"},{"id":"517261","messageId":"1b99a559520a8bfed143c6fe8265f76b1ac4283c.1746458844.git.gitgitgadget@gmail.com","threadId":"63372","inReplyTo":"pull.1913.v2.git.1746458844.gitgitgadget@gmail.com","subject":"[PATCH v2 2/4] scalar register: add --no-maintenance option","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-05-05T15:27:22Z","receivedAt":"2025-05-05T15:27:29Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <stolee@gmail.com>\n\nWhen registering a repository with Scalar to get the latest opinionated\nconfiguration, the 'scalar register' command will also set up background\nmaintenance. This is a recommended feature for most user scenarios.\n\nHowever, this is not always recommended in some scenarios where\nbackground modifications may interfere with foreground activities.\nSpecifically, setting up a clone for use in automation may require doing\ncertain maintenance steps in the foreground that could become blocked by\nconcurrent background maintenance operations.\n\nAllow the user to specify --no-maintenance to 'scalar register'. This\nrequires updating the method prototype for register_dir(), so use the\ndefault of enabling this value when otherwise specified.\n\nSigned-off-by: Derrick Stolee <stolee@gmail.com>\n---\n Documentation/scalar.adoc |  8 +++++++-\n scalar.c                  |  8 ++++++--\n t/t9210-scalar.sh         | 13 ++++++++++++-\n 3 files changed, 25 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc\nindex 7e4259c6743f..b2b244a86499 100644\n--- a/Documentation/scalar.adoc\n+++ b/Documentation/scalar.adoc\n@@ -11,7 +11,7 @@ SYNOPSIS\n scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n \t[--[no-]src] <url> [<enlistment>]\n scalar list\n-scalar register [<enlistment>]\n+scalar register [--[no-]maintenance] [<enlistment>]\n scalar unregister [<enlistment>]\n scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [<enlistment>]\n scalar reconfigure [ --all | <enlistment> ]\n@@ -117,6 +117,12 @@ Note: when this subcommand is called in a worktree that is called `src/`, its\n parent directory is considered to be the Scalar enlistment. If the worktree is\n _not_ called `src/`, it itself will be considered to be the Scalar enlistment.\n \n+--[no-]maintenance::\n+\tBy default, `scalar register` configures the enlistment to use Git's\n+\tbackground maintenance feature. Use the `--no-maintenance` to skip\n+\tthis configuration. This does not disable any maintenance that may\n+\talready be enabled in other ways.\n+\n Unregister\n ~~~~~~~~~~\n \ndiff --git a/scalar.c b/scalar.c\nindex b20b063471a6..da0c46bc96cc 100644\n--- a/scalar.c\n+++ b/scalar.c\n@@ -612,11 +612,14 @@ static int cmd_list(int argc, const char **argv UNUSED)\n \n static int cmd_register(int argc, const char **argv)\n {\n+\tint maintenance = 1;\n \tstruct option options[] = {\n+\t\tOPT_BOOL(0, \"maintenance\", &maintenance,\n+\t\t\t N_(\"specify if background maintenance should be enabled\")),\n \t\tOPT_END(),\n \t};\n \tconst char * const usage[] = {\n-\t\tN_(\"scalar register [<enlistment>]\"),\n+\t\tN_(\"scalar register [--[no-]maintenance] [<enlistment>]\"),\n \t\tNULL\n \t};\n \n@@ -625,7 +628,8 @@ static int cmd_register(int argc, const char **argv)\n \n \tsetup_enlistment_directory(argc, argv, usage, options, NULL);\n \n-\treturn register_dir(1);\n+\t/* If --no-maintenance, then leave maintenance as-is. */\n+\treturn register_dir(maintenance);\n }\n \n static int get_scalar_repos(const char *key, const char *value,\ndiff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh\nindex a81662713eb8..89a6a2a24d8b 100755\n--- a/t/t9210-scalar.sh\n+++ b/t/t9210-scalar.sh\n@@ -108,7 +108,7 @@ test_expect_success 'scalar register warns when background maintenance fails' '\n \tgit init register-repo &&\n \tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n \t\tscalar register register-repo 2>err &&\n-\tgrep \"could not turn on maintenance\" err\n+\tgrep \"could not toggle maintenance\" err\n '\n \n test_expect_success 'scalar unregister' '\n@@ -129,6 +129,17 @@ test_expect_success 'scalar unregister' '\n \tscalar unregister vanish\n '\n \n+test_expect_success 'scalar register --no-maintenance' '\n+\tgit init register-no-maint &&\n+\tevent_log=\"$(pwd)/no-maint.event\" &&\n+\tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n+\tGIT_TRACE2_EVENT=\"$event_log\" \\\n+\tGIT_TRACE2_EVENT_DEPTH=100 \\\n+\t\tscalar register --no-maintenance register-no-maint 2>err &&\n+\ttest_must_be_empty err &&\n+\ttest_subcommand ! git maintenance unregister --force <no-maint.event\n+'\n+\n test_expect_success 'set up repository to clone' '\n \ttest_commit first &&\n \ttest_commit second &&\n-- \ngitgitgadget\n\n"},{"id":"517262","messageId":"e52b1282d93b795d077f169573487dca06b83bbe.1746458844.git.gitgitgadget@gmail.com","threadId":"63372","inReplyTo":"pull.1913.v2.git.1746458844.gitgitgadget@gmail.com","subject":"[PATCH v2 3/4] scalar clone: add --no-maintenance option","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-05-05T15:27:23Z","receivedAt":"2025-05-05T15:27:30Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <stolee@gmail.com>\n\nWhen creating a new enlistment via 'scalar clone', the default is to set\nup situations that work for most user scenarios. Background maintenance\nis one of those highly-recommended options for most users.\n\nHowever, when using 'scalar clone' to create an enlistment in a\ndifferent situation, such as prepping a VM image, it may be valuable to\ndisable background maintenance so the manual maintenance steps do not\nget blocked by concurrent background maintenance activities.\n\nAdd a new --no-maintenance option to 'scalar clone'.\n\nSigned-off-by: Derrick Stolee <stolee@gmail.com>\n---\n Documentation/scalar.adoc |  7 ++++++-\n scalar.c                  |  9 ++++++---\n t/t9211-scalar-clone.sh   | 11 ++++++++++-\n 3 files changed, 22 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc\nindex b2b244a86499..7753df3b4352 100644\n--- a/Documentation/scalar.adoc\n+++ b/Documentation/scalar.adoc\n@@ -9,7 +9,7 @@ SYNOPSIS\n --------\n [verse]\n scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n-\t[--[no-]src] <url> [<enlistment>]\n+\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]\n scalar list\n scalar register [--[no-]maintenance] [<enlistment>]\n scalar unregister [<enlistment>]\n@@ -97,6 +97,11 @@ cloning. If the HEAD at the remote did not point at any branch when\n \tA sparse-checkout is initialized by default. This behavior can be\n \tturned off via `--full-clone`.\n \n+--[no-]maintenance::\n+\tBy default, `scalar clone` configures the enlistment to use Git's\n+\tbackground maintenance feature. Use the `--no-maintenance` to skip\n+\tthis configuration.\n+\n List\n ~~~~\n \ndiff --git a/scalar.c b/scalar.c\nindex da0c46bc96cc..dd6e1447e086 100644\n--- a/scalar.c\n+++ b/scalar.c\n@@ -426,7 +426,7 @@ static int cmd_clone(int argc, const char **argv)\n \tconst char *branch = NULL;\n \tchar *branch_to_free = NULL;\n \tint full_clone = 0, single_branch = 0, show_progress = isatty(2);\n-\tint src = 1, tags = 1;\n+\tint src = 1, tags = 1, maintenance = 1;\n \tstruct option clone_options[] = {\n \t\tOPT_STRING('b', \"branch\", &branch, N_(\"<branch>\"),\n \t\t\t   N_(\"branch to checkout after clone\")),\n@@ -439,11 +439,13 @@ static int cmd_clone(int argc, const char **argv)\n \t\t\t N_(\"create repository within 'src' directory\")),\n \t\tOPT_BOOL(0, \"tags\", &tags,\n \t\t\t N_(\"specify if tags should be fetched during clone\")),\n+\t\tOPT_BOOL(0, \"maintenance\", &maintenance,\n+\t\t\t N_(\"specify if background maintenance should be enabled\")),\n \t\tOPT_END(),\n \t};\n \tconst char * const clone_usage[] = {\n \t\tN_(\"scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\\n\"\n-\t\t   \"\\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]\"),\n+\t\t   \"\\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]\"),\n \t\tNULL\n \t};\n \tconst char *url;\n@@ -565,7 +567,8 @@ static int cmd_clone(int argc, const char **argv)\n \tif (res)\n \t\tgoto cleanup;\n \n-\tres = register_dir(1);\n+\t/* If --no-maintenance, then skip maintenance command entirely. */\n+\tres = register_dir(maintenance);\n \n cleanup:\n \tfree(branch_to_free);\ndiff --git a/t/t9211-scalar-clone.sh b/t/t9211-scalar-clone.sh\nindex 01f71910f533..bfbf22a46218 100755\n--- a/t/t9211-scalar-clone.sh\n+++ b/t/t9211-scalar-clone.sh\n@@ -177,7 +177,16 @@ test_expect_success 'progress without tty' '\n test_expect_success 'scalar clone warns when background maintenance fails' '\n \tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n \t\tscalar clone \"file://$(pwd)/to-clone\" maint-fail 2>err &&\n-\tgrep \"could not turn on maintenance\" err\n+\tgrep \"could not toggle maintenance\" err\n+'\n+\n+test_expect_success 'scalar clone --no-maintenance' '\n+\tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n+\tGIT_TRACE2_EVENT=\"$(pwd)/no-maint.event\" \\\n+\tGIT_TRACE2_EVENT_DEPTH=100 \\\n+\t\tscalar clone --no-maintenance \"file://$(pwd)/to-clone\" no-maint 2>err &&\n+\t! grep \"could not toggle maintenance\" err &&\n+\ttest_subcommand ! git maintenance unregister --force <no-maint.event\n '\n \n test_expect_success '`scalar clone --no-src`' '\n-- \ngitgitgadget\n\n"},{"id":"517263","messageId":"6fac9c4c394b9882a2f7af6209af389edf384e4d.1746458844.git.gitgitgadget@gmail.com","threadId":"63372","inReplyTo":"pull.1913.v2.git.1746458844.gitgitgadget@gmail.com","subject":"[PATCH v2 4/4] scalar reconfigure: add --no-maintenance option","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-05-05T15:27:24Z","receivedAt":"2025-05-05T15:27:30Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <stolee@gmail.com>\n\nWhen users want to enable the latest and greatest configuration options\nrecommended by Scalar after a Git upgrade, 'scalar reconfigure --all' is\na great option that iterates over all repos in the multi-valued\n'scalar.repos' config key.\n\nHowever, this feature previously forced users to enable background\nmaintenance. In some environments this is not preferred.\n\nAdd a new --[no-]maintenance option to 'scalar reconfigure' that avoids\nrunning 'git maintenance start' on these enlistments.\n\nSigned-off-by: Derrick Stolee <stolee@gmail.com>\n---\n Documentation/scalar.adoc | 14 +++++++++++---\n scalar.c                  |  9 ++++++---\n t/t9210-scalar.sh         |  7 ++++++-\n 3 files changed, 23 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc\nindex 7753df3b4352..2868b01988e4 100644\n--- a/Documentation/scalar.adoc\n+++ b/Documentation/scalar.adoc\n@@ -14,7 +14,7 @@ scalar list\n scalar register [--[no-]maintenance] [<enlistment>]\n scalar unregister [<enlistment>]\n scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [<enlistment>]\n-scalar reconfigure [ --all | <enlistment> ]\n+scalar reconfigure [--[no-]maintenance] [ --all | <enlistment> ]\n scalar diagnose [<enlistment>]\n scalar delete <enlistment>\n \n@@ -160,8 +160,16 @@ After a Scalar upgrade, or when the configuration of a Scalar enlistment\n was somehow corrupted or changed by mistake, this subcommand allows to\n reconfigure the enlistment.\n \n-With the `--all` option, all enlistments currently registered with Scalar\n-will be reconfigured. Use this option after each Scalar upgrade.\n+--all::\n+\tWhen `--all` is specified, reconfigure all enlistments currently\n+\tregistered with Scalar by the `scalar.repo` config key. Use this\n+\toption after each upgrade to get the latest features.\n+\n+--[no-]maintenance::\n+\tBy default, Scalar configures the enlistment to use Git's\n+\tbackground maintenance feature. Use the `--no-maintenance` to skip\n+\tthis configuration and leave the repositories in whatever state is\n+\tcurrently configured.\n \n Diagnose\n ~~~~~~~~\ndiff --git a/scalar.c b/scalar.c\nindex dd6e1447e086..0b8a63f6e5a6 100644\n--- a/scalar.c\n+++ b/scalar.c\n@@ -667,14 +667,16 @@ static int remove_deleted_enlistment(struct strbuf *path)\n \n static int cmd_reconfigure(int argc, const char **argv)\n {\n-\tint all = 0;\n+\tint all = 0, maintenance = 1;\n \tstruct option options[] = {\n \t\tOPT_BOOL('a', \"all\", &all,\n \t\t\t N_(\"reconfigure all registered enlistments\")),\n+\t\tOPT_BOOL(0, \"maintenance\", &maintenance,\n+\t\t\t N_(\"specify if background maintenance should be enabled\")),\n \t\tOPT_END(),\n \t};\n \tconst char * const usage[] = {\n-\t\tN_(\"scalar reconfigure [--all | <enlistment>]\"),\n+\t\tN_(\"scalar reconfigure [--[no-]maintenance] [--all | <enlistment>]\"),\n \t\tNULL\n \t};\n \tstruct string_list scalar_repos = STRING_LIST_INIT_DUP;\n@@ -758,7 +760,8 @@ static int cmd_reconfigure(int argc, const char **argv)\n \t\tthe_repository = old_repo;\n \t\trepo_clear(&r);\n \n-\t\tif (toggle_maintenance(1) >= 0)\n+\t\tif (maintenance &&\n+\t\t    toggle_maintenance(1) >= 0)\n \t\t\tsucceeded = 1;\n \n loop_end:\ndiff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh\nindex 89a6a2a24d8b..34765a49fd07 100755\n--- a/t/t9210-scalar.sh\n+++ b/t/t9210-scalar.sh\n@@ -210,7 +210,12 @@ test_expect_success 'scalar reconfigure' '\n \tGIT_TRACE2_EVENT=\"$(pwd)/reconfigure\" scalar reconfigure -a &&\n \ttest_path_is_file one/src/cron.txt &&\n \ttest true = \"$(git -C one/src config core.preloadIndex)\" &&\n-\ttest_subcommand git maintenance start <reconfigure\n+\ttest_subcommand git maintenance start <reconfigure &&\n+\ttest_subcommand ! git maintenance unregister --force <reconfigure &&\n+\n+\tGIT_TRACE2_EVENT=\"$(pwd)/reconfigure-maint\" scalar reconfigure --no-maintenance -a &&\n+\ttest_subcommand ! git maintenance start <reconfigure-maint &&\n+\ttest_subcommand ! git maintenance unregister --force <reconfigure-maint\n '\n \n test_expect_success 'scalar reconfigure --all with includeIf.onbranch' '\n-- \ngitgitgadget\n"},{"id":"517281","messageId":"xmqqselin30f.fsf@gitster.g","threadId":"63372","inReplyTo":"6fac9c4c394b9882a2f7af6209af389edf384e4d.1746458844.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 4/4] scalar reconfigure: add --no-maintenance option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-05-05T21:47:44Z","receivedAt":"2025-05-05T21:47:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Derrick Stolee <stolee@gmail.com>\n>\n> When users want to enable the latest and greatest configuration options\n> recommended by Scalar after a Git upgrade, 'scalar reconfigure --all' is\n> a great option that iterates over all repos in the multi-valued\n> 'scalar.repos' config key.\n>\n> However, this feature previously forced users to enable background\n> maintenance. In some environments this is not preferred.\n>\n> Add a new --[no-]maintenance option to 'scalar reconfigure' that avoids\n> running 'git maintenance start' on these enlistments.\n\nIt makes sense for --maintenance option to be between enable and\ndisable when registering a new directory to the system, and when\ncloning somebody else's repository that causes a new directory to be\ncreated and enlisting the resulting new directory to the system.\n\nBut wouldn't users want \"leave maintenance-enrollment status alone\"\noption when reconfiguring an existing already enlisted directory?\n\nAs written, the design easily allows enabling of maintenance as part\nof reconfiguring, but disabling cannot be done the same way\n(i.e. individual enlistments need to be visited and their\nmaintenance disabled manually).\n\nIOW, it is a bit counter-intuitive\n\n> +--[no-]maintenance::\n> +\tBy default, Scalar configures the enlistment to use Git's\n> +\tbackground maintenance feature. Use the `--no-maintenance` to skip\n> +\tthis configuration and leave the repositories in whatever state is\n> +\tcurrently configured.\n\nthat for clone and register, --maintenance means \"enable\" and\n\"--no-maintenance\" means \"disable\", but when reconfiguring an\nalready registered directory, it would be natural to expect that\n\"--no-maintenance\" would explicitly tell the command to disable\nscheduled maintenance.\n\n> -\t\tif (toggle_maintenance(1) >= 0)\n> +\t\tif (maintenance &&\n> +\t\t    toggle_maintenance(1) >= 0)\n>  \t\t\tsucceeded = 1;\n\nA 3-way approach would make this part something like ...\n\n\tswitch (maintenance) {\n\tdefault:\tBUG(\"...\"); break;\n\tcase ENABLE:\tres = toggle_maintenance(1); break;\n\tcase DISABLE:\tres = toggle_maintenance(0); break;\n\tcase ASIS:\tres = 0; break;\n\t}\n\tif (res >= 0)\n\t\tsucceeded = 1;\n\n... which would allow people to easily say \"leave the existing\nmaintenance state alone\".\n\nI dunno.\n"},{"id":"517373","messageId":"3e307bf1-52ef-4280-bada-5cc50cc7a817@gmail.com","threadId":"63372","inReplyTo":"xmqqselin30f.fsf@gitster.g","subject":"Re: [PATCH v2 4/4] scalar reconfigure: add --no-maintenance option","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2025-05-06T18:00:02Z","receivedAt":"2025-05-06T18:00:04Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 5/5/2025 5:47 PM, Junio C Hamano wrote:\n> \"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n> \n>> From: Derrick Stolee <stolee@gmail.com>\n>>\n>> When users want to enable the latest and greatest configuration options\n>> recommended by Scalar after a Git upgrade, 'scalar reconfigure --all' is\n>> a great option that iterates over all repos in the multi-valued\n>> 'scalar.repos' config key.\n>>\n>> However, this feature previously forced users to enable background\n>> maintenance. In some environments this is not preferred.\n>>\n>> Add a new --[no-]maintenance option to 'scalar reconfigure' that avoids\n>> running 'git maintenance start' on these enlistments.\n> \n> It makes sense for --maintenance option to be between enable and\n> disable when registering a new directory to the system, and when\n> cloning somebody else's repository that causes a new directory to be\n> created and enlisting the resulting new directory to the system.\n> \n> But wouldn't users want \"leave maintenance-enrollment status alone\"\n> option when reconfiguring an existing already enlisted directory?\n> \n> As written, the design easily allows enabling of maintenance as part\n> of reconfiguring, but disabling cannot be done the same way\n> (i.e. individual enlistments need to be visited and their\n> maintenance disabled manually).\n> \n> IOW, it is a bit counter-intuitive\n> \n>> +--[no-]maintenance::\n>> +\tBy default, Scalar configures the enlistment to use Git's\n>> +\tbackground maintenance feature. Use the `--no-maintenance` to skip\n>> +\tthis configuration and leave the repositories in whatever state is\n>> +\tcurrently configured.\n> \n> that for clone and register, --maintenance means \"enable\" and\n> \"--no-maintenance\" means \"disable\", but when reconfiguring an\n> already registered directory, it would be natural to expect that\n> \"--no-maintenance\" would explicitly tell the command to disable\n> scheduled maintenance.\n\nI can see how this command is different from the other two, and thus\na three-way flipper can actually result in three different behaviors:\n\n> A 3-way approach would make this part something like ...\n> \n> \tswitch (maintenance) {\n> \tdefault:\tBUG(\"...\"); break;\n> \tcase ENABLE:\tres = toggle_maintenance(1); break;\n> \tcase DISABLE:\tres = toggle_maintenance(0); break;\n> \tcase ASIS:\tres = 0; break;\n> \t}\n> \tif (res >= 0)\n> \t\tsucceeded = 1;\n> \n> ... which would allow people to easily say \"leave the existing\n> maintenance state alone\".\n\nThis does mean that we'd need to have a different toggle from the\ntypical OPT_BOOL().\n\nWhat do you think about something of the form --maintenance=<option>\nwhere <option> is one of these:\n\n * \"enable\" (default) runs 'git maintenance start'\n * \"disable\" runs 'git maintenance unregister'\n * \"keep\" does not mess with maintenance config.\n\nDoes this sort of option seem to make sense? I'll wait to see if\nany further adjustments are recommended before I start rolling a\nnew version.\n\nThanks,\n-Stolee\n"},{"id":"517397","messageId":"xmqqselhfkq8.fsf@gitster.g","threadId":"63372","inReplyTo":"3e307bf1-52ef-4280-bada-5cc50cc7a817@gmail.com","subject":"Re: [PATCH v2 4/4] scalar reconfigure: add --no-maintenance option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-05-06T22:16:47Z","receivedAt":"2025-05-06T22:16:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Derrick Stolee <stolee@gmail.com> writes:\n\n> What do you think about something of the form --maintenance=<option>\n> where <option> is one of these:\n>\n>  * \"enable\" (default) runs 'git maintenance start'\n>  * \"disable\" runs 'git maintenance unregister'\n>  * \"keep\" does not mess with maintenance config.\n\nI think it makes superb sense.  \n\nCertainly much less ambiguous than \"--[no-]maintenance\" given that\nwe need to handle \"reconfigure\".  Without the need to deal with\n\"reconfigure\", it certainly is attractive if we can treat it as a\nsimple Boolean, though.\n\nIt is also tempting to just initialize the internal variable to -1\nand keep using OPT_BOOL() though.  Then after config and command\nline parsing is done, clone and register would turn -1 the user did\nnot touch into 1 (i.e. enable is default for these two operations),\nwhile reconfigure treats -1 as \"leave it as-is\".  It would make it\nvery cumbersome if we ever change our mind and give a default other\nthan \"leave it as-is\" to \"reconfigure\", but other than that minor\ndownside, it may be easier to use from end-user's point of view.\n\nI have no strong opinion between the two.\n\nThanks.\n\n\n\n\n\n    \n"},{"id":"517426","messageId":"pull.1913.v3.git.1746582637.gitgitgadget@gmail.com","threadId":"63372","inReplyTo":"pull.1913.v2.git.1746458844.gitgitgadget@gmail.com","subject":"[PATCH v3 0/4] scalar: add --no-maintenance option","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-05-07T01:50:33Z","receivedAt":"2025-05-07T01:50:40Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"These patches add a new --no-maintenance option to the scalar register and\nscalar clone commands. My motivation is based on setting up Scalar clones in\nautomated environments that set up a repo onto a disk image for use later.\nIf background maintenance runs during later setup steps, then this\nintroduces a variable that is unexpected at minimum and disruptive at worst.\nThe disruption comes in if the automation has steps to run git maintenance\nrun --task=<X> commands but those commands are blocked due to the\nmaintenance.lock file.\n\nFunctionally, these leave the default behavior as-is but allow disabling the\ngit maintenance start step when users opt-in to this difference. The idea of\nScalar is to recommend the best practices for a typical user, but allowing\ncustomization for expert users.\n\n\nUpdates in v2\n=============\n\n * The previous use of toggle_maintenance() in register_dir() would run the\n   'git maintenance unregister --force' command. There is a new patch 1 that\n   is explicit about whether this should or should not happen and new tests\n   are added to verify this behavior in the later patches.\n * A new patch 4 adds the --[no-]maintenance option to scalar reconfigure.\n\n\nUpdates in v3\n=============\n\n * Patch 4 converts the --[no-]maintenance option of scalar reconfigure to\n   --maintenance=<mode> to keep the default behavior the same (enable\n   maintenance) but also allow two other modes: disable maintenance and\n   leave maintenance as configured.\n\nThanks, -Stolee\n\nDerrick Stolee (4):\n  scalar: customize register_dir()'s behavior\n  scalar register: add --no-maintenance option\n  scalar clone: add --no-maintenance option\n  scalar reconfigure: add --maintenance=<mode> option\n\n Documentation/scalar.adoc | 32 ++++++++++++++++---\n scalar.c                  | 65 +++++++++++++++++++++++++++++++--------\n t/t9210-scalar.sh         | 26 ++++++++++++++--\n t/t9211-scalar-clone.sh   | 11 ++++++-\n 4 files changed, 114 insertions(+), 20 deletions(-)\n\n\nbase-commit: f65182a99e545d2f2bc22e6c1c2da192133b16a3\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1913%2Fderrickstolee%2Fscalar-no-maintenance-v3\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1913/derrickstolee/scalar-no-maintenance-v3\nPull-Request: https://github.com/gitgitgadget/git/pull/1913\n\nRange-diff vs v2:\n\n 1:  f3a3cfe3ef1 = 1:  f3a3cfe3ef1 scalar: customize register_dir()'s behavior\n 2:  1b99a559520 = 2:  1b99a559520 scalar register: add --no-maintenance option\n 3:  e52b1282d93 = 3:  e52b1282d93 scalar clone: add --no-maintenance option\n 4:  6fac9c4c394 ! 4:  684f04aaf7e scalar reconfigure: add --no-maintenance option\n     @@ Metadata\n      Author: Derrick Stolee <dstolee@microsoft.com>\n      \n       ## Commit message ##\n     -    scalar reconfigure: add --no-maintenance option\n     +    scalar reconfigure: add --maintenance=<mode> option\n      \n          When users want to enable the latest and greatest configuration options\n          recommended by Scalar after a Git upgrade, 'scalar reconfigure --all' is\n     @@ Commit message\n          However, this feature previously forced users to enable background\n          maintenance. In some environments this is not preferred.\n      \n     -    Add a new --[no-]maintenance option to 'scalar reconfigure' that avoids\n     -    running 'git maintenance start' on these enlistments.\n     +    Add a new --maintenance=<mode> option to 'scalar reconfigure' that\n     +    provides options for enabling (default), disabling, or leaving\n     +    background maintenance config as-is.\n      \n     +    Helped-by: Junio C Hamano <gitster@pobox.com>\n          Signed-off-by: Derrick Stolee <stolee@gmail.com>\n      \n       ## Documentation/scalar.adoc ##\n     @@ Documentation/scalar.adoc: scalar list\n       scalar unregister [<enlistment>]\n       scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [<enlistment>]\n      -scalar reconfigure [ --all | <enlistment> ]\n     -+scalar reconfigure [--[no-]maintenance] [ --all | <enlistment> ]\n     ++scalar reconfigure [--maintenance=<mode>] [ --all | <enlistment> ]\n       scalar diagnose [<enlistment>]\n       scalar delete <enlistment>\n       \n     @@ Documentation/scalar.adoc: After a Scalar upgrade, or when the configuration of\n      +\tregistered with Scalar by the `scalar.repo` config key. Use this\n      +\toption after each upgrade to get the latest features.\n      +\n     -+--[no-]maintenance::\n     ++--maintenance=<mode>::\n      +\tBy default, Scalar configures the enlistment to use Git's\n     -+\tbackground maintenance feature. Use the `--no-maintenance` to skip\n     -+\tthis configuration and leave the repositories in whatever state is\n     -+\tcurrently configured.\n     ++\tbackground maintenance feature; this is the same as using the\n     ++\t`--maintenance=enable` value for this option. Use the\n     ++\t`--maintenance=disable` to remove each considered enlistment\n     ++\tfrom background maintenance. Use `--maitnenance=keep' to leave\n     ++\tthe background maintenance configuration untouched for These\n     ++\trepositories.\n       \n       Diagnose\n       ~~~~~~~~\n      \n       ## scalar.c ##\n      @@ scalar.c: static int remove_deleted_enlistment(struct strbuf *path)\n     - \n       static int cmd_reconfigure(int argc, const char **argv)\n       {\n     --\tint all = 0;\n     -+\tint all = 0, maintenance = 1;\n     + \tint all = 0;\n     ++\tconst char *maintenance_str = NULL;\n     ++\tint maintenance = 1; /* Enable maintenance by default. */\n     ++\n       \tstruct option options[] = {\n       \t\tOPT_BOOL('a', \"all\", &all,\n       \t\t\t N_(\"reconfigure all registered enlistments\")),\n     -+\t\tOPT_BOOL(0, \"maintenance\", &maintenance,\n     -+\t\t\t N_(\"specify if background maintenance should be enabled\")),\n     ++\t\tOPT_STRING(0, \"maintenance\", &maintenance_str,\n     ++\t\t\t N_(\"<mode>\"),\n     ++\t\t\t N_(\"signal how to adjust background maintenance\")),\n       \t\tOPT_END(),\n       \t};\n       \tconst char * const usage[] = {\n      -\t\tN_(\"scalar reconfigure [--all | <enlistment>]\"),\n     -+\t\tN_(\"scalar reconfigure [--[no-]maintenance] [--all | <enlistment>]\"),\n     ++\t\tN_(\"scalar reconfigure [--maintenance=<mode>] [--all | <enlistment>]\"),\n       \t\tNULL\n       \t};\n       \tstruct string_list scalar_repos = STRING_LIST_INIT_DUP;\n     +@@ scalar.c: static int cmd_reconfigure(int argc, const char **argv)\n     + \t\tusage_msg_opt(_(\"--all or <enlistment>, but not both\"),\n     + \t\t\t      usage, options);\n     + \n     ++\tif (maintenance_str) {\n     ++\t\tif (!strcmp(maintenance_str, \"enable\"))\n     ++\t\t\tmaintenance = 1;\n     ++\t\telse if (!strcmp(maintenance_str, \"disable\"))\n     ++\t\t\tmaintenance = 0;\n     ++\t\telse if (!strcmp(maintenance_str, \"keep\"))\n     ++\t\t\tmaintenance = -1;\n     ++\t\telse\n     ++\t\t\tdie(_(\"unknown mode for --maintenance option: %s\"),\n     ++\t\t\t    maintenance_str);\n     ++\t}\n     ++\n     + \tgit_config(get_scalar_repos, &scalar_repos);\n     + \n     + \tfor (size_t i = 0; i < scalar_repos.nr; i++) {\n      @@ scalar.c: static int cmd_reconfigure(int argc, const char **argv)\n       \t\tthe_repository = old_repo;\n       \t\trepo_clear(&r);\n       \n      -\t\tif (toggle_maintenance(1) >= 0)\n     -+\t\tif (maintenance &&\n     -+\t\t    toggle_maintenance(1) >= 0)\n     ++\t\tif (maintenance >= 0 &&\n     ++\t\t    toggle_maintenance(maintenance) >= 0)\n       \t\t\tsucceeded = 1;\n       \n       loop_end:\n     @@ t/t9210-scalar.sh: test_expect_success 'scalar reconfigure' '\n      +\ttest_subcommand git maintenance start <reconfigure &&\n      +\ttest_subcommand ! git maintenance unregister --force <reconfigure &&\n      +\n     -+\tGIT_TRACE2_EVENT=\"$(pwd)/reconfigure-maint\" scalar reconfigure --no-maintenance -a &&\n     -+\ttest_subcommand ! git maintenance start <reconfigure-maint &&\n     -+\ttest_subcommand ! git maintenance unregister --force <reconfigure-maint\n     ++\tGIT_TRACE2_EVENT=\"$(pwd)/reconfigure-maint-disable\" \\\n     ++\t\tscalar reconfigure -a --maintenance=disable &&\n     ++\ttest_subcommand ! git maintenance start <reconfigure-maint-disable &&\n     ++\ttest_subcommand git maintenance unregister --force <reconfigure-maint-disable &&\n     ++\n     ++\tGIT_TRACE2_EVENT=\"$(pwd)/reconfigure-maint-keep\" \\\n     ++\t\tscalar reconfigure --maintenance=keep -a &&\n     ++\ttest_subcommand ! git maintenance start <reconfigure-maint-keep &&\n     ++\ttest_subcommand ! git maintenance unregister --force <reconfigure-maint-keep\n       '\n       \n       test_expect_success 'scalar reconfigure --all with includeIf.onbranch' '\n\n-- \ngitgitgadget\n"},{"id":"517427","messageId":"f3a3cfe3ef1404a98ee8113e98a25fd19cec3215.1746582637.git.gitgitgadget@gmail.com","threadId":"63372","inReplyTo":"pull.1913.v3.git.1746582637.gitgitgadget@gmail.com","subject":"[PATCH v3 1/4] scalar: customize register_dir()'s behavior","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-05-07T01:50:34Z","receivedAt":"2025-05-07T01:50:41Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <stolee@gmail.com>\n\nIn advance of adding a --[no-]maintenance option to several 'scalar'\nsubcommands, extend the register_dir() method to include an option for\nhow it should handle background maintenance.\n\nIt's important that we understand the context of toggle_maintenance()\nthat will enable _or disable_ maintenance depending on its input value.\nAdd a doc comment with this information.\n\nSimilarly, update register_dir() to either enable maintenance or leave\nit alone.\n\nSigned-off-by: Derrick Stolee <stolee@gmail.com>\n---\n scalar.c | 29 ++++++++++++++++++++++-------\n 1 file changed, 22 insertions(+), 7 deletions(-)\n\ndiff --git a/scalar.c b/scalar.c\nindex d359f08bb8e2..b20b063471a6 100644\n--- a/scalar.c\n+++ b/scalar.c\n@@ -209,6 +209,12 @@ static int set_recommended_config(int reconfigure)\n \treturn 0;\n }\n \n+/**\n+ * Enable or disable the maintenance mode for the current repository:\n+ *\n+ * * If 'enable' is nonzero, run 'git maintenance start'.\n+ * * If 'enable' is zero, run 'git maintenance unregister --force'.\n+ */\n static int toggle_maintenance(int enable)\n {\n \treturn run_git(\"maintenance\",\n@@ -259,7 +265,15 @@ static int stop_fsmonitor_daemon(void)\n \treturn 0;\n }\n \n-static int register_dir(void)\n+/**\n+ * Register the current directory as a Scalar enlistment, and set the\n+ * recommended configuration.\n+ *\n+ * * If 'maintenance' is non-zero, then enable background maintenance.\n+ * * If 'maintenance' is zero, then leave background maintenance as it is\n+ *   currently configured.\n+ */\n+static int register_dir(int maintenance)\n {\n \tif (add_or_remove_enlistment(1))\n \t\treturn error(_(\"could not add enlistment\"));\n@@ -267,8 +281,9 @@ static int register_dir(void)\n \tif (set_recommended_config(0))\n \t\treturn error(_(\"could not set recommended config\"));\n \n-\tif (toggle_maintenance(1))\n-\t\twarning(_(\"could not turn on maintenance\"));\n+\tif (maintenance &&\n+\t    toggle_maintenance(maintenance))\n+\t\twarning(_(\"could not toggle maintenance\"));\n \n \tif (have_fsmonitor_support() && start_fsmonitor_daemon()) {\n \t\treturn error(_(\"could not start the FSMonitor daemon\"));\n@@ -550,7 +565,7 @@ static int cmd_clone(int argc, const char **argv)\n \tif (res)\n \t\tgoto cleanup;\n \n-\tres = register_dir();\n+\tres = register_dir(1);\n \n cleanup:\n \tfree(branch_to_free);\n@@ -610,7 +625,7 @@ static int cmd_register(int argc, const char **argv)\n \n \tsetup_enlistment_directory(argc, argv, usage, options, NULL);\n \n-\treturn register_dir();\n+\treturn register_dir(1);\n }\n \n static int get_scalar_repos(const char *key, const char *value,\n@@ -803,13 +818,13 @@ static int cmd_run(int argc, const char **argv)\n \tstrbuf_release(&buf);\n \n \tif (i == 0)\n-\t\treturn register_dir();\n+\t\treturn register_dir(1);\n \n \tif (i > 0)\n \t\treturn run_git(\"maintenance\", \"run\",\n \t\t\t       \"--task\", tasks[i].task, NULL);\n \n-\tif (register_dir())\n+\tif (register_dir(1))\n \t\treturn -1;\n \tfor (i = 1; tasks[i].arg; i++)\n \t\tif (run_git(\"maintenance\", \"run\",\n-- \ngitgitgadget\n\n"},{"id":"517428","messageId":"1b99a559520a8bfed143c6fe8265f76b1ac4283c.1746582637.git.gitgitgadget@gmail.com","threadId":"63372","inReplyTo":"pull.1913.v3.git.1746582637.gitgitgadget@gmail.com","subject":"[PATCH v3 2/4] scalar register: add --no-maintenance option","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-05-07T01:50:35Z","receivedAt":"2025-05-07T01:50:42Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <stolee@gmail.com>\n\nWhen registering a repository with Scalar to get the latest opinionated\nconfiguration, the 'scalar register' command will also set up background\nmaintenance. This is a recommended feature for most user scenarios.\n\nHowever, this is not always recommended in some scenarios where\nbackground modifications may interfere with foreground activities.\nSpecifically, setting up a clone for use in automation may require doing\ncertain maintenance steps in the foreground that could become blocked by\nconcurrent background maintenance operations.\n\nAllow the user to specify --no-maintenance to 'scalar register'. This\nrequires updating the method prototype for register_dir(), so use the\ndefault of enabling this value when otherwise specified.\n\nSigned-off-by: Derrick Stolee <stolee@gmail.com>\n---\n Documentation/scalar.adoc |  8 +++++++-\n scalar.c                  |  8 ++++++--\n t/t9210-scalar.sh         | 13 ++++++++++++-\n 3 files changed, 25 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc\nindex 7e4259c6743f..b2b244a86499 100644\n--- a/Documentation/scalar.adoc\n+++ b/Documentation/scalar.adoc\n@@ -11,7 +11,7 @@ SYNOPSIS\n scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n \t[--[no-]src] <url> [<enlistment>]\n scalar list\n-scalar register [<enlistment>]\n+scalar register [--[no-]maintenance] [<enlistment>]\n scalar unregister [<enlistment>]\n scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [<enlistment>]\n scalar reconfigure [ --all | <enlistment> ]\n@@ -117,6 +117,12 @@ Note: when this subcommand is called in a worktree that is called `src/`, its\n parent directory is considered to be the Scalar enlistment. If the worktree is\n _not_ called `src/`, it itself will be considered to be the Scalar enlistment.\n \n+--[no-]maintenance::\n+\tBy default, `scalar register` configures the enlistment to use Git's\n+\tbackground maintenance feature. Use the `--no-maintenance` to skip\n+\tthis configuration. This does not disable any maintenance that may\n+\talready be enabled in other ways.\n+\n Unregister\n ~~~~~~~~~~\n \ndiff --git a/scalar.c b/scalar.c\nindex b20b063471a6..da0c46bc96cc 100644\n--- a/scalar.c\n+++ b/scalar.c\n@@ -612,11 +612,14 @@ static int cmd_list(int argc, const char **argv UNUSED)\n \n static int cmd_register(int argc, const char **argv)\n {\n+\tint maintenance = 1;\n \tstruct option options[] = {\n+\t\tOPT_BOOL(0, \"maintenance\", &maintenance,\n+\t\t\t N_(\"specify if background maintenance should be enabled\")),\n \t\tOPT_END(),\n \t};\n \tconst char * const usage[] = {\n-\t\tN_(\"scalar register [<enlistment>]\"),\n+\t\tN_(\"scalar register [--[no-]maintenance] [<enlistment>]\"),\n \t\tNULL\n \t};\n \n@@ -625,7 +628,8 @@ static int cmd_register(int argc, const char **argv)\n \n \tsetup_enlistment_directory(argc, argv, usage, options, NULL);\n \n-\treturn register_dir(1);\n+\t/* If --no-maintenance, then leave maintenance as-is. */\n+\treturn register_dir(maintenance);\n }\n \n static int get_scalar_repos(const char *key, const char *value,\ndiff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh\nindex a81662713eb8..89a6a2a24d8b 100755\n--- a/t/t9210-scalar.sh\n+++ b/t/t9210-scalar.sh\n@@ -108,7 +108,7 @@ test_expect_success 'scalar register warns when background maintenance fails' '\n \tgit init register-repo &&\n \tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n \t\tscalar register register-repo 2>err &&\n-\tgrep \"could not turn on maintenance\" err\n+\tgrep \"could not toggle maintenance\" err\n '\n \n test_expect_success 'scalar unregister' '\n@@ -129,6 +129,17 @@ test_expect_success 'scalar unregister' '\n \tscalar unregister vanish\n '\n \n+test_expect_success 'scalar register --no-maintenance' '\n+\tgit init register-no-maint &&\n+\tevent_log=\"$(pwd)/no-maint.event\" &&\n+\tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n+\tGIT_TRACE2_EVENT=\"$event_log\" \\\n+\tGIT_TRACE2_EVENT_DEPTH=100 \\\n+\t\tscalar register --no-maintenance register-no-maint 2>err &&\n+\ttest_must_be_empty err &&\n+\ttest_subcommand ! git maintenance unregister --force <no-maint.event\n+'\n+\n test_expect_success 'set up repository to clone' '\n \ttest_commit first &&\n \ttest_commit second &&\n-- \ngitgitgadget\n\n"},{"id":"517429","messageId":"e52b1282d93b795d077f169573487dca06b83bbe.1746582637.git.gitgitgadget@gmail.com","threadId":"63372","inReplyTo":"pull.1913.v3.git.1746582637.gitgitgadget@gmail.com","subject":"[PATCH v3 3/4] scalar clone: add --no-maintenance option","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-05-07T01:50:36Z","receivedAt":"2025-05-07T01:50:42Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <stolee@gmail.com>\n\nWhen creating a new enlistment via 'scalar clone', the default is to set\nup situations that work for most user scenarios. Background maintenance\nis one of those highly-recommended options for most users.\n\nHowever, when using 'scalar clone' to create an enlistment in a\ndifferent situation, such as prepping a VM image, it may be valuable to\ndisable background maintenance so the manual maintenance steps do not\nget blocked by concurrent background maintenance activities.\n\nAdd a new --no-maintenance option to 'scalar clone'.\n\nSigned-off-by: Derrick Stolee <stolee@gmail.com>\n---\n Documentation/scalar.adoc |  7 ++++++-\n scalar.c                  |  9 ++++++---\n t/t9211-scalar-clone.sh   | 11 ++++++++++-\n 3 files changed, 22 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc\nindex b2b244a86499..7753df3b4352 100644\n--- a/Documentation/scalar.adoc\n+++ b/Documentation/scalar.adoc\n@@ -9,7 +9,7 @@ SYNOPSIS\n --------\n [verse]\n scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n-\t[--[no-]src] <url> [<enlistment>]\n+\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]\n scalar list\n scalar register [--[no-]maintenance] [<enlistment>]\n scalar unregister [<enlistment>]\n@@ -97,6 +97,11 @@ cloning. If the HEAD at the remote did not point at any branch when\n \tA sparse-checkout is initialized by default. This behavior can be\n \tturned off via `--full-clone`.\n \n+--[no-]maintenance::\n+\tBy default, `scalar clone` configures the enlistment to use Git's\n+\tbackground maintenance feature. Use the `--no-maintenance` to skip\n+\tthis configuration.\n+\n List\n ~~~~\n \ndiff --git a/scalar.c b/scalar.c\nindex da0c46bc96cc..dd6e1447e086 100644\n--- a/scalar.c\n+++ b/scalar.c\n@@ -426,7 +426,7 @@ static int cmd_clone(int argc, const char **argv)\n \tconst char *branch = NULL;\n \tchar *branch_to_free = NULL;\n \tint full_clone = 0, single_branch = 0, show_progress = isatty(2);\n-\tint src = 1, tags = 1;\n+\tint src = 1, tags = 1, maintenance = 1;\n \tstruct option clone_options[] = {\n \t\tOPT_STRING('b', \"branch\", &branch, N_(\"<branch>\"),\n \t\t\t   N_(\"branch to checkout after clone\")),\n@@ -439,11 +439,13 @@ static int cmd_clone(int argc, const char **argv)\n \t\t\t N_(\"create repository within 'src' directory\")),\n \t\tOPT_BOOL(0, \"tags\", &tags,\n \t\t\t N_(\"specify if tags should be fetched during clone\")),\n+\t\tOPT_BOOL(0, \"maintenance\", &maintenance,\n+\t\t\t N_(\"specify if background maintenance should be enabled\")),\n \t\tOPT_END(),\n \t};\n \tconst char * const clone_usage[] = {\n \t\tN_(\"scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\\n\"\n-\t\t   \"\\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]\"),\n+\t\t   \"\\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]\"),\n \t\tNULL\n \t};\n \tconst char *url;\n@@ -565,7 +567,8 @@ static int cmd_clone(int argc, const char **argv)\n \tif (res)\n \t\tgoto cleanup;\n \n-\tres = register_dir(1);\n+\t/* If --no-maintenance, then skip maintenance command entirely. */\n+\tres = register_dir(maintenance);\n \n cleanup:\n \tfree(branch_to_free);\ndiff --git a/t/t9211-scalar-clone.sh b/t/t9211-scalar-clone.sh\nindex 01f71910f533..bfbf22a46218 100755\n--- a/t/t9211-scalar-clone.sh\n+++ b/t/t9211-scalar-clone.sh\n@@ -177,7 +177,16 @@ test_expect_success 'progress without tty' '\n test_expect_success 'scalar clone warns when background maintenance fails' '\n \tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n \t\tscalar clone \"file://$(pwd)/to-clone\" maint-fail 2>err &&\n-\tgrep \"could not turn on maintenance\" err\n+\tgrep \"could not toggle maintenance\" err\n+'\n+\n+test_expect_success 'scalar clone --no-maintenance' '\n+\tGIT_TEST_MAINT_SCHEDULER=\"crontab:false,launchctl:false,schtasks:false\" \\\n+\tGIT_TRACE2_EVENT=\"$(pwd)/no-maint.event\" \\\n+\tGIT_TRACE2_EVENT_DEPTH=100 \\\n+\t\tscalar clone --no-maintenance \"file://$(pwd)/to-clone\" no-maint 2>err &&\n+\t! grep \"could not toggle maintenance\" err &&\n+\ttest_subcommand ! git maintenance unregister --force <no-maint.event\n '\n \n test_expect_success '`scalar clone --no-src`' '\n-- \ngitgitgadget\n\n"},{"id":"517430","messageId":"684f04aaf7e87f22ab0b00a4fd42d2943304ef04.1746582637.git.gitgitgadget@gmail.com","threadId":"63372","inReplyTo":"pull.1913.v3.git.1746582637.gitgitgadget@gmail.com","subject":"[PATCH v3 4/4] scalar reconfigure: add --maintenance=<mode> option","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-05-07T01:50:37Z","receivedAt":"2025-05-07T01:50:44Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <stolee@gmail.com>\n\nWhen users want to enable the latest and greatest configuration options\nrecommended by Scalar after a Git upgrade, 'scalar reconfigure --all' is\na great option that iterates over all repos in the multi-valued\n'scalar.repos' config key.\n\nHowever, this feature previously forced users to enable background\nmaintenance. In some environments this is not preferred.\n\nAdd a new --maintenance=<mode> option to 'scalar reconfigure' that\nprovides options for enabling (default), disabling, or leaving\nbackground maintenance config as-is.\n\nHelped-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Derrick Stolee <stolee@gmail.com>\n---\n Documentation/scalar.adoc | 17 ++++++++++++++---\n scalar.c                  | 23 +++++++++++++++++++++--\n t/t9210-scalar.sh         | 13 ++++++++++++-\n 3 files changed, 47 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc\nindex 7753df3b4352..387527be1ea5 100644\n--- a/Documentation/scalar.adoc\n+++ b/Documentation/scalar.adoc\n@@ -14,7 +14,7 @@ scalar list\n scalar register [--[no-]maintenance] [<enlistment>]\n scalar unregister [<enlistment>]\n scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [<enlistment>]\n-scalar reconfigure [ --all | <enlistment> ]\n+scalar reconfigure [--maintenance=<mode>] [ --all | <enlistment> ]\n scalar diagnose [<enlistment>]\n scalar delete <enlistment>\n \n@@ -160,8 +160,19 @@ After a Scalar upgrade, or when the configuration of a Scalar enlistment\n was somehow corrupted or changed by mistake, this subcommand allows to\n reconfigure the enlistment.\n \n-With the `--all` option, all enlistments currently registered with Scalar\n-will be reconfigured. Use this option after each Scalar upgrade.\n+--all::\n+\tWhen `--all` is specified, reconfigure all enlistments currently\n+\tregistered with Scalar by the `scalar.repo` config key. Use this\n+\toption after each upgrade to get the latest features.\n+\n+--maintenance=<mode>::\n+\tBy default, Scalar configures the enlistment to use Git's\n+\tbackground maintenance feature; this is the same as using the\n+\t`--maintenance=enable` value for this option. Use the\n+\t`--maintenance=disable` to remove each considered enlistment\n+\tfrom background maintenance. Use `--maitnenance=keep' to leave\n+\tthe background maintenance configuration untouched for These\n+\trepositories.\n \n Diagnose\n ~~~~~~~~\ndiff --git a/scalar.c b/scalar.c\nindex dd6e1447e086..847d2dd2f58a 100644\n--- a/scalar.c\n+++ b/scalar.c\n@@ -668,13 +668,19 @@ static int remove_deleted_enlistment(struct strbuf *path)\n static int cmd_reconfigure(int argc, const char **argv)\n {\n \tint all = 0;\n+\tconst char *maintenance_str = NULL;\n+\tint maintenance = 1; /* Enable maintenance by default. */\n+\n \tstruct option options[] = {\n \t\tOPT_BOOL('a', \"all\", &all,\n \t\t\t N_(\"reconfigure all registered enlistments\")),\n+\t\tOPT_STRING(0, \"maintenance\", &maintenance_str,\n+\t\t\t N_(\"<mode>\"),\n+\t\t\t N_(\"signal how to adjust background maintenance\")),\n \t\tOPT_END(),\n \t};\n \tconst char * const usage[] = {\n-\t\tN_(\"scalar reconfigure [--all | <enlistment>]\"),\n+\t\tN_(\"scalar reconfigure [--maintenance=<mode>] [--all | <enlistment>]\"),\n \t\tNULL\n \t};\n \tstruct string_list scalar_repos = STRING_LIST_INIT_DUP;\n@@ -694,6 +700,18 @@ static int cmd_reconfigure(int argc, const char **argv)\n \t\tusage_msg_opt(_(\"--all or <enlistment>, but not both\"),\n \t\t\t      usage, options);\n \n+\tif (maintenance_str) {\n+\t\tif (!strcmp(maintenance_str, \"enable\"))\n+\t\t\tmaintenance = 1;\n+\t\telse if (!strcmp(maintenance_str, \"disable\"))\n+\t\t\tmaintenance = 0;\n+\t\telse if (!strcmp(maintenance_str, \"keep\"))\n+\t\t\tmaintenance = -1;\n+\t\telse\n+\t\t\tdie(_(\"unknown mode for --maintenance option: %s\"),\n+\t\t\t    maintenance_str);\n+\t}\n+\n \tgit_config(get_scalar_repos, &scalar_repos);\n \n \tfor (size_t i = 0; i < scalar_repos.nr; i++) {\n@@ -758,7 +776,8 @@ static int cmd_reconfigure(int argc, const char **argv)\n \t\tthe_repository = old_repo;\n \t\trepo_clear(&r);\n \n-\t\tif (toggle_maintenance(1) >= 0)\n+\t\tif (maintenance >= 0 &&\n+\t\t    toggle_maintenance(maintenance) >= 0)\n \t\t\tsucceeded = 1;\n \n loop_end:\ndiff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh\nindex 89a6a2a24d8b..bd6f0c40d229 100755\n--- a/t/t9210-scalar.sh\n+++ b/t/t9210-scalar.sh\n@@ -210,7 +210,18 @@ test_expect_success 'scalar reconfigure' '\n \tGIT_TRACE2_EVENT=\"$(pwd)/reconfigure\" scalar reconfigure -a &&\n \ttest_path_is_file one/src/cron.txt &&\n \ttest true = \"$(git -C one/src config core.preloadIndex)\" &&\n-\ttest_subcommand git maintenance start <reconfigure\n+\ttest_subcommand git maintenance start <reconfigure &&\n+\ttest_subcommand ! git maintenance unregister --force <reconfigure &&\n+\n+\tGIT_TRACE2_EVENT=\"$(pwd)/reconfigure-maint-disable\" \\\n+\t\tscalar reconfigure -a --maintenance=disable &&\n+\ttest_subcommand ! git maintenance start <reconfigure-maint-disable &&\n+\ttest_subcommand git maintenance unregister --force <reconfigure-maint-disable &&\n+\n+\tGIT_TRACE2_EVENT=\"$(pwd)/reconfigure-maint-keep\" \\\n+\t\tscalar reconfigure --maintenance=keep -a &&\n+\ttest_subcommand ! git maintenance start <reconfigure-maint-keep &&\n+\ttest_subcommand ! git maintenance unregister --force <reconfigure-maint-keep\n '\n \n test_expect_success 'scalar reconfigure --all with includeIf.onbranch' '\n-- \ngitgitgadget\n"},{"id":"517522","messageId":"xmqqcyckayb4.fsf@gitster.g","threadId":"63372","inReplyTo":"684f04aaf7e87f22ab0b00a4fd42d2943304ef04.1746582637.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v3 4/4] scalar reconfigure: add --maintenance=<mode> option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-05-07T21:46:55Z","receivedAt":"2025-05-07T21:46:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> Add a new --maintenance=<mode> option to 'scalar reconfigure' that\n> provides options for enabling (default), disabling, or leaving\n> background maintenance config as-is.\n\nHmph, this is a bit unexpected.\n\n> +--maintenance=<mode>::\n> +\tBy default, Scalar configures the enlistment to use Git's\n> +\tbackground maintenance feature; this is the same as using the\n> +\t`--maintenance=enable` value for this option. Use the\n> +\t`--maintenance=disable` to remove each considered enlistment\n> +\tfrom background maintenance. Use `--maitnenance=keep' to leave\n> +\tthe background maintenance configuration untouched for These\n> +\trepositories.\n\nIf I understand it correctly, here is the only place that the users\ncan learn what the valid choices are, and it is not even an\nenumeration.  They are forced to read the entire paragraph to learn\nwhat the choices are.\n\n> +\t\tOPT_STRING(0, \"maintenance\", &maintenance_str,\n> +\t\t\t N_(\"<mode>\"),\n> +\t\t\t N_(\"signal how to adjust background maintenance\")),\n\nAnd there is no hint what are the right <mode> strings are.\n\n>  \tconst char * const usage[] = {\n> -\t\tN_(\"scalar reconfigure [--all | <enlistment>]\"),\n> +\t\tN_(\"scalar reconfigure [--maintenance=<mode>] [--all | <enlistment>]\"),\n>  \t\tNULL\n>  \t};\n\nSo \"scalar reconfigure -h\" would not tell readers what the right\nchoices are, either.\n\n> +\tif (maintenance_str) {\n> +\t\tif (!strcmp(maintenance_str, \"enable\"))\n> +\t\t\tmaintenance = 1;\n> +\t\telse if (!strcmp(maintenance_str, \"disable\"))\n> +\t\t\tmaintenance = 0;\n> +\t\telse if (!strcmp(maintenance_str, \"keep\"))\n> +\t\t\tmaintenance = -1;\n> +\t\telse\n> +\t\t\tdie(_(\"unknown mode for --maintenance option: %s\"),\n> +\t\t\t    maintenance_str);\n\nThose who say \"scalar reconfigure --maintenance=yes\" gets this\nmessage that tells 'yes' is not a known mode, without saying that\nthey meant 'enable'.  \n\nThe --opt=<mode> interface is good when we expect the vocabulary for\n<mode> to grow, but I am not sure if it is warranted in this case.\nIs there a strong reason why 'reconfigure' MUST enable the\nmaintenance by default, even if it were originally disabled in the\nenlistment?  If there isn't, initializing maintenance to -1 and\nsetting it with OPT_BOOL() would make the UI consistent with the\nregister and clone subcommands, and also we can lose the above block\nto parse out a string.  Also the code below ...\n\n\n> @@ -758,7 +776,8 @@ static int cmd_reconfigure(int argc, const char **argv)\n>  \t\tthe_repository = old_repo;\n>  \t\trepo_clear(&r);\n>  \n> -\t\tif (toggle_maintenance(1) >= 0)\n> +\t\tif (maintenance >= 0 &&\n> +\t\t    toggle_maintenance(maintenance) >= 0)\n>  \t\t\tsucceeded = 1;\n\n... which does make perfect sense, would still be applicable.\n\nI dunno.  I just feel that 3-way \"mode\" interface is too much hassle\nto get right (e.g., give hints to guide the users who forgot what\nmodes are available and how they are spelled) for this code path.\n\nAnyway, will replace the previous round with this one.\n\nThanks.\n\n\n"},{"id":"517852","messageId":"35ecaa1d-589f-4d28-9d97-78bae8de2d41@gmail.com","threadId":"63372","inReplyTo":"xmqqcyckayb4.fsf@gitster.g","subject":"Re: [PATCH v3 4/4] scalar reconfigure: add --maintenance=<mode> option","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2025-05-12T14:34:22Z","receivedAt":"2025-05-12T14:34:24Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 5/7/25 5:46 PM, Junio C Hamano wrote:\n> \"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n> \n>> Add a new --maintenance=<mode> option to 'scalar reconfigure' that\n>> provides options for enabling (default), disabling, or leaving\n>> background maintenance config as-is.\n> \n> Hmph, this is a bit unexpected.\n> \n>> +--maintenance=<mode>::\n>> +\tBy default, Scalar configures the enlistment to use Git's\n>> +\tbackground maintenance feature; this is the same as using the\n>> +\t`--maintenance=enable` value for this option. Use the\n>> +\t`--maintenance=disable` to remove each considered enlistment\n>> +\tfrom background maintenance. Use `--maitnenance=keep' to leave\n>> +\tthe background maintenance configuration untouched for These\n>> +\trepositories.\n> \n> If I understand it correctly, here is the only place that the users\n> can learn what the valid choices are, and it is not even an\n> enumeration.  They are forced to read the entire paragraph to learn\n> what the choices are.\n\nI suppose this could be fixed by changing the `<mode>` to be of the\nform \"[enable|disable|keep]\".\n\n>> +\t\tOPT_STRING(0, \"maintenance\", &maintenance_str,\n>> +\t\t\t N_(\"<mode>\"),\n>> +\t\t\t N_(\"signal how to adjust background maintenance\")),\n> \n> And there is no hint what are the right <mode> strings are.\n> \n>>   \tconst char * const usage[] = {\n>> -\t\tN_(\"scalar reconfigure [--all | <enlistment>]\"),\n>> +\t\tN_(\"scalar reconfigure [--maintenance=<mode>] [--all | <enlistment>]\"),\n>>   \t\tNULL\n>>   \t};\n> \n> So \"scalar reconfigure -h\" would not tell readers what the right\n> choices are, either.\n> \n>> +\tif (maintenance_str) {\n>> +\t\tif (!strcmp(maintenance_str, \"enable\"))\n>> +\t\t\tmaintenance = 1;\n>> +\t\telse if (!strcmp(maintenance_str, \"disable\"))\n>> +\t\t\tmaintenance = 0;\n>> +\t\telse if (!strcmp(maintenance_str, \"keep\"))\n>> +\t\t\tmaintenance = -1;\n>> +\t\telse\n>> +\t\t\tdie(_(\"unknown mode for --maintenance option: %s\"),\n>> +\t\t\t    maintenance_str);\n> \n> Those who say \"scalar reconfigure --maintenance=yes\" gets this\n> message that tells 'yes' is not a known mode, without saying that\n> they meant 'enable'.\n> \n> The --opt=<mode> interface is good when we expect the vocabulary for\n> <mode> to grow, but I am not sure if it is warranted in this case.\n> Is there a strong reason why 'reconfigure' MUST enable the\n> maintenance by default, even if it were originally disabled in the\n> enlistment?  If there isn't, initializing maintenance to -1 and\n> setting it with OPT_BOOL() would make the UI consistent with the\n> register and clone subcommands, and also we can lose the above block\n> to parse out a string.  Also the code below ...\n> \n> \n>> @@ -758,7 +776,8 @@ static int cmd_reconfigure(int argc, const char **argv)\n>>   \t\tthe_repository = old_repo;\n>>   \t\trepo_clear(&r);\n>>   \n>> -\t\tif (toggle_maintenance(1) >= 0)\n>> +\t\tif (maintenance >= 0 &&\n>> +\t\t    toggle_maintenance(maintenance) >= 0)\n>>   \t\t\tsucceeded = 1;\n> \n> ... which does make perfect sense, would still be applicable.\n> \n> I dunno.  I just feel that 3-way \"mode\" interface is too much hassle\n> to get right (e.g., give hints to guide the users who forgot what\n> modes are available and how they are spelled) for this code path.\n\nMy intention was to bend over backwards to prevent a behavior change\nin the default case. However, I'm coming around to understand that\nwe don't need this background maintenance to be redone every time\nand can become a no-op by default. (Other new configuration will\nstill happen.)\n\nIn the case where we're fine changing the default behavior, then\nthe standard --[no-]maintenance option will work, though it is a\nthree-way switch where the lack of its existence means \"don't do\neither mode\".\n\nI've got a new version of this patch doing what you asked for in\nthe first place.\n\nThanks,\n-Stolee\n\n"},{"id":"517888","messageId":"xmqqy0v1sp05.fsf@gitster.g","threadId":"63372","inReplyTo":"35ecaa1d-589f-4d28-9d97-78bae8de2d41@gmail.com","subject":"Re: [PATCH v3 4/4] scalar reconfigure: add --maintenance=<mode> option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-05-12T17:44:10Z","receivedAt":"2025-05-12T17:44:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Derrick Stolee <stolee@gmail.com> writes:\n\n> My intention was to bend over backwards to prevent a behavior change\n> in the default case. However, I'm coming around to understand that\n> we don't need this background maintenance to be redone every time\n> and can become a no-op by default. (Other new configuration will\n> still happen.)\n>\n> In the case where we're fine changing the default behavior, then\n> the standard --[no-]maintenance option will work, though it is a\n> three-way switch where the lack of its existence means \"don't do\n> either mode\".\n\nAhh, OK.  I misread your intention.\n\nIf it is common for existing users to disable maintenance, perhaps\nby mistake, together with configuration changes that are not quite\nright, perhaps also by mistake, and if they used reconfigure to\nrecover from such mistakes, it indeed may make sense to nuke the\ncurrent setting and enable maintenance unconditionally.\n\nAs you suggested in a part of your response I omitted, we can\nannotate <mode> to give hints on the valid choices to help users,\nwithout changing the default behaviour.  I am personally fine either\nway, as long as we clearly document the reasoning behind our design.\n\nThanks.\n"},{"id":"517890","messageId":"82c2c073-3fa6-4023-82d5-bdb772c3790b@gmail.com","threadId":"63372","inReplyTo":"xmqqy0v1sp05.fsf@gitster.g","subject":"Re: [PATCH v3 4/4] scalar reconfigure: add --maintenance=<mode> option","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2025-05-12T18:02:26Z","receivedAt":"2025-05-12T18:02:49Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 5/12/2025 1:44 PM, Junio C Hamano wrote:\n> Derrick Stolee <stolee@gmail.com> writes:\n> \n>> My intention was to bend over backwards to prevent a behavior change\n>> in the default case. However, I'm coming around to understand that\n>> we don't need this background maintenance to be redone every time\n>> and can become a no-op by default. (Other new configuration will\n>> still happen.)\n>>\n>> In the case where we're fine changing the default behavior, then\n>> the standard --[no-]maintenance option will work, though it is a\n>> three-way switch where the lack of its existence means \"don't do\n>> either mode\".\n> \n> Ahh, OK.  I misread your intention.\n> \n> If it is common for existing users to disable maintenance, perhaps\n> by mistake, together with configuration changes that are not quite\n> right, perhaps also by mistake, and if they used reconfigure to\n> recover from such mistakes, it indeed may make sense to nuke the\n> current setting and enable maintenance unconditionally.\n\nThe original intent of updating background maintenance in the\n\"reconfigure\" command was primarily about updating the schedule, if\nneeded.\n\nThe recent bug in the macOS scheduler is a good example of this.\nUsers will need to rerun 'git maintenance start' somewhere in order\nto get the \"correct\" schedule. This bug only needs this run for any\nsingle repo, which makes the 'scalar reconfigure -a' command a\nsomewhat strange place to get the fix.\n\n> As you suggested in a part of your response I omitted, we can\n> annotate <mode> to give hints on the valid choices to help users,\n> without changing the default behaviour.  I am personally fine either\n> way, as long as we clearly document the reasoning behind our design.\n\nI'll create a new patch on top of the current series version that\ndoes this, calling it out as an intentional pattern. It's previously\nbeen used by these examples:\n\n * --fixup=[(amend|reword):]<commit>\n * --diff-filter=[(A|C|D|M|R|T|U|X|B)...[*]]\n * --tool=[g,n,]vimdiff\n * --exclude-hidden=[fetch|receive|uploadpack]\n\nOne place where this kind of notation could be helpful, but appears\nto be absent, is the '-L(<n>:<m>)|(:<method>):<file>' argument for\n'git log' and 'git rev-list'. Perhaps this is too dense, though, so\nit would be better split into '-L<n>:<m>:<file>' and\n'-L:<method>:<file>'.\n\nThanks,\n-Stolee\n\n"},{"id":"518024","messageId":"xmqqzfffcr5j.fsf@gitster.g","threadId":"63372","inReplyTo":"82c2c073-3fa6-4023-82d5-bdb772c3790b@gmail.com","subject":"Re: [PATCH v3 4/4] scalar reconfigure: add --maintenance=<mode> option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-05-14T12:28:56Z","receivedAt":"2025-05-14T12:28:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Derrick Stolee <stolee@gmail.com> writes:\n\n>> As you suggested in a part of your response I omitted, we can\n>> annotate <mode> to give hints on the valid choices to help users,\n>> without changing the default behaviour.  I am personally fine either\n>> way, as long as we clearly document the reasoning behind our design.\n>\n> I'll create a new patch on top of the current series version that\n> does this, calling it out as an intentional pattern. It's previously\n> been used by these examples:\n>\n>  * --fixup=[(amend|reword):]<commit>\n>  * --diff-filter=[(A|C|D|M|R|T|U|X|B)...[*]]\n>  * --tool=[g,n,]vimdiff\n>  * --exclude-hidden=[fetch|receive|uploadpack]\n\nYup, these are good things to have in \"git cmd -h\" to help users jog\ntheir memory what the available choices are.  We do not have to\nalways verbosely explain what these mean everywhere, of course, but\nif we said in \"git commit -h\" something like\n\n    --fixup=<choice>\n\nthat would be almost hostile to the users.  And in documentation\npages, of course we can describe what each of the available choices\nmean.\n\n> One place where this kind of notation could be helpful, but appears\n> to be absent, is the '-L(<n>:<m>)|(:<method>):<file>' argument for\n> 'git log' and 'git rev-list'. Perhaps this is too dense, though, so\n> it would be better split into '-L<n>:<m>:<file>' and\n> '-L:<method>:<file>'.\n\nYup.\n"},{"id":"518038","messageId":"7534cfc7-751c-488c-9a98-6f422e5d0a81@gmail.com","threadId":"63372","inReplyTo":"pull.1913.v3.git.1746582637.gitgitgadget@gmail.com","subject":"[PATCH 5/4] scalar reconfigure: improve --maintenance docs","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2025-05-14T13:52:44Z","receivedAt":"2025-05-14T13:52:46Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":" From 0f5dc1cb6d697c7d8d3c126f3640c2f58fcfda43 Mon Sep 17 00:00:00 2001\nFrom: Derrick Stolee <stolee@gmail.com>\nDate: Wed, 14 May 2025 09:50:32 -0400\nSubject: [PATCH 5/4] scalar reconfigure: improve --maintenance docs\n\nThe --maintenance option for 'scalar reconfigure' has three possible\nvalues. Improve the documentation by specifying the option in the -h\nhelp menu and usage information.\n\nSigned-off-by: Derrick Stolee <stolee@gmail.com>\n---\n\nAdding this extra patch on top to improve the docs. I could resend\nas a full v4 if needed.\n\nThanks,\n-Stolee\n\n\n  Documentation/scalar.adoc | 13 ++++++-------\n  scalar.c                  |  4 ++--\n  2 files changed, 8 insertions(+), 9 deletions(-)\n\ndiff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc\nindex 387527be1ea..4bd5b150e8e 100644\n--- a/Documentation/scalar.adoc\n+++ b/Documentation/scalar.adoc\n@@ -14,7 +14,7 @@ scalar list\n  scalar register [--[no-]maintenance] [<enlistment>]\n  scalar unregister [<enlistment>]\n  scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files \n) [<enlistment>]\n-scalar reconfigure [--maintenance=<mode>] [ --all | <enlistment> ]\n+scalar reconfigure [--maintenance=(enable|disable|keep)] [ --all | <enlistment> ]\n  scalar diagnose [<enlistment>]\n  scalar delete <enlistment>\n\n@@ -165,14 +165,13 @@ reconfigure the enlistment.\n  \tregistered with Scalar by the `scalar.repo` config key. Use this\n  \toption after each upgrade to get the latest features.\n\n---maintenance=<mode>::\n+--maintenance=(enable|disable|keep)::\n  \tBy default, Scalar configures the enlistment to use Git's\n  \tbackground maintenance feature; this is the same as using the\n-\t`--maintenance=enable` value for this option. Use the\n-\t`--maintenance=disable` to remove each considered enlistment\n-\tfrom background maintenance. Use `--maitnenance=keep' to leave\n-\tthe background maintenance configuration untouched for These\n-\trepositories.\n+\t`enable` value for this option. Use the\t`disable` value to\n+\tremove each considered enlistment from background maintenance.\n+\tUse `keep' to leave the background maintenance configuration\n+\tuntouched for these repositories.\n\n  Diagnose\n  ~~~~~~~~\ndiff --git a/scalar.c b/scalar.c\nindex 847d2dd2f58..355baf75e49 100644\n--- a/scalar.c\n+++ b/scalar.c\n@@ -675,12 +675,12 @@ static int cmd_reconfigure(int argc, const char **argv)\n  \t\tOPT_BOOL('a', \"all\", &all,\n  \t\t\t N_(\"reconfigure all registered enlistments\")),\n  \t\tOPT_STRING(0, \"maintenance\", &maintenance_str,\n-\t\t\t N_(\"<mode>\"),\n+\t\t\t N_(\"(enable|disable|keep)\"),\n  \t\t\t N_(\"signal how to adjust background maintenance\")),\n  \t\tOPT_END(),\n  \t};\n  \tconst char * const usage[] = {\n-\t\tN_(\"scalar reconfigure [--maintenance=<mode>] [--all | <enlistment>]\"),\n+\t\tN_(\"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | \n<enlistment>]\"),\n  \t\tNULL\n  \t};\n  \tstruct string_list scalar_repos = STRING_LIST_INIT_DUP;\n-- \n2.47.2.vfs.0.2\n\n\n"},{"id":"518077","messageId":"xmqqikm27s9o.fsf@gitster.g","threadId":"63372","inReplyTo":"7534cfc7-751c-488c-9a98-6f422e5d0a81@gmail.com","subject":"Re: [PATCH 5/4] scalar reconfigure: improve --maintenance docs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-05-14T22:16:03Z","receivedAt":"2025-05-14T22:16:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Derrick Stolee <stolee@gmail.com> writes:\n\n> Adding this extra patch on top to improve the docs. I could resend\n> as a full v4 if needed.\n\nNah, the other four patches have been beaten to death, I think.\nPlease double check the result when I push it out later today, as\nI've got the following when running \"git am\".\n\n    warning: Patch sent with format=flowed; space at the end of lines might be lost.\n    Applying: scalar reconfigure: improve --maintenance docs\n\nThanks.\n"},{"id":"518265","messageId":"93a96453-88b6-461d-a50e-d88ef87784c8@gmail.com","threadId":"63372","inReplyTo":"xmqqikm27s9o.fsf@gitster.g","subject":"Re: [PATCH 5/4] scalar reconfigure: improve --maintenance docs","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2025-05-16T16:36:42Z","receivedAt":"2025-05-16T16:36:44Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 5/14/2025 6:16 PM, Junio C Hamano wrote:\n> Derrick Stolee <stolee@gmail.com> writes:\n> \n>> Adding this extra patch on top to improve the docs. I could resend\n>> as a full v4 if needed.\n> \n> Nah, the other four patches have been beaten to death, I think.\n> Please double check the result when I push it out later today, as\n> I've got the following when running \"git am\".\n> \n>     warning: Patch sent with format=flowed; space at the end of lines might be lost.\n>     Applying: scalar reconfigure: improve --maintenance docs\n\nThank you for fixing up this whitespace issue.\n\nI'm happy with your copy of ds/scalar-no-maintenance.\n\nThanks,\n-Stolee\n\n"}]}