diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 49bcd0a2a9854a..7dbf9f7f123c89 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -265,7 +265,7 @@ jobs: run: pip install meson ninja - name: Setup shell: pwsh - run: meson setup build --vsenv -Dperl=disabled -Dcredential_helpers=wincred + run: meson setup build --vsenv -Dbuildtype=release -Dperl=disabled -Dcredential_helpers=wincred - name: Compile shell: pwsh run: meson compile -C build diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4798b283745918..bb6d5b976cdc36 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -173,7 +173,6 @@ build:msvc-meson: test:msvc-meson: extends: .msvc-meson stage: test - when: manual timeout: 6h needs: - job: "build:msvc-meson" diff --git a/Documentation/RelNotes/2.50.0.adoc b/Documentation/RelNotes/2.50.0.adoc index bf73de114eb147..f721ea350d7af5 100644 --- a/Documentation/RelNotes/2.50.0.adoc +++ b/Documentation/RelNotes/2.50.0.adoc @@ -72,6 +72,10 @@ UI, Workflows & Features * The `send-email` documentation has been updated with OAuth2.0 related examples. + * Two of the "scalar" subcommands that add a repository that hasn't + been under "scalar"'s control are taught an option not to enable the + scheduled maintenance on it. + Performance, Internal Implementation, Development Support etc. -------------------------------------------------------------- @@ -157,6 +161,12 @@ Performance, Internal Implementation, Development Support etc. * Build performance fix. + * Teach "git send-email" to also consult `hostname -f` for mail + domain to compute the identity given to SMTP servers. + + * The dependency on the_repository variable has been reduced from the + code paths in "git replay". + Fixes since v2.49 ----------------- @@ -306,6 +316,15 @@ Fixes since v2.49 * Use-after-free fix in the sequencer. (merge 5dbaec628d pw/sequencer-reflog-use-after-free later to maint). + * win+Meson CI pipeline, unlike other pipelines for Windows, + used to build artifacts in develper mode, which has been changed to + build them in release mode for consistency. + (merge 184abdcf05 js/ci-build-win-in-release-mode later to maint). + + * CI settings at GitLab has been updated to run MSVC based Meson job + automatically (as opposed to be done only upon manual request). + (merge 6389579b2f ps/ci-gitlab-enable-msvc-meson-job later to maint). + * Other code cleanup, docfix, build fix, etc. (merge 227c4f33a0 ja/doc-block-delimiter-markup-fix later to maint). (merge 2bfd3b3685 ab/decorate-code-cleanup later to maint). diff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc index 7e4259c6743f9b..4bd5b150e8e1d4 100644 --- a/Documentation/scalar.adoc +++ b/Documentation/scalar.adoc @@ -9,12 +9,12 @@ SYNOPSIS -------- [verse] scalar clone [--single-branch] [--branch ] [--full-clone] - [--[no-]src] [] + [--[no-]src] [--[no-]tags] [--[no-]maintenance] [] scalar list -scalar register [] +scalar register [--[no-]maintenance] [] scalar unregister [] scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [] -scalar reconfigure [ --all | ] +scalar reconfigure [--maintenance=(enable|disable|keep)] [ --all | ] scalar diagnose [] scalar delete @@ -97,6 +97,11 @@ cloning. If the HEAD at the remote did not point at any branch when A sparse-checkout is initialized by default. This behavior can be turned off via `--full-clone`. +--[no-]maintenance:: + By default, `scalar clone` configures the enlistment to use Git's + background maintenance feature. Use the `--no-maintenance` to skip + this configuration. + List ~~~~ @@ -117,6 +122,12 @@ Note: when this subcommand is called in a worktree that is called `src/`, its parent directory is considered to be the Scalar enlistment. If the worktree is _not_ called `src/`, it itself will be considered to be the Scalar enlistment. +--[no-]maintenance:: + By default, `scalar register` configures the enlistment to use Git's + background maintenance feature. Use the `--no-maintenance` to skip + this configuration. This does not disable any maintenance that may + already be enabled in other ways. + Unregister ~~~~~~~~~~ @@ -149,8 +160,18 @@ After a Scalar upgrade, or when the configuration of a Scalar enlistment was somehow corrupted or changed by mistake, this subcommand allows to reconfigure the enlistment. -With the `--all` option, all enlistments currently registered with Scalar -will be reconfigured. Use this option after each Scalar upgrade. +--all:: + When `--all` is specified, reconfigure all enlistments currently + registered with Scalar by the `scalar.repo` config key. Use this + option after each upgrade to get the latest features. + +--maintenance=(enable|disable|keep):: + By default, Scalar configures the enlistment to use Git's + background maintenance feature; this is the same as using the + `enable` value for this option. Use the `disable` value to + remove each considered enlistment from background maintenance. + Use `keep' to leave the background maintenance configuration + untouched for these repositories. Diagnose ~~~~~~~~ diff --git a/builtin/replay.c b/builtin/replay.c index 032c172b65ece4..225cef08807e33 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -20,21 +20,22 @@ #include #include -static const char *short_commit_name(struct commit *commit) +static const char *short_commit_name(struct repository *repo, + struct commit *commit) { - return repo_find_unique_abbrev(the_repository, &commit->object.oid, + return repo_find_unique_abbrev(repo, &commit->object.oid, DEFAULT_ABBREV); } -static struct commit *peel_committish(const char *name) +static struct commit *peel_committish(struct repository *repo, const char *name) { struct object *obj; struct object_id oid; - if (repo_get_oid(the_repository, name, &oid)) + if (repo_get_oid(repo, name, &oid)) return NULL; - obj = parse_object(the_repository, &oid); - return (struct commit *)repo_peel_to_type(the_repository, name, 0, obj, + obj = parse_object(repo, &oid); + return (struct commit *)repo_peel_to_type(repo, name, 0, obj, OBJ_COMMIT); } @@ -50,7 +51,8 @@ static char *get_author(const char *message) return NULL; } -static struct commit *create_commit(struct tree *tree, +static struct commit *create_commit(struct repository *repo, + struct tree *tree, struct commit *based_on, struct commit *parent) { @@ -62,7 +64,7 @@ static struct commit *create_commit(struct tree *tree, struct commit_extra_header *extra = NULL; struct strbuf msg = STRBUF_INIT; const char *out_enc = get_commit_output_encoding(); - const char *message = repo_logmsg_reencode(the_repository, based_on, + const char *message = repo_logmsg_reencode(repo, based_on, NULL, out_enc); const char *orig_message = NULL; const char *exclude_gpgsig[] = { "gpgsig", NULL }; @@ -79,7 +81,7 @@ static struct commit *create_commit(struct tree *tree, goto out; } - obj = parse_object(the_repository, &ret); + obj = parse_object(repo, &ret); out: free_commit_extra_headers(extra); @@ -97,7 +99,8 @@ struct ref_info { int negative_refexprs; }; -static void get_ref_information(struct rev_cmdline_info *cmd_info, +static void get_ref_information(struct repository *repo, + struct rev_cmdline_info *cmd_info, struct ref_info *ref_info) { int i; @@ -132,14 +135,14 @@ static void get_ref_information(struct rev_cmdline_info *cmd_info, if (*refexpr == '^') refexpr++; - if (repo_dwim_ref(the_repository, refexpr, strlen(refexpr), &oid, &fullname, 0) != 1) + if (repo_dwim_ref(repo, refexpr, strlen(refexpr), &oid, &fullname, 0) != 1) can_uniquely_dwim = 0; if (e->flags & BOTTOM) { if (can_uniquely_dwim) strset_add(&ref_info->negative_refs, fullname); if (!ref_info->negative_refexprs) - ref_info->onto = lookup_commit_reference_gently(the_repository, + ref_info->onto = lookup_commit_reference_gently(repo, &e->item->oid, 1); ref_info->negative_refexprs++; } else { @@ -152,7 +155,8 @@ static void get_ref_information(struct rev_cmdline_info *cmd_info, } } -static void determine_replay_mode(struct rev_cmdline_info *cmd_info, +static void determine_replay_mode(struct repository *repo, + struct rev_cmdline_info *cmd_info, const char *onto_name, char **advance_name, struct commit **onto, @@ -160,14 +164,14 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info, { struct ref_info rinfo; - get_ref_information(cmd_info, &rinfo); + get_ref_information(repo, cmd_info, &rinfo); if (!rinfo.positive_refexprs) die(_("need some commits to replay")); die_for_incompatible_opt2(!!onto_name, "--onto", !!*advance_name, "--advance"); if (onto_name) { - *onto = peel_committish(onto_name); + *onto = peel_committish(repo, onto_name); if (rinfo.positive_refexprs < strset_get_size(&rinfo.positive_refs)) die(_("all positive revisions given must be references")); @@ -175,8 +179,8 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info, struct object_id oid; char *fullname = NULL; - *onto = peel_committish(*advance_name); - if (repo_dwim_ref(the_repository, *advance_name, strlen(*advance_name), + *onto = peel_committish(repo, *advance_name); + if (repo_dwim_ref(repo, *advance_name, strlen(*advance_name), &oid, &fullname, 0) == 1) { free(*advance_name); *advance_name = fullname; @@ -245,7 +249,8 @@ static struct commit *mapped_commit(kh_oid_map_t *replayed_commits, return kh_value(replayed_commits, pos); } -static struct commit *pick_regular_commit(struct commit *pickme, +static struct commit *pick_regular_commit(struct repository *repo, + struct commit *pickme, kh_oid_map_t *replayed_commits, struct commit *onto, struct merge_options *merge_opt, @@ -257,12 +262,12 @@ static struct commit *pick_regular_commit(struct commit *pickme, base = pickme->parents->item; replayed_base = mapped_commit(replayed_commits, base, onto); - result->tree = repo_get_commit_tree(the_repository, replayed_base); - pickme_tree = repo_get_commit_tree(the_repository, pickme); - base_tree = repo_get_commit_tree(the_repository, base); + result->tree = repo_get_commit_tree(repo, replayed_base); + pickme_tree = repo_get_commit_tree(repo, pickme); + base_tree = repo_get_commit_tree(repo, base); - merge_opt->branch1 = short_commit_name(replayed_base); - merge_opt->branch2 = short_commit_name(pickme); + merge_opt->branch1 = short_commit_name(repo, replayed_base); + merge_opt->branch2 = short_commit_name(repo, pickme); merge_opt->ancestor = xstrfmt("parent of %s", merge_opt->branch2); merge_incore_nonrecursive(merge_opt, @@ -275,13 +280,13 @@ static struct commit *pick_regular_commit(struct commit *pickme, merge_opt->ancestor = NULL; if (!result->clean) return NULL; - return create_commit(result->tree, pickme, replayed_base); + return create_commit(repo, result->tree, pickme, replayed_base); } int cmd_replay(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { const char *advance_name_opt = NULL; char *advance_name = NULL; @@ -329,7 +334,7 @@ int cmd_replay(int argc, "--advance", "--contained"); advance_name = xstrdup_or_null(advance_name_opt); - repo_init_revisions(the_repository, &revs, prefix); + repo_init_revisions(repo, &revs, prefix); /* * Set desired values for rev walking options here. If they @@ -380,7 +385,7 @@ int cmd_replay(int argc, revs.simplify_history = 0; } - determine_replay_mode(&revs.cmdline, onto_name, &advance_name, + determine_replay_mode(repo, &revs.cmdline, onto_name, &advance_name, &onto, &update_refs); if (!onto) /* FIXME: Should handle replaying down to root commit */ @@ -391,7 +396,7 @@ int cmd_replay(int argc, goto cleanup; } - init_basic_merge_options(&merge_opt, the_repository); + init_basic_merge_options(&merge_opt, repo); memset(&result, 0, sizeof(result)); merge_opt.show_rename_progress = 0; last_commit = onto; @@ -406,8 +411,8 @@ int cmd_replay(int argc, if (commit->parents->next) die(_("replaying merge commits is not supported yet!")); - last_commit = pick_regular_commit(commit, replayed_commits, onto, - &merge_opt, &result); + last_commit = pick_regular_commit(repo, commit, replayed_commits, + onto, &merge_opt, &result); if (!last_commit) break; diff --git a/git-send-email.perl b/git-send-email.perl index 55b7e00d29d29a..659e6c588bcf87 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -1393,8 +1393,22 @@ sub maildomain_mta { return $maildomain; } +sub maildomain_hostname_command { + my $maildomain; + + if ($^O eq 'linux' || $^O eq 'darwin') { + my $domain = `(hostname -f) 2>/dev/null`; + if (!$?) { + chomp($domain); + $maildomain = $domain if valid_fqdn($domain); + } + } + return $maildomain; +} + sub maildomain { - return maildomain_net() || maildomain_mta() || 'localhost.localdomain'; + return maildomain_net() || maildomain_mta() || + maildomain_hostname_command || 'localhost.localdomain'; } sub smtp_host_string { diff --git a/json-writer.c b/json-writer.c index 8c5187e9fdda81..34577dc25f887c 100644 --- a/json-writer.c +++ b/json-writer.c @@ -268,10 +268,6 @@ static void append_sub_jw(struct json_writer *jw, strbuf_addbuf(&jw->json, &value->json); } -/* - * Append existing (properly terminated) JSON sub-data (object or array) - * as-is onto the given JSON data. - */ void jw_object_sub_jw(struct json_writer *jw, const char *key, const struct json_writer *value) { diff --git a/json-writer.h b/json-writer.h index 04413bd1afda5d..8f845d4d294d8d 100644 --- a/json-writer.h +++ b/json-writer.h @@ -28,6 +28,34 @@ * object/array) -or- by building them inline in one pass. This is a * personal style and/or data shape choice. * + * USAGE: + * ====== + * + * - Initialize the json_writer with jw_init. + * + * - Open an object as the main data structure with jw_object_begin. + * Append a key-value pair to it using the jw_object_ functions. + * Conclude with jw_end. + * + * - Alternatively, open an array as the main data structure with + * jw_array_begin. Append a value to it using the jw_array_ + * functions. Conclude with jw_end. + * + * - Append a new, unterminated array or object to the current + * object using the jw_object_inline_begin_{array, object} functions. + * Similarly, append a new, unterminated array or object to + * the current array using the jw_array_inline_begin_{array, object} + * functions. + * + * - Append other json_writer as a value to the current array or object + * using the jw_{array, object}_sub_jw functions. + * + * - Extend the current array with an null-terminated array of strings + * by using jw_array_argv or with a fixed number of elements of a + * array of string by using jw_array_argc_argv. + * + * - Release the json_writer after using it by calling jw_release. + * * See t/helper/test-json-writer.c for various usage examples. * * LIMITATIONS: @@ -69,42 +97,185 @@ struct json_writer .open_stack = STRBUF_INIT, \ } +/* + * Initialize a json_writer with empty values. + */ void jw_init(struct json_writer *jw); + +/* + * Release the internal buffers of a json_writer. + */ void jw_release(struct json_writer *jw); +/* + * Begin the json_writer using an object as the top-level data structure. If + * pretty is set to 1, the result will be a human-readable and indented JSON, + * and if it is set to 0 the result will be minified single-line JSON. + */ void jw_object_begin(struct json_writer *jw, int pretty); + +/* + * Begin the json_writer using an array as the top-level data structure. If + * pretty is set to 1, the result will be a human-readable and indented JSON, + * and if it is set to 0 the result will be minified single-line JSON. + */ void jw_array_begin(struct json_writer *jw, int pretty); +/* + * Append a string field to the current object of the json_writer, given its key + * and its value. Trigger a BUG when not in an object. + */ void jw_object_string(struct json_writer *jw, const char *key, const char *value); + +/* + * Append an int field to the current object of the json_writer, given its key + * and its value. Trigger a BUG when not in an object. + */ void jw_object_intmax(struct json_writer *jw, const char *key, intmax_t value); + +/* + * Append a double field to the current object of the json_writer, given its key + * and its value. The precision parameter defines the number of significant + * digits, where -1 can be used for maximum precision. Trigger a BUG when not in + * an object. + */ void jw_object_double(struct json_writer *jw, const char *key, int precision, double value); + +/* + * Append a boolean field set to true to the current object of the json_writer, + * given its key. Trigger a BUG when not in an object. + */ void jw_object_true(struct json_writer *jw, const char *key); + +/* + * Append a boolean field set to false to the current object of the json_writer, + * given its key. Trigger a BUG when not in an object. + */ void jw_object_false(struct json_writer *jw, const char *key); + +/* + * Append a boolean field to the current object of the json_writer, given its + * key and its value. Trigger a BUG when not in an object. + */ void jw_object_bool(struct json_writer *jw, const char *key, int value); + +/* + * Append a null field to the current object of the json_writer, given its key. + * Trigger a BUG when not in an object. + */ void jw_object_null(struct json_writer *jw, const char *key); + +/* + * Append a field to the current object of the json_writer, given its key and + * another json_writer that represents its content. Trigger a BUG when not in + * an object. + */ void jw_object_sub_jw(struct json_writer *jw, const char *key, const struct json_writer *value); +/* + * Start an object as the value of a field in the current object of the + * json_writer. Trigger a BUG when not in an object. + */ void jw_object_inline_begin_object(struct json_writer *jw, const char *key); + +/* + * Start an array as the value of a field in the current object of the + * json_writer. Trigger a BUG when not in an object. + */ void jw_object_inline_begin_array(struct json_writer *jw, const char *key); +/* + * Append a string value to the current array of the json_writer. Trigger a BUG + * when not in an array. + */ void jw_array_string(struct json_writer *jw, const char *value); + +/* + * Append an int value to the current array of the json_writer. Trigger a BUG + * when not in an array. + */ void jw_array_intmax(struct json_writer *jw, intmax_t value); + +/* + * Append a double value to the current array of the json_writer. The precision + * parameter defines the number of significant digits, where -1 can be used for + * maximum precision. Trigger a BUG when not in an array. + */ void jw_array_double(struct json_writer *jw, int precision, double value); + +/* + * Append a true value to the current array of the json_writer. Trigger a BUG + * when not in an array. + */ void jw_array_true(struct json_writer *jw); + +/* + * Append a false value to the current array of the json_writer. Trigger a BUG + * when not in an array. + */ void jw_array_false(struct json_writer *jw); + +/* + * Append a boolean value to the current array of the json_writer. Trigger a BUG + * when not in an array. + */ void jw_array_bool(struct json_writer *jw, int value); + +/* + * Append a null value to the current array of the json_writer. Trigger a BUG + * when not in an array. + */ void jw_array_null(struct json_writer *jw); + +/* + * Append a json_writer as a value to the current array of the + * json_writer. Trigger a BUG when not in an array. + */ void jw_array_sub_jw(struct json_writer *jw, const struct json_writer *value); + +/* + * Append the first argc values from the argv array of strings to the current + * array of the json_writer. Trigger a BUG when not in an array. + * + * This function does not provide safety for cases where the array has less than + * argc values. + */ void jw_array_argc_argv(struct json_writer *jw, int argc, const char **argv); + +/* + * Append a null-terminated array of strings to the current array of the + * json_writer. Trigger a BUG when not in an array. + */ void jw_array_argv(struct json_writer *jw, const char **argv); +/* + * Start an object as a value in the current array of the json_writer. Trigger a + * BUG when not in an array. + */ void jw_array_inline_begin_object(struct json_writer *jw); + +/* + * Start an array as a value in the current array. Trigger a BUG when not in an + * array. + */ void jw_array_inline_begin_array(struct json_writer *jw); +/* + * Return whether the json_writer is terminated. In other words, if the all the + * objects and arrays are already closed. + */ int jw_is_terminated(const struct json_writer *jw); + +/* + * Terminates the current object or array of the json_writer. In other words, + * append a ] if the current array is not closed or } if the current object + * is not closed. + * + * Abort the execution if there's no object or array that can be terminated. + */ void jw_end(struct json_writer *jw); #endif /* JSON_WRITER_H */ diff --git a/pack-bitmap.c b/pack-bitmap.c index b9f1d866046bad..ac6d62b980c5a8 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -388,10 +388,6 @@ static int load_bitmap_entries_v1(struct bitmap_index *index) return error(_("corrupt ewah bitmap: commit index %u out of range"), (unsigned)commit_idx_pos); - bitmap = read_bitmap_1(index); - if (!bitmap) - return -1; - if (xor_offset > MAX_XOR_OFFSET || xor_offset > i) return error(_("corrupted bitmap pack index")); @@ -402,6 +398,10 @@ static int load_bitmap_entries_v1(struct bitmap_index *index) return error(_("invalid XOR offset in bitmap pack index")); } + bitmap = read_bitmap_1(index); + if (!bitmap) + return -1; + recent_bitmaps[i % MAX_XOR_OFFSET] = store_bitmap( index, bitmap, &oid, xor_bitmap, flags); } diff --git a/scalar.c b/scalar.c index d359f08bb8e23e..355baf75e499cb 100644 --- a/scalar.c +++ b/scalar.c @@ -209,6 +209,12 @@ static int set_recommended_config(int reconfigure) return 0; } +/** + * Enable or disable the maintenance mode for the current repository: + * + * * If 'enable' is nonzero, run 'git maintenance start'. + * * If 'enable' is zero, run 'git maintenance unregister --force'. + */ static int toggle_maintenance(int enable) { return run_git("maintenance", @@ -259,7 +265,15 @@ static int stop_fsmonitor_daemon(void) return 0; } -static int register_dir(void) +/** + * Register the current directory as a Scalar enlistment, and set the + * recommended configuration. + * + * * If 'maintenance' is non-zero, then enable background maintenance. + * * If 'maintenance' is zero, then leave background maintenance as it is + * currently configured. + */ +static int register_dir(int maintenance) { if (add_or_remove_enlistment(1)) return error(_("could not add enlistment")); @@ -267,8 +281,9 @@ static int register_dir(void) if (set_recommended_config(0)) return error(_("could not set recommended config")); - if (toggle_maintenance(1)) - warning(_("could not turn on maintenance")); + if (maintenance && + toggle_maintenance(maintenance)) + warning(_("could not toggle maintenance")); if (have_fsmonitor_support() && start_fsmonitor_daemon()) { return error(_("could not start the FSMonitor daemon")); @@ -411,7 +426,7 @@ static int cmd_clone(int argc, const char **argv) const char *branch = NULL; char *branch_to_free = NULL; int full_clone = 0, single_branch = 0, show_progress = isatty(2); - int src = 1, tags = 1; + int src = 1, tags = 1, maintenance = 1; struct option clone_options[] = { OPT_STRING('b', "branch", &branch, N_(""), N_("branch to checkout after clone")), @@ -424,11 +439,13 @@ static int cmd_clone(int argc, const char **argv) N_("create repository within 'src' directory")), OPT_BOOL(0, "tags", &tags, N_("specify if tags should be fetched during clone")), + OPT_BOOL(0, "maintenance", &maintenance, + N_("specify if background maintenance should be enabled")), OPT_END(), }; const char * const clone_usage[] = { N_("scalar clone [--single-branch] [--branch ] [--full-clone]\n" - "\t[--[no-]src] [--[no-]tags] []"), + "\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] []"), NULL }; const char *url; @@ -550,7 +567,8 @@ static int cmd_clone(int argc, const char **argv) if (res) goto cleanup; - res = register_dir(); + /* If --no-maintenance, then skip maintenance command entirely. */ + res = register_dir(maintenance); cleanup: free(branch_to_free); @@ -597,11 +615,14 @@ static int cmd_list(int argc, const char **argv UNUSED) static int cmd_register(int argc, const char **argv) { + int maintenance = 1; struct option options[] = { + OPT_BOOL(0, "maintenance", &maintenance, + N_("specify if background maintenance should be enabled")), OPT_END(), }; const char * const usage[] = { - N_("scalar register []"), + N_("scalar register [--[no-]maintenance] []"), NULL }; @@ -610,7 +631,8 @@ static int cmd_register(int argc, const char **argv) setup_enlistment_directory(argc, argv, usage, options, NULL); - return register_dir(); + /* If --no-maintenance, then leave maintenance as-is. */ + return register_dir(maintenance); } static int get_scalar_repos(const char *key, const char *value, @@ -646,13 +668,19 @@ static int remove_deleted_enlistment(struct strbuf *path) static int cmd_reconfigure(int argc, const char **argv) { int all = 0; + const char *maintenance_str = NULL; + int maintenance = 1; /* Enable maintenance by default. */ + struct option options[] = { OPT_BOOL('a', "all", &all, N_("reconfigure all registered enlistments")), + OPT_STRING(0, "maintenance", &maintenance_str, + N_("(enable|disable|keep)"), + N_("signal how to adjust background maintenance")), OPT_END(), }; const char * const usage[] = { - N_("scalar reconfigure [--all | ]"), + N_("scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | ]"), NULL }; struct string_list scalar_repos = STRING_LIST_INIT_DUP; @@ -672,6 +700,18 @@ static int cmd_reconfigure(int argc, const char **argv) usage_msg_opt(_("--all or , but not both"), usage, options); + if (maintenance_str) { + if (!strcmp(maintenance_str, "enable")) + maintenance = 1; + else if (!strcmp(maintenance_str, "disable")) + maintenance = 0; + else if (!strcmp(maintenance_str, "keep")) + maintenance = -1; + else + die(_("unknown mode for --maintenance option: %s"), + maintenance_str); + } + git_config(get_scalar_repos, &scalar_repos); for (size_t i = 0; i < scalar_repos.nr; i++) { @@ -736,7 +776,8 @@ static int cmd_reconfigure(int argc, const char **argv) the_repository = old_repo; repo_clear(&r); - if (toggle_maintenance(1) >= 0) + if (maintenance >= 0 && + toggle_maintenance(maintenance) >= 0) succeeded = 1; loop_end: @@ -803,13 +844,13 @@ static int cmd_run(int argc, const char **argv) strbuf_release(&buf); if (i == 0) - return register_dir(); + return register_dir(1); if (i > 0) return run_git("maintenance", "run", "--task", tasks[i].task, NULL); - if (register_dir()) + if (register_dir(1)) return -1; for (i = 1; tasks[i].arg; i++) if (run_git("maintenance", "run", diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh index a81662713eb876..bd6f0c40d229b6 100755 --- a/t/t9210-scalar.sh +++ b/t/t9210-scalar.sh @@ -108,7 +108,7 @@ test_expect_success 'scalar register warns when background maintenance fails' ' git init register-repo && GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \ scalar register register-repo 2>err && - grep "could not turn on maintenance" err + grep "could not toggle maintenance" err ' test_expect_success 'scalar unregister' ' @@ -129,6 +129,17 @@ test_expect_success 'scalar unregister' ' scalar unregister vanish ' +test_expect_success 'scalar register --no-maintenance' ' + git init register-no-maint && + event_log="$(pwd)/no-maint.event" && + GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \ + GIT_TRACE2_EVENT="$event_log" \ + GIT_TRACE2_EVENT_DEPTH=100 \ + scalar register --no-maintenance register-no-maint 2>err && + test_must_be_empty err && + test_subcommand ! git maintenance unregister --force err && - grep "could not turn on maintenance" err + grep "could not toggle maintenance" err +' + +test_expect_success 'scalar clone --no-maintenance' ' + GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \ + GIT_TRACE2_EVENT="$(pwd)/no-maint.event" \ + GIT_TRACE2_EVENT_DEPTH=100 \ + scalar clone --no-maintenance "file://$(pwd)/to-clone" no-maint 2>err && + ! grep "could not toggle maintenance" err && + test_subcommand ! git maintenance unregister --force