From 184abdcf0593a5bbf909ed74fbddcc5f79f214be Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 3 May 2025 14:25:46 +0000 Subject: [PATCH 01/13] ci(win+Meson): build in Release mode When the `win+Meson` job was added to Git's CI, modeled after the `win+vs` job, it overlooked that the latter built the Git artifacts in release mode. The reason for this is that there is code in `compat/mingw.c` that turns on the modal assertion dialogs in debug mode, which are very useful when debugging interactively (as they offer to attach Visual Studio's debugger), but they are scarcely useful in CI builds (where that modal dialog would sit around, waiting for a human being to see and deal with it, which obviously won't ever happen). This problem was not realized immediately because of a separate bug: the `win+Meson` job erroneously built using the `gcc` that is in the `PATH` by default on hosted GitHub Actions runners. Since that bug was fixed by switching to `--vsenv`, though, the t7001-mv test consistently timed out after six hours in the CI builds on GitHub, quite often, and wasting build minutes without any benefit in return. The reason for this timeout was a symptom of aforementioned debug mode problem, where the test case 'nonsense mv triggers assertion failure and partially updated index' in t7001-mv triggered an assertion. I originally proposed this here patch to address the timeouts in CI builds. The Git project decided to address this timeout differently, though: by fixing the bug that the t7001-mv test case demonstrated. This does not address the debug mode problem, though, as an `assert()` call could be triggered in other ways in CI, and it should still not cause the CI build to hang but should cause Git to error out instead. To avoid having to accept this here patch, it was then proposed to replace all `assert()` calls in Git's code base by `BUG()` calls. This might be reasonable for independent reasons, but it obviously still does not address the debug mode problem, as `assert()` calls could be easily re-introduced by mistake, and besides, Git has a couple of dependencies that all may have their own `assert()` calls (which are then safely outside the control of the Git project to remove), therefore this here patch is still needed. Signed-off-by: Johannes Schindelin Acked-by: Patrick Steinhardt [jc: rebased on 'maint' to enable fast-tracking the change down] Signed-off-by: Junio C Hamano --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1c8260ecb68b76..323e2ee2a367c6 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 -Dperl=disabled -Dcredential_helpers=wincred + run: meson setup build -Dbuildtype=release -Dperl=disabled -Dcredential_helpers=wincred - name: Compile shell: pwsh run: meson compile -C build From c428216d4df289704ad01bb413c177bc0de32e0c Mon Sep 17 00:00:00 2001 From: Derrick Stolee Date: Wed, 7 May 2025 01:50:34 +0000 Subject: [PATCH 02/13] scalar: customize register_dir()'s behavior In advance of adding a --[no-]maintenance option to several 'scalar' subcommands, extend the register_dir() method to include an option for how it should handle background maintenance. It's important that we understand the context of toggle_maintenance() that will enable _or disable_ maintenance depending on its input value. Add a doc comment with this information. Similarly, update register_dir() to either enable maintenance or leave it alone. Signed-off-by: Derrick Stolee Signed-off-by: Junio C Hamano --- scalar.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/scalar.c b/scalar.c index d359f08bb8e23e..b20b063471a693 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")); @@ -550,7 +565,7 @@ static int cmd_clone(int argc, const char **argv) if (res) goto cleanup; - res = register_dir(); + res = register_dir(1); cleanup: free(branch_to_free); @@ -610,7 +625,7 @@ static int cmd_register(int argc, const char **argv) setup_enlistment_directory(argc, argv, usage, options, NULL); - return register_dir(); + return register_dir(1); } static int get_scalar_repos(const char *key, const char *value, @@ -803,13 +818,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", From 9816e24a78e3973164f324d50caa948ecfa2ab81 Mon Sep 17 00:00:00 2001 From: Derrick Stolee Date: Wed, 7 May 2025 01:50:35 +0000 Subject: [PATCH 03/13] scalar register: add --no-maintenance option When registering a repository with Scalar to get the latest opinionated configuration, the 'scalar register' command will also set up background maintenance. This is a recommended feature for most user scenarios. However, this is not always recommended in some scenarios where background modifications may interfere with foreground activities. Specifically, setting up a clone for use in automation may require doing certain maintenance steps in the foreground that could become blocked by concurrent background maintenance operations. Allow the user to specify --no-maintenance to 'scalar register'. This requires updating the method prototype for register_dir(), so use the default of enabling this value when otherwise specified. Signed-off-by: Derrick Stolee Signed-off-by: Junio C Hamano --- Documentation/scalar.adoc | 8 +++++++- scalar.c | 8 ++++++-- t/t9210-scalar.sh | 13 ++++++++++++- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc index 7e4259c6743f9b..b2b244a8649930 100644 --- a/Documentation/scalar.adoc +++ b/Documentation/scalar.adoc @@ -11,7 +11,7 @@ SYNOPSIS scalar clone [--single-branch] [--branch ] [--full-clone] [--[no-]src] [] scalar list -scalar register [] +scalar register [--[no-]maintenance] [] scalar unregister [] scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [] scalar reconfigure [ --all | ] @@ -117,6 +117,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 ~~~~~~~~~~ diff --git a/scalar.c b/scalar.c index b20b063471a693..da0c46bc96cc76 100644 --- a/scalar.c +++ b/scalar.c @@ -612,11 +612,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 }; @@ -625,7 +628,8 @@ static int cmd_register(int argc, const char **argv) setup_enlistment_directory(argc, argv, usage, options, NULL); - return register_dir(1); + /* If --no-maintenance, then leave maintenance as-is. */ + return register_dir(maintenance); } static int get_scalar_repos(const char *key, const char *value, diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh index a81662713eb876..89a6a2a24d8bd5 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 Date: Wed, 7 May 2025 01:50:36 +0000 Subject: [PATCH 04/13] scalar clone: add --no-maintenance option When creating a new enlistment via 'scalar clone', the default is to set up situations that work for most user scenarios. Background maintenance is one of those highly-recommended options for most users. However, when using 'scalar clone' to create an enlistment in a different situation, such as prepping a VM image, it may be valuable to disable background maintenance so the manual maintenance steps do not get blocked by concurrent background maintenance activities. Add a new --no-maintenance option to 'scalar clone'. Signed-off-by: Derrick Stolee Signed-off-by: Junio C Hamano --- Documentation/scalar.adoc | 7 ++++++- scalar.c | 9 ++++++--- t/t9211-scalar-clone.sh | 11 ++++++++++- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc index b2b244a8649930..7753df3b4352b6 100644 --- a/Documentation/scalar.adoc +++ b/Documentation/scalar.adoc @@ -9,7 +9,7 @@ SYNOPSIS -------- [verse] scalar clone [--single-branch] [--branch ] [--full-clone] - [--[no-]src] [] + [--[no-]src] [--[no-]tags] [--[no-]maintenance] [] scalar list scalar register [--[no-]maintenance] [] scalar unregister [] @@ -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 ~~~~ diff --git a/scalar.c b/scalar.c index da0c46bc96cc76..dd6e1447e08634 100644 --- a/scalar.c +++ b/scalar.c @@ -426,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")), @@ -439,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; @@ -565,7 +567,8 @@ static int cmd_clone(int argc, const char **argv) if (res) goto cleanup; - res = register_dir(1); + /* If --no-maintenance, then skip maintenance command entirely. */ + res = register_dir(maintenance); cleanup: free(branch_to_free); diff --git a/t/t9211-scalar-clone.sh b/t/t9211-scalar-clone.sh index 01f71910f53323..bfbf22a4621843 100755 --- a/t/t9211-scalar-clone.sh +++ b/t/t9211-scalar-clone.sh @@ -177,7 +177,16 @@ test_expect_success 'progress without tty' ' test_expect_success 'scalar clone warns when background maintenance fails' ' GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \ scalar clone "file://$(pwd)/to-clone" maint-fail 2>err && - grep "could not turn on maintenance" err + grep "could not toggle maintenance" err +' + +test_expect_success 'scalar clone --no-maintenance' ' + GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \ + GIT_TRACE2_EVENT="$(pwd)/no-maint.event" \ + GIT_TRACE2_EVENT_DEPTH=100 \ + scalar clone --no-maintenance "file://$(pwd)/to-clone" no-maint 2>err && + ! grep "could not toggle maintenance" err && + test_subcommand ! git maintenance unregister --force Date: Wed, 7 May 2025 01:50:37 +0000 Subject: [PATCH 05/13] scalar reconfigure: add --maintenance= option When users want to enable the latest and greatest configuration options recommended by Scalar after a Git upgrade, 'scalar reconfigure --all' is a great option that iterates over all repos in the multi-valued 'scalar.repos' config key. However, this feature previously forced users to enable background maintenance. In some environments this is not preferred. Add a new --maintenance= option to 'scalar reconfigure' that provides options for enabling (default), disabling, or leaving background maintenance config as-is. Helped-by: Junio C Hamano Signed-off-by: Derrick Stolee Signed-off-by: Junio C Hamano --- Documentation/scalar.adoc | 17 ++++++++++++++--- scalar.c | 23 +++++++++++++++++++++-- t/t9210-scalar.sh | 13 ++++++++++++- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc index 7753df3b4352b6..387527be1ea5bc 100644 --- a/Documentation/scalar.adoc +++ b/Documentation/scalar.adoc @@ -14,7 +14,7 @@ scalar list scalar register [--[no-]maintenance] [] scalar unregister [] scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [] -scalar reconfigure [ --all | ] +scalar reconfigure [--maintenance=] [ --all | ] scalar diagnose [] scalar delete @@ -160,8 +160,19 @@ 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=:: + By default, Scalar configures the enlistment to use Git's + background maintenance feature; this is the same as using the + `--maintenance=enable` value for this option. Use the + `--maintenance=disable` to remove each considered enlistment + from background maintenance. Use `--maitnenance=keep' to leave + the background maintenance configuration untouched for These + repositories. Diagnose ~~~~~~~~ diff --git a/scalar.c b/scalar.c index dd6e1447e08634..847d2dd2f58a1b 100644 --- a/scalar.c +++ b/scalar.c @@ -668,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_(""), + N_("signal how to adjust background maintenance")), OPT_END(), }; const char * const usage[] = { - N_("scalar reconfigure [--all | ]"), + N_("scalar reconfigure [--maintenance=] [--all | ]"), NULL }; struct string_list scalar_repos = STRING_LIST_INIT_DUP; @@ -694,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++) { @@ -758,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: diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh index 89a6a2a24d8bd5..bd6f0c40d229b6 100755 --- a/t/t9210-scalar.sh +++ b/t/t9210-scalar.sh @@ -210,7 +210,18 @@ test_expect_success 'scalar reconfigure' ' GIT_TRACE2_EVENT="$(pwd)/reconfigure" scalar reconfigure -a && test_path_is_file one/src/cron.txt && test true = "$(git -C one/src config core.preloadIndex)" && - test_subcommand git maintenance start Date: Mon, 12 May 2025 12:22:10 +0000 Subject: [PATCH 06/13] pack-bitmap: fix memory leak if `load_bitmap_entries_v1` failed In pack-bitmap.c:load_bitmap_entries_v1, the function `read_bitmap_1` allocates a bitmap and reads index data into it. However, if any of the validation checks following the allocation fail, the allocated bitmap is not freed, resulting in a memory leak. To avoid this, the validation checks should be performed before the bitmap is allocated. Signed-off-by: Lidong Yan <502024330056@smail.nju.edu.cn> Signed-off-by: Junio C Hamano --- pack-bitmap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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); } From 6389579b2f6d0d6aba87563c0a6f1e3942154cc3 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 28 Apr 2025 11:32:12 +0200 Subject: [PATCH 07/13] gitlab-ci: always run MSVC-based Meson job With 7304bd2bc39 (ci: wire up Visual Studio build with Meson, 2025-01-22) we have introduced a CI job that builds and tests Git with Microsoft Visual Studio via Meson. This job is only being executed by default on GitHub Workflows though -- on GitLab CI it is marked as a "manual" job, so the developer has to actively trigger these jobs. The consequence of this split is that any breakage specific to this job is only noticed by developers who mainly work with GitHub. Let's improve this situation by also running the job by default on GitLab CI. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2805cdeecb6a54..da7a70f50465ff 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" From 9c9f8849a2a5ca058e8a9a1dfd6c9c925533e581 Mon Sep 17 00:00:00 2001 From: Aditya Garg Date: Mon, 12 May 2025 08:11:19 +0000 Subject: [PATCH 08/13] send-email: try to get fqdn by running hostname -f on Linux and macOS `hostname` is a popular command available on both Linux and macOS. As per the man-page[1], `hostname -f` command returns the fully qualified domain name (FQDN) of the system. The current Net::Domain perl module being used in the script for the same has been quite unrealiable in many cases. Thankfully, we now have a better check for valid_fqdn, which does reject the invalid FQDNs given by this module properly, but at the same time, it will result in a fallback to 'localhost.localdomain' being used. `hostname -f` has been quite reliable (probably even more reliable than the Net::Domain module) and before falling back to 'localhost.localdomain', we should try to use it. Interestingly, the `hostname` command is actually used by perl modules like Net::Domain[2] and Sys::Hostname[3] to get the hostname. So, lets give `hostname -f` a chance as well! [1]: https://man7.org/linux/man-pages/man1/hostname.1.html [2]: https://github.com/Perl/perl5/blob/blead/cpan/libnet/lib/Net/Domain.pm#L88 [3]: https://github.com/Perl/perl5/blob/blead/ext/Sys-Hostname/Hostname.pm#L93 Signed-off-by: Aditya Garg Signed-off-by: Junio C Hamano --- git-send-email.perl | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/git-send-email.perl b/git-send-email.perl index 1f613fa979df45..db5ba8deca8939 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -1386,8 +1386,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 { From e918917360817e7bb58baae2bc166998ffdc8726 Mon Sep 17 00:00:00 2001 From: Derrick Stolee Date: Wed, 14 May 2025 09:52:44 -0400 Subject: [PATCH 09/13] scalar reconfigure: improve --maintenance docs The --maintenance option for 'scalar reconfigure' has three possible values. Improve the documentation by specifying the option in the -h help menu and usage information. Signed-off-by: Derrick Stolee Signed-off-by: Junio C Hamano --- Documentation/scalar.adoc | 13 ++++++------- scalar.c | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc index 387527be1ea5bc..4bd5b150e8e1d4 100644 --- a/Documentation/scalar.adoc +++ b/Documentation/scalar.adoc @@ -14,7 +14,7 @@ scalar list scalar register [--[no-]maintenance] [] scalar unregister [] scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [] -scalar reconfigure [--maintenance=] [ --all | ] +scalar reconfigure [--maintenance=(enable|disable|keep)] [ --all | ] scalar diagnose [] scalar delete @@ -165,14 +165,13 @@ reconfigure the enlistment. registered with Scalar by the `scalar.repo` config key. Use this option after each upgrade to get the latest features. ---maintenance=:: +--maintenance=(enable|disable|keep):: By default, Scalar configures the enlistment to use Git's background maintenance feature; this is the same as using the - `--maintenance=enable` value for this option. Use the - `--maintenance=disable` to remove each considered enlistment - from background maintenance. Use `--maitnenance=keep' to leave - the background maintenance configuration untouched for These - repositories. + `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/scalar.c b/scalar.c index 847d2dd2f58a1b..355baf75e499cb 100644 --- a/scalar.c +++ b/scalar.c @@ -675,12 +675,12 @@ static int cmd_reconfigure(int argc, const char **argv) OPT_BOOL('a', "all", &all, N_("reconfigure all registered enlistments")), OPT_STRING(0, "maintenance", &maintenance_str, - N_(""), + N_("(enable|disable|keep)"), N_("signal how to adjust background maintenance")), OPT_END(), }; const char * const usage[] = { - N_("scalar reconfigure [--maintenance=] [--all | ]"), + N_("scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | ]"), NULL }; struct string_list scalar_repos = STRING_LIST_INIT_DUP; From d2c3e94a0aa1755677c18b16d05b71e94c700029 Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Wed, 14 May 2025 20:33:25 +0000 Subject: [PATCH 10/13] replay: replace the_repository with repo parameter passed to cmd_replay () Replace the_repository everywhere with repo, feed repo from cmd_replay() to all the other functions in the file that need it, and remove the UNUSED annotation on repo. Signed-off-by: Elijah Newren Signed-off-by: Junio C Hamano --- builtin/replay.c | 65 ++++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 30 deletions(-) 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; From fba60a4841ce2185200e82cdb80428e9819233f8 Mon Sep 17 00:00:00 2001 From: Lucas Seiki Oshiro Date: Thu, 15 May 2025 22:01:58 -0300 Subject: [PATCH 11/13] json-writer: add docstrings to jw_* functions Add a docstring for each function that manipulates json_writers. Helped-by: Junio C Hamano Helped-by: Patrick Steinhardt Helped-by: Karthik Nayak Signed-off-by: Lucas Seiki Oshiro Acked-by: Karthik Nayak Signed-off-by: Junio C Hamano --- json-writer.c | 4 -- json-writer.h | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 4 deletions(-) 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..0e8e6c3ddc3957 100644 --- a/json-writer.h +++ b/json-writer.h @@ -69,42 +69,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 */ From da692298ac64a835378237ed4870737fb19552fc Mon Sep 17 00:00:00 2001 From: Lucas Seiki Oshiro Date: Thu, 15 May 2025 22:01:59 -0300 Subject: [PATCH 12/13] json-writer: describe the usage of jw_* functions Provide an overview of the set of functions used for manipulating `json_writer`s, by describing what functions should be used for each JSON-related task. Helped-by: Junio C Hamano Helped-by: Patrick Steinhardt Helped-by: Karthik Nayak Signed-off-by: Lucas Seiki Oshiro Acked-by: Karthik Nayak Signed-off-by: Junio C Hamano --- json-writer.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/json-writer.h b/json-writer.h index 0e8e6c3ddc3957..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: From 845c48a16a7f7b2c44d8cb137b16a4a1f0140229 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 23 May 2025 15:33:39 -0700 Subject: [PATCH 13/13] The seventeenth batch Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.50.0.adoc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) 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).