Git fork

Merge branch 'ds/scalar-no-maintenance'

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

* ds/scalar-no-maintenance:
scalar reconfigure: improve --maintenance docs
scalar reconfigure: add --maintenance=<mode> option
scalar clone: add --no-maintenance option
scalar register: add --no-maintenance option
scalar: customize register_dir()'s behavior

+113 -20
+26 -5
Documentation/scalar.adoc
··· 9 -------- 10 [verse] 11 scalar clone [--single-branch] [--branch <main-branch>] [--full-clone] 12 - [--[no-]src] <url> [<enlistment>] 13 scalar list 14 - scalar register [<enlistment>] 15 scalar unregister [<enlistment>] 16 scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [<enlistment>] 17 - scalar reconfigure [ --all | <enlistment> ] 18 scalar diagnose [<enlistment>] 19 scalar delete <enlistment> 20 ··· 97 A sparse-checkout is initialized by default. This behavior can be 98 turned off via `--full-clone`. 99 100 List 101 ~~~~ 102 ··· 116 Note: when this subcommand is called in a worktree that is called `src/`, its 117 parent directory is considered to be the Scalar enlistment. If the worktree is 118 _not_ called `src/`, it itself will be considered to be the Scalar enlistment. 119 120 Unregister 121 ~~~~~~~~~~ ··· 149 was somehow corrupted or changed by mistake, this subcommand allows to 150 reconfigure the enlistment. 151 152 - With the `--all` option, all enlistments currently registered with Scalar 153 - will be reconfigured. Use this option after each Scalar upgrade. 154 155 Diagnose 156 ~~~~~~~~
··· 9 -------- 10 [verse] 11 scalar clone [--single-branch] [--branch <main-branch>] [--full-clone] 12 + [--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>] 13 scalar list 14 + scalar register [--[no-]maintenance] [<enlistment>] 15 scalar unregister [<enlistment>] 16 scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [<enlistment>] 17 + scalar reconfigure [--maintenance=(enable|disable|keep)] [ --all | <enlistment> ] 18 scalar diagnose [<enlistment>] 19 scalar delete <enlistment> 20 ··· 97 A sparse-checkout is initialized by default. This behavior can be 98 turned off via `--full-clone`. 99 100 + --[no-]maintenance:: 101 + By default, `scalar clone` configures the enlistment to use Git's 102 + background maintenance feature. Use the `--no-maintenance` to skip 103 + this configuration. 104 + 105 List 106 ~~~~ 107 ··· 121 Note: when this subcommand is called in a worktree that is called `src/`, its 122 parent directory is considered to be the Scalar enlistment. If the worktree is 123 _not_ called `src/`, it itself will be considered to be the Scalar enlistment. 124 + 125 + --[no-]maintenance:: 126 + By default, `scalar register` configures the enlistment to use Git's 127 + background maintenance feature. Use the `--no-maintenance` to skip 128 + this configuration. This does not disable any maintenance that may 129 + already be enabled in other ways. 130 131 Unregister 132 ~~~~~~~~~~ ··· 160 was somehow corrupted or changed by mistake, this subcommand allows to 161 reconfigure the enlistment. 162 163 + --all:: 164 + When `--all` is specified, reconfigure all enlistments currently 165 + registered with Scalar by the `scalar.repo` config key. Use this 166 + option after each upgrade to get the latest features. 167 + 168 + --maintenance=(enable|disable|keep):: 169 + By default, Scalar configures the enlistment to use Git's 170 + background maintenance feature; this is the same as using the 171 + `enable` value for this option. Use the `disable` value to 172 + remove each considered enlistment from background maintenance. 173 + Use `keep' to leave the background maintenance configuration 174 + untouched for these repositories. 175 176 Diagnose 177 ~~~~~~~~
+53 -12
scalar.c
··· 209 return 0; 210 } 211 212 static int toggle_maintenance(int enable) 213 { 214 return run_git("maintenance", ··· 259 return 0; 260 } 261 262 - static int register_dir(void) 263 { 264 if (add_or_remove_enlistment(1)) 265 return error(_("could not add enlistment")); ··· 267 if (set_recommended_config(0)) 268 return error(_("could not set recommended config")); 269 270 - if (toggle_maintenance(1)) 271 - warning(_("could not turn on maintenance")); 272 273 if (have_fsmonitor_support() && start_fsmonitor_daemon()) { 274 return error(_("could not start the FSMonitor daemon")); ··· 411 const char *branch = NULL; 412 char *branch_to_free = NULL; 413 int full_clone = 0, single_branch = 0, show_progress = isatty(2); 414 - int src = 1, tags = 1; 415 struct option clone_options[] = { 416 OPT_STRING('b', "branch", &branch, N_("<branch>"), 417 N_("branch to checkout after clone")), ··· 424 N_("create repository within 'src' directory")), 425 OPT_BOOL(0, "tags", &tags, 426 N_("specify if tags should be fetched during clone")), 427 OPT_END(), 428 }; 429 const char * const clone_usage[] = { 430 N_("scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" 431 - "\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]"), 432 NULL 433 }; 434 const char *url; ··· 550 if (res) 551 goto cleanup; 552 553 - res = register_dir(); 554 555 cleanup: 556 free(branch_to_free); ··· 597 598 static int cmd_register(int argc, const char **argv) 599 { 600 struct option options[] = { 601 OPT_END(), 602 }; 603 const char * const usage[] = { 604 - N_("scalar register [<enlistment>]"), 605 NULL 606 }; 607 ··· 610 611 setup_enlistment_directory(argc, argv, usage, options, NULL); 612 613 - return register_dir(); 614 } 615 616 static int get_scalar_repos(const char *key, const char *value, ··· 646 static int cmd_reconfigure(int argc, const char **argv) 647 { 648 int all = 0; 649 struct option options[] = { 650 OPT_BOOL('a', "all", &all, 651 N_("reconfigure all registered enlistments")), 652 OPT_END(), 653 }; 654 const char * const usage[] = { 655 - N_("scalar reconfigure [--all | <enlistment>]"), 656 NULL 657 }; 658 struct string_list scalar_repos = STRING_LIST_INIT_DUP; ··· 672 usage_msg_opt(_("--all or <enlistment>, but not both"), 673 usage, options); 674 675 git_config(get_scalar_repos, &scalar_repos); 676 677 for (size_t i = 0; i < scalar_repos.nr; i++) { ··· 736 the_repository = old_repo; 737 repo_clear(&r); 738 739 - if (toggle_maintenance(1) >= 0) 740 succeeded = 1; 741 742 loop_end: ··· 803 strbuf_release(&buf); 804 805 if (i == 0) 806 - return register_dir(); 807 808 if (i > 0) 809 return run_git("maintenance", "run", 810 "--task", tasks[i].task, NULL); 811 812 - if (register_dir()) 813 return -1; 814 for (i = 1; tasks[i].arg; i++) 815 if (run_git("maintenance", "run",
··· 209 return 0; 210 } 211 212 + /** 213 + * Enable or disable the maintenance mode for the current repository: 214 + * 215 + * * If 'enable' is nonzero, run 'git maintenance start'. 216 + * * If 'enable' is zero, run 'git maintenance unregister --force'. 217 + */ 218 static int toggle_maintenance(int enable) 219 { 220 return run_git("maintenance", ··· 265 return 0; 266 } 267 268 + /** 269 + * Register the current directory as a Scalar enlistment, and set the 270 + * recommended configuration. 271 + * 272 + * * If 'maintenance' is non-zero, then enable background maintenance. 273 + * * If 'maintenance' is zero, then leave background maintenance as it is 274 + * currently configured. 275 + */ 276 + static int register_dir(int maintenance) 277 { 278 if (add_or_remove_enlistment(1)) 279 return error(_("could not add enlistment")); ··· 281 if (set_recommended_config(0)) 282 return error(_("could not set recommended config")); 283 284 + if (maintenance && 285 + toggle_maintenance(maintenance)) 286 + warning(_("could not toggle maintenance")); 287 288 if (have_fsmonitor_support() && start_fsmonitor_daemon()) { 289 return error(_("could not start the FSMonitor daemon")); ··· 426 const char *branch = NULL; 427 char *branch_to_free = NULL; 428 int full_clone = 0, single_branch = 0, show_progress = isatty(2); 429 + int src = 1, tags = 1, maintenance = 1; 430 struct option clone_options[] = { 431 OPT_STRING('b', "branch", &branch, N_("<branch>"), 432 N_("branch to checkout after clone")), ··· 439 N_("create repository within 'src' directory")), 440 OPT_BOOL(0, "tags", &tags, 441 N_("specify if tags should be fetched during clone")), 442 + OPT_BOOL(0, "maintenance", &maintenance, 443 + N_("specify if background maintenance should be enabled")), 444 OPT_END(), 445 }; 446 const char * const clone_usage[] = { 447 N_("scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" 448 + "\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]"), 449 NULL 450 }; 451 const char *url; ··· 567 if (res) 568 goto cleanup; 569 570 + /* If --no-maintenance, then skip maintenance command entirely. */ 571 + res = register_dir(maintenance); 572 573 cleanup: 574 free(branch_to_free); ··· 615 616 static int cmd_register(int argc, const char **argv) 617 { 618 + int maintenance = 1; 619 struct option options[] = { 620 + OPT_BOOL(0, "maintenance", &maintenance, 621 + N_("specify if background maintenance should be enabled")), 622 OPT_END(), 623 }; 624 const char * const usage[] = { 625 + N_("scalar register [--[no-]maintenance] [<enlistment>]"), 626 NULL 627 }; 628 ··· 631 632 setup_enlistment_directory(argc, argv, usage, options, NULL); 633 634 + /* If --no-maintenance, then leave maintenance as-is. */ 635 + return register_dir(maintenance); 636 } 637 638 static int get_scalar_repos(const char *key, const char *value, ··· 668 static int cmd_reconfigure(int argc, const char **argv) 669 { 670 int all = 0; 671 + const char *maintenance_str = NULL; 672 + int maintenance = 1; /* Enable maintenance by default. */ 673 + 674 struct option options[] = { 675 OPT_BOOL('a', "all", &all, 676 N_("reconfigure all registered enlistments")), 677 + OPT_STRING(0, "maintenance", &maintenance_str, 678 + N_("(enable|disable|keep)"), 679 + N_("signal how to adjust background maintenance")), 680 OPT_END(), 681 }; 682 const char * const usage[] = { 683 + N_("scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | <enlistment>]"), 684 NULL 685 }; 686 struct string_list scalar_repos = STRING_LIST_INIT_DUP; ··· 700 usage_msg_opt(_("--all or <enlistment>, but not both"), 701 usage, options); 702 703 + if (maintenance_str) { 704 + if (!strcmp(maintenance_str, "enable")) 705 + maintenance = 1; 706 + else if (!strcmp(maintenance_str, "disable")) 707 + maintenance = 0; 708 + else if (!strcmp(maintenance_str, "keep")) 709 + maintenance = -1; 710 + else 711 + die(_("unknown mode for --maintenance option: %s"), 712 + maintenance_str); 713 + } 714 + 715 git_config(get_scalar_repos, &scalar_repos); 716 717 for (size_t i = 0; i < scalar_repos.nr; i++) { ··· 776 the_repository = old_repo; 777 repo_clear(&r); 778 779 + if (maintenance >= 0 && 780 + toggle_maintenance(maintenance) >= 0) 781 succeeded = 1; 782 783 loop_end: ··· 844 strbuf_release(&buf); 845 846 if (i == 0) 847 + return register_dir(1); 848 849 if (i > 0) 850 return run_git("maintenance", "run", 851 "--task", tasks[i].task, NULL); 852 853 + if (register_dir(1)) 854 return -1; 855 for (i = 1; tasks[i].arg; i++) 856 if (run_git("maintenance", "run",
+24 -2
t/t9210-scalar.sh
··· 108 git init register-repo && 109 GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \ 110 scalar register register-repo 2>err && 111 - grep "could not turn on maintenance" err 112 ' 113 114 test_expect_success 'scalar unregister' ' ··· 127 128 # scalar unregister should be idempotent 129 scalar unregister vanish 130 ' 131 132 test_expect_success 'set up repository to clone' ' ··· 199 GIT_TRACE2_EVENT="$(pwd)/reconfigure" scalar reconfigure -a && 200 test_path_is_file one/src/cron.txt && 201 test true = "$(git -C one/src config core.preloadIndex)" && 202 - test_subcommand git maintenance start <reconfigure 203 ' 204 205 test_expect_success 'scalar reconfigure --all with includeIf.onbranch' '
··· 108 git init register-repo && 109 GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \ 110 scalar register register-repo 2>err && 111 + grep "could not toggle maintenance" err 112 ' 113 114 test_expect_success 'scalar unregister' ' ··· 127 128 # scalar unregister should be idempotent 129 scalar unregister vanish 130 + ' 131 + 132 + test_expect_success 'scalar register --no-maintenance' ' 133 + git init register-no-maint && 134 + event_log="$(pwd)/no-maint.event" && 135 + GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \ 136 + GIT_TRACE2_EVENT="$event_log" \ 137 + GIT_TRACE2_EVENT_DEPTH=100 \ 138 + scalar register --no-maintenance register-no-maint 2>err && 139 + test_must_be_empty err && 140 + test_subcommand ! git maintenance unregister --force <no-maint.event 141 ' 142 143 test_expect_success 'set up repository to clone' ' ··· 210 GIT_TRACE2_EVENT="$(pwd)/reconfigure" scalar reconfigure -a && 211 test_path_is_file one/src/cron.txt && 212 test true = "$(git -C one/src config core.preloadIndex)" && 213 + test_subcommand git maintenance start <reconfigure && 214 + test_subcommand ! git maintenance unregister --force <reconfigure && 215 + 216 + GIT_TRACE2_EVENT="$(pwd)/reconfigure-maint-disable" \ 217 + scalar reconfigure -a --maintenance=disable && 218 + test_subcommand ! git maintenance start <reconfigure-maint-disable && 219 + test_subcommand git maintenance unregister --force <reconfigure-maint-disable && 220 + 221 + GIT_TRACE2_EVENT="$(pwd)/reconfigure-maint-keep" \ 222 + scalar reconfigure --maintenance=keep -a && 223 + test_subcommand ! git maintenance start <reconfigure-maint-keep && 224 + test_subcommand ! git maintenance unregister --force <reconfigure-maint-keep 225 ' 226 227 test_expect_success 'scalar reconfigure --all with includeIf.onbranch' '
+10 -1
t/t9211-scalar-clone.sh
··· 177 test_expect_success 'scalar clone warns when background maintenance fails' ' 178 GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \ 179 scalar clone "file://$(pwd)/to-clone" maint-fail 2>err && 180 - grep "could not turn on maintenance" err 181 ' 182 183 test_expect_success '`scalar clone --no-src`' '
··· 177 test_expect_success 'scalar clone warns when background maintenance fails' ' 178 GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \ 179 scalar clone "file://$(pwd)/to-clone" maint-fail 2>err && 180 + grep "could not toggle maintenance" err 181 + ' 182 + 183 + test_expect_success 'scalar clone --no-maintenance' ' 184 + GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \ 185 + GIT_TRACE2_EVENT="$(pwd)/no-maint.event" \ 186 + GIT_TRACE2_EVENT_DEPTH=100 \ 187 + scalar clone --no-maintenance "file://$(pwd)/to-clone" no-maint 2>err && 188 + ! grep "could not toggle maintenance" err && 189 + test_subcommand ! git maintenance unregister --force <no-maint.event 190 ' 191 192 test_expect_success '`scalar clone --no-src`' '