{"thread":{"id":"58752","subject":"[PATCH 0/2] git-maintenance quality-of-life improvements","startedAt":"2022-11-05T18:45:55Z","lastAt":"2022-11-07T20:49:56Z","messageCount":8,"participants":["Ronan Pigott","Taylor Blau","Derrick Stolee"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"466612","messageId":"20221105184532.457043-1-ronan@rjp.ie","threadId":"58752","inReplyTo":null,"subject":"[PATCH 0/2] git-maintenance quality-of-life improvements","fromName":"Ronan Pigott","fromEmail":"ronan@rjp.ie","sentAt":"2022-11-05T18:45:30Z","receivedAt":"2022-11-05T18:45:55Z","isPatch":true,"sender":{"key":"ronan@rjp.ie","avatar":"https://avatars.githubusercontent.com/u/12577529?v=4"},"body":"This is a pair of quality-of-life patches for git-maintenance that have\nhelped me in my workflow. PTAL.\n\nRonan Pigott (2):\n  for-each-repo: interpolate repo path arguments\n  maintenance: add option to register in a specific config\n\n Documentation/git-maintenance.txt | 14 +++++++-------\n builtin/for-each-repo.c           |  5 ++++-\n builtin/gc.c                      | 28 +++++++++++++++++-----------\n t/t7900-maintenance.sh            | 15 +++++++++++++++\n 4 files changed, 43 insertions(+), 19 deletions(-)\n\n-- \n2.38.1\n\n"},{"id":"466613","messageId":"20221105184532.457043-2-ronan@rjp.ie","threadId":"58752","inReplyTo":"20221105184532.457043-1-ronan@rjp.ie","subject":"[PATCH 1/2] for-each-repo: interpolate repo path arguments","fromName":"Ronan Pigott","fromEmail":"ronan@rjp.ie","sentAt":"2022-11-05T18:45:31Z","receivedAt":"2022-11-05T18:45:57Z","isPatch":true,"sender":{"key":"ronan@rjp.ie","avatar":"https://avatars.githubusercontent.com/u/12577529?v=4"},"body":"This is a quality of life change for git-maintenance, so repos can be\nrecorded with the tilde syntax. The register subcommand will not record\nrepos in this format by default.\n\nSigned-off-by: Ronan Pigott <ronan@rjp.ie>\n---\n builtin/for-each-repo.c | 5 ++++-\n 1 file changed, 4 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/for-each-repo.c b/builtin/for-each-repo.c\nindex d45d873f57..6aeac37148 100644\n--- a/builtin/for-each-repo.c\n+++ b/builtin/for-each-repo.c\n@@ -14,13 +14,16 @@ static int run_command_on_repo(const char *path, int argc, const char ** argv)\n {\n \tint i;\n \tstruct child_process child = CHILD_PROCESS_INIT;\n+\tchar *abspath = interpolate_path(path, 0);\n \n \tchild.git_cmd = 1;\n-\tstrvec_pushl(&child.args, \"-C\", path, NULL);\n+\tstrvec_pushl(&child.args, \"-C\", abspath, NULL);\n \n \tfor (i = 0; i < argc; i++)\n \t\tstrvec_push(&child.args, argv[i]);\n \n+\tfree(abspath);\n+\n \treturn run_command(&child);\n }\n \n-- \n2.38.1\n\n"},{"id":"466614","messageId":"20221105184532.457043-3-ronan@rjp.ie","threadId":"58752","inReplyTo":"20221105184532.457043-1-ronan@rjp.ie","subject":"[PATCH 2/2] maintenance: add option to register in a specific config","fromName":"Ronan Pigott","fromEmail":"ronan@rjp.ie","sentAt":"2022-11-05T18:45:32Z","receivedAt":"2022-11-05T18:46:03Z","isPatch":true,"sender":{"key":"ronan@rjp.ie","avatar":"https://avatars.githubusercontent.com/u/12577529?v=4"},"body":"maintenance register currently records the maintenance repo exclusively\nwithin the user's global configuration, but other configuration files\nmay be relevant when running maintenance if they are included from the\nglobal config. This option allows the user to choose where maintenance\nrepos are recorded.\n\nSigned-off-by: Ronan Pigott <ronan@rjp.ie>\n---\n\nI track my global config in a bare gitrepo, and include host-specific\nconfiguration from an auxiliary path. Since on each host I may work on\ndifferent repos, at different paths, and have different preferences for\nprefetch or gc frequency, I record maintenance repos in this\nhost-specific config. This option will facilitate this use case.\n\n Documentation/git-maintenance.txt | 14 +++++++-------\n builtin/gc.c                      | 28 +++++++++++++++++-----------\n t/t7900-maintenance.sh            | 15 +++++++++++++++\n 3 files changed, 39 insertions(+), 18 deletions(-)\n\ndiff --git a/Documentation/git-maintenance.txt b/Documentation/git-maintenance.txt\nindex bb888690e4..eb3ae9fbd5 100644\n--- a/Documentation/git-maintenance.txt\n+++ b/Documentation/git-maintenance.txt\n@@ -50,13 +50,13 @@ stop::\n \tthe background maintenance is restarted later.\n \n register::\n-\tInitialize Git config values so any scheduled maintenance will\n-\tstart running on this repository. This adds the repository to the\n-\t`maintenance.repo` config variable in the current user's global\n-\tconfig and enables some recommended configuration values for\n-\t`maintenance.<task>.schedule`. The tasks that are enabled are safe\n-\tfor running in the background without disrupting foreground\n-\tprocesses.\n+\tInitialize Git config values so any scheduled maintenance will start\n+\trunning on this repository. This adds the repository to the\n+\t`maintenance.repo` config variable in the current user's global config,\n+\tor the config specified by --config option, and enables some\n+\trecommended configuration values for `maintenance.<task>.schedule`. The\n+\ttasks that are enabled are safe for running in the background without\n+\tdisrupting foreground processes.\n +\n The `register` subcommand will also set the `maintenance.strategy` config\n value to `incremental`, if this value is not previously set. The\ndiff --git a/builtin/gc.c b/builtin/gc.c\nindex 24ea85c7af..5da6905033 100644\n--- a/builtin/gc.c\n+++ b/builtin/gc.c\n@@ -1454,13 +1454,15 @@ static char *get_maintpath(void)\n }\n \n static char const * const builtin_maintenance_register_usage[] = {\n-\t\"git maintenance register\",\n+\t\"git maintenance register [--config <file>]\",\n \tNULL\n };\n \n static int maintenance_register(int argc, const char **argv, const char *prefix)\n {\n+\tconst char *config_file = NULL;\n \tstruct option options[] = {\n+\t\tOPT_STRING('c', \"config\", &config_file, N_(\"file\"), N_(\"use given config file\")),\n \t\tOPT_END(),\n \t};\n \tint found = 0;\n@@ -1502,7 +1504,7 @@ static int maintenance_register(int argc, const char **argv, const char *prefix)\n \t\tif (!user_config)\n \t\t\tdie(_(\"$HOME not set\"));\n \t\trc = git_config_set_multivar_in_file_gently(\n-\t\t\tuser_config, \"maintenance.repo\", maintpath,\n+\t\t\tconfig_file ?: user_config, \"maintenance.repo\", maintpath,\n \t\t\tCONFIG_REGEX_NONE, 0);\n \t\tfree(user_config);\n \t\tfree(xdg_config);\n@@ -1517,14 +1519,16 @@ static int maintenance_register(int argc, const char **argv, const char *prefix)\n }\n \n static char const * const builtin_maintenance_unregister_usage[] = {\n-\t\"git maintenance unregister [--force]\",\n+\t\"git maintenance unregister [--config <file>] [--force]\",\n \tNULL\n };\n \n static int maintenance_unregister(int argc, const char **argv, const char *prefix)\n {\n \tint force = 0;\n+\tconst char *config_file = NULL;\n \tstruct option options[] = {\n+\t\tOPT_STRING('c', \"config\", &config_file, N_(\"file\"), N_(\"use given config file\")),\n \t\tOPT__FORCE(&force,\n \t\t\t   N_(\"return success even if repository was not registered\"),\n \t\t\t   PARSE_OPT_NOCOMPLETE),\n@@ -1542,24 +1546,26 @@ static int maintenance_unregister(int argc, const char **argv, const char *prefi\n \t\tusage_with_options(builtin_maintenance_unregister_usage,\n \t\t\t\t   options);\n \n-\tlist = git_config_get_value_multi(key);\n-\tif (list) {\n-\t\tfor_each_string_list_item(item, list) {\n-\t\t\tif (!strcmp(maintpath, item->string)) {\n-\t\t\t\tfound = 1;\n-\t\t\t\tbreak;\n+\tif (!config_file) {\n+\t\tlist = git_config_get_value_multi(key);\n+\t\tif (list) {\n+\t\t\tfor_each_string_list_item(item, list) {\n+\t\t\t\tif (!strcmp(maintpath, item->string)) {\n+\t\t\t\t\tfound = 1;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n \t\t\t}\n \t\t}\n \t}\n \n-\tif (found) {\n+\tif (found || config_file) {\n \t\tint rc;\n \t\tchar *user_config, *xdg_config;\n \t\tgit_global_config(&user_config, &xdg_config);\n \t\tif (!user_config)\n \t\t\tdie(_(\"$HOME not set\"));\n \t\trc = git_config_set_multivar_in_file_gently(\n-\t\t\tuser_config, key, NULL, maintpath,\n+\t\t\tconfig_file ?: user_config, key, NULL, maintpath,\n \t\t\tCONFIG_FLAGS_MULTI_REPLACE | CONFIG_FLAGS_FIXED_VALUE);\n \t\tfree(user_config);\n \t\tfree(xdg_config);\ndiff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh\nindex 96bdd42045..c2c2dbbb5f 100755\n--- a/t/t7900-maintenance.sh\n+++ b/t/t7900-maintenance.sh\n@@ -500,6 +500,21 @@ test_expect_success 'register and unregister' '\n \tgit config --global --get-all maintenance.repo >actual &&\n \ttest_cmp before actual &&\n \n+\tgit config --file ./other --add maintenance.repo /existing1 &&\n+\tgit config --file ./other --add maintenance.repo /existing2 &&\n+\tgit config --file ./other --get-all maintenance.repo >before &&\n+\n+\tgit maintenance register --config ./other &&\n+\ttest_cmp_config false maintenance.auto &&\n+\tgit config --file ./other --get-all maintenance.repo >between &&\n+\tcp before expect &&\n+\tpwd >>expect &&\n+\ttest_cmp expect between &&\n+\n+\tgit maintenance unregister --config ./other &&\n+\tgit config --file ./other --get-all maintenance.repo >actual &&\n+\ttest_cmp before actual &&\n+\n \ttest_must_fail git maintenance unregister 2>err &&\n \tgrep \"is not registered\" err &&\n \tgit maintenance unregister --force\n-- \n2.38.1\n\n"},{"id":"466619","messageId":"Y2b/tCUc3nGI+8M7@nand.local","threadId":"58752","inReplyTo":"20221105184532.457043-3-ronan@rjp.ie","subject":"Re: [PATCH 2/2] maintenance: add option to register in a specific config","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2022-11-06T00:28:36Z","receivedAt":"2022-11-06T00:30:22Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Sat, Nov 05, 2022 at 11:45:32AM -0700, Ronan Pigott wrote:\n> @@ -1502,7 +1504,7 @@ static int maintenance_register(int argc, const char **argv, const char *prefix)\n>  \t\tif (!user_config)\n>  \t\t\tdie(_(\"$HOME not set\"));\n>  \t\trc = git_config_set_multivar_in_file_gently(\n> -\t\t\tuser_config, \"maintenance.repo\", maintpath,\n> +\t\t\tconfig_file ?: user_config, \"maintenance.repo\", maintpath,\n>  \t\t\tCONFIG_REGEX_NONE, 0);\n>  \t\tfree(user_config);\n>  \t\tfree(xdg_config);\n\nThe \"?:\" construct is a GNU extension which we do not use.\n\nThanks,\nTaylor\n"},{"id":"466620","messageId":"Y2cAFSR83bjFFcq/@nand.local","threadId":"58752","inReplyTo":"20221105184532.457043-2-ronan@rjp.ie","subject":"Re: [PATCH 1/2] for-each-repo: interpolate repo path arguments","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2022-11-06T00:30:13Z","receivedAt":"2022-11-06T00:30:22Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Sat, Nov 05, 2022 at 11:45:31AM -0700, Ronan Pigott wrote:\n> This is a quality of life change for git-maintenance, so repos can be\n> recorded with the tilde syntax. The register subcommand will not record\n> repos in this format by default.\n>\n> Signed-off-by: Ronan Pigott <ronan@rjp.ie>\n> ---\n>  builtin/for-each-repo.c | 5 ++++-\n>  1 file changed, 4 insertions(+), 1 deletion(-)\n\nSeems reasonable. So the 'register' subcommand will never write a record\nthat isn't an absolute path, but a user may manually munge the\nmaintenance configuration and we want to err on the side of flexibility.\n\nOK, sounds good. Missing test, though?\n\nThanks,\nTaylor\n"},{"id":"466621","messageId":"Y2cC4QCz5IhRZLqP@nand.local","threadId":"58752","inReplyTo":"20221105184532.457043-3-ronan@rjp.ie","subject":"Re: [PATCH 2/2] maintenance: add option to register in a specific config","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2022-11-06T00:42:09Z","receivedAt":"2022-11-06T00:42:18Z","isPatch":true,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Sat, Nov 05, 2022 at 11:45:32AM -0700, Ronan Pigott wrote:\n> maintenance register currently records the maintenance repo exclusively\n> within the user's global configuration, but other configuration files\n> may be relevant when running maintenance if they are included from the\n> global config. This option allows the user to choose where maintenance\n> repos are recorded.\n\nI see. So we don't change the location of the config that 'maintenance\nrun/start' are reading from, but we can change the location of the\nconfig we use to record which repositories are maintenance candidates.\n\nI guess it makes sense if you are including arbitrary configuration\nfiles in your global config, so this seems reasonable to me.\n\n> Signed-off-by: Ronan Pigott <ronan@rjp.ie>\n> ---\n>\n> I track my global config in a bare gitrepo, and include host-specific\n> configuration from an auxiliary path. Since on each host I may work on\n> different repos, at different paths, and have different preferences for\n> prefetch or gc frequency, I record maintenance repos in this\n> host-specific config. This option will facilitate this use case.\n>\n>  Documentation/git-maintenance.txt | 14 +++++++-------\n>  builtin/gc.c                      | 28 +++++++++++++++++-----------\n>  t/t7900-maintenance.sh            | 15 +++++++++++++++\n>  3 files changed, 39 insertions(+), 18 deletions(-)\n>\n> diff --git a/Documentation/git-maintenance.txt b/Documentation/git-maintenance.txt\n> index bb888690e4..eb3ae9fbd5 100644\n> --- a/Documentation/git-maintenance.txt\n> +++ b/Documentation/git-maintenance.txt\n> @@ -50,13 +50,13 @@ stop::\n>  \tthe background maintenance is restarted later.\n>\n>  register::\n> -\tInitialize Git config values so any scheduled maintenance will\n> -\tstart running on this repository. This adds the repository to the\n> -\t`maintenance.repo` config variable in the current user's global\n> -\tconfig and enables some recommended configuration values for\n> -\t`maintenance.<task>.schedule`. The tasks that are enabled are safe\n> -\tfor running in the background without disrupting foreground\n> -\tprocesses.\n> +\tInitialize Git config values so any scheduled maintenance will start\n> +\trunning on this repository. This adds the repository to the\n> +\t`maintenance.repo` config variable in the current user's global config,\n> +\tor the config specified by --config option, and enables some\n> +\trecommended configuration values for `maintenance.<task>.schedule`. The\n> +\ttasks that are enabled are safe for running in the background without\n> +\tdisrupting foreground processes.\n\nThe new text looks good, but there is some unnecessary line re-wrapping\nthat occurred around it.\n\n>  The `register` subcommand will also set the `maintenance.strategy` config\n>  value to `incremental`, if this value is not previously set. The\n> diff --git a/builtin/gc.c b/builtin/gc.c\n> index 24ea85c7af..5da6905033 100644\n> --- a/builtin/gc.c\n> +++ b/builtin/gc.c\n> @@ -1454,13 +1454,15 @@ static char *get_maintpath(void)\n>  }\n>\n>  static char const * const builtin_maintenance_register_usage[] = {\n> -\t\"git maintenance register\",\n> +\t\"git maintenance register [--config <file>]\",\n\n\"<path>\" (instead of \"<file>\") is slightly more common these days.\n\n>  \tNULL\n>  };\n>\n>  static int maintenance_register(int argc, const char **argv, const char *prefix)\n>  {\n> +\tconst char *config_file = NULL;\n>  \tstruct option options[] = {\n> +\t\tOPT_STRING('c', \"config\", &config_file, N_(\"file\"), N_(\"use given config file\")),\n>  \t\tOPT_END(),\n>  \t};\n>  \tint found = 0;\n> @@ -1502,7 +1504,7 @@ static int maintenance_register(int argc, const char **argv, const char *prefix)\n>  \t\tif (!user_config)\n>  \t\t\tdie(_(\"$HOME not set\"));\n\nHmm. I wonder if we want to avoid calling git_global_config() when we\ndon't need to. Maybe something like this:\n\n--- >8 ---\ndiff --git a/builtin/gc.c b/builtin/gc.c\nindex 5da6905033..13a2633912 100644\n--- a/builtin/gc.c\n+++ b/builtin/gc.c\n@@ -1460,7 +1460,7 @@ static char const * const builtin_maintenance_register_usage[] = {\n\n static int maintenance_register(int argc, const char **argv, const char *prefix)\n {\n-\tconst char *config_file = NULL;\n+\tchar *config_file = NULL;\n \tstruct option options[] = {\n \t\tOPT_STRING('c', \"config\", &config_file, N_(\"file\"), N_(\"use given config file\")),\n \t\tOPT_END(),\n@@ -1499,14 +1499,21 @@ static int maintenance_register(int argc, const char **argv, const char *prefix)\n\n \tif (!found) {\n \t\tint rc;\n-\t\tchar *user_config, *xdg_config;\n-\t\tgit_global_config(&user_config, &xdg_config);\n-\t\tif (!user_config)\n-\t\t\tdie(_(\"$HOME not set\"));\n+\t\tchar *user_config = NULL, *xdg_config = NULL;\n+\t\tchar *to_free = NULL;\n+\n+\t\tif (config_file) {\n+\t\t\tuser_config = config_file;\n+\t\t} else {\n+\t\t\tgit_global_config(&user_config, &xdg_config);\n+\t\t\tto_free = user_config;\n+\t\t\tif (!user_config)\n+\t\t\t\tdie(_(\"$HOME not set\"));\n+\t\t}\n \t\trc = git_config_set_multivar_in_file_gently(\n-\t\t\tconfig_file ?: user_config, \"maintenance.repo\", maintpath,\n+\t\t\tuser_config, \"maintenance.repo\", maintpath,\n \t\t\tCONFIG_REGEX_NONE, 0);\n-\t\tfree(user_config);\n+\t\tfree(to_free);\n \t\tfree(xdg_config);\n\n \t\tif (rc)\n--- 8< ---\n\n> -\t\t\tuser_config, key, NULL, maintpath,\n> +\t\t\tconfig_file ?: user_config, key, NULL, maintpath,\n\nSame note(s) here, too.\n\n> @@ -500,6 +500,21 @@ test_expect_success 'register and unregister' '\n>  \tgit config --global --get-all maintenance.repo >actual &&\n>  \ttest_cmp before actual &&\n>\n> +\tgit config --file ./other --add maintenance.repo /existing1 &&\n> +\tgit config --file ./other --add maintenance.repo /existing2 &&\n> +\tgit config --file ./other --get-all maintenance.repo >before &&\n\nI was wondering why you didn't bother writing all of this into \"expect\",\nand then appending \"pwd\" onto the end of it.\n\n> +\tgit maintenance register --config ./other &&\n> +\ttest_cmp_config false maintenance.auto &&\n> +\tgit config --file ./other --get-all maintenance.repo >between &&\n> +\tcp before expect &&\n> +\tpwd >>expect &&\n> +\ttest_cmp expect between &&\n\n...since it would have simplified the setup here.\n\n> +\tgit maintenance unregister --config ./other &&\n> +\tgit config --file ./other --get-all maintenance.repo >actual &&\n> +\ttest_cmp before actual &&\n\n...but here you want to compare the output you got above with everything\nthat was configured before, i.e., just what came out of the first three\nlines. Makes sense.\n\nThanks,\nTaylor\n"},{"id":"466736","messageId":"15d9326c-8a32-c11c-53b0-cf399e541a48@github.com","threadId":"58752","inReplyTo":"Y2cAFSR83bjFFcq/@nand.local","subject":"Re: [PATCH 1/2] for-each-repo: interpolate repo path arguments","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-11-07T20:46:36Z","receivedAt":"2022-11-07T20:46:44Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 11/5/22 8:30 PM, Taylor Blau wrote:\n> On Sat, Nov 05, 2022 at 11:45:31AM -0700, Ronan Pigott wrote:\n>> This is a quality of life change for git-maintenance, so repos can be\n>> recorded with the tilde syntax. The register subcommand will not record\n>> repos in this format by default.\n>>\n>> Signed-off-by: Ronan Pigott <ronan@rjp.ie>\n>> ---\n>>  builtin/for-each-repo.c | 5 ++++-\n>>  1 file changed, 4 insertions(+), 1 deletion(-)\n> \n> Seems reasonable. So the 'register' subcommand will never write a record\n> that isn't an absolute path, but a user may manually munge the\n> maintenance configuration and we want to err on the side of flexibility.\n> \n> OK, sounds good. Missing test, though?\n\nI agree that this implementation looks good, but a test\nwould be helpful to be sure.\n\nThanks,\n-Stolee\n"},{"id":"466737","messageId":"22a74e0f-f389-7b9c-f2cc-b3581c246c75@github.com","threadId":"58752","inReplyTo":"20221105184532.457043-3-ronan@rjp.ie","subject":"Re: [PATCH 2/2] maintenance: add option to register in a specific config","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-11-07T20:49:28Z","receivedAt":"2022-11-07T20:49:56Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 11/5/22 2:45 PM, Ronan Pigott wrote:\n> maintenance register currently records the maintenance repo exclusively\n> within the user's global configuration, but other configuration files\n> may be relevant when running maintenance if they are included from the\n> global config. This option allows the user to choose where maintenance\n> repos are recorded.\n\nTaylor already provided most of the feedback that I would have given.\n\n>  static char const * const builtin_maintenance_register_usage[] = {\n> -\t\"git maintenance register\",\n> +\t\"git maintenance register [--config <file>]\",\n\nThe only recommendation I have remaining is to rename this option to\n`--config-file=<file>` since it is unclear from just \"--config\" if it\nis a config _file_ or a config _key_.\n\nThanks,\n-Stolee\n"}]}