All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] maintenance: use systemd timers on Linux
@ 2021-05-01 14:52 Lénaïc Huard
  2021-05-01 20:02 ` brian m. carlson
                   ` (5 more replies)
  0 siblings, 6 replies; 138+ messages in thread
From: Lénaïc Huard @ 2021-05-01 14:52 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Derrick Stolee, Eric Sunshine, Lénaïc Huard

The existing mechanism for scheduling background maintenance is done
through cron. On Linux systems managed by systemd, systemd provides an
alternative to schedule recurring tasks: systemd timers.

The main motivations to implement systemd timers in addition to cron
are:
* cron is optional and Linux systems running systemd might not have it
  installed.
* The execution of `crontab -l` can tell us if cron is installed but not
  if the daemon is actually running.
* With systemd, each service is run in its own cgroup and its logs are
  tagged by the service inside journald. With cron, all scheduled tasks
  are running in the cron daemon cgroup and all the logs of the
  user-scheduled tasks are pretended to belong to the system cron
  service.
  Concretely, a user that doesn’t have access to the system logs won’t
  have access to the log of its own tasks scheduled by cron whereas he
  will have access to the log of its own tasks scheduled by systemd
  timer.

In order to schedule git maintenance, we need two unit template files:
* ~/.config/systemd/user/git-maintenance@.service
  to define the command to be started by systemd and
* ~/.config/systemd/user/git-maintenance@.timer
  to define the schedule at which the command should be run.

Those units are templates that are parametrized by the frequency.

Based on those templates, 3 timers are started:
* git-maintenance@hourly.timer
* git-maintenance@daily.timer
* git-maintenance@weekly.timer

The command launched by those three timers are the same than with the
other scheduling methods:

git for-each-repo --config=maintenance.repo maintenance run
--schedule=%i

with the full path for git to ensure that the version of git launched
for the scheduled maintenance is the same as the one used to run
`maintenance start`.

The timer unit contains `Persistent=true` so that, if the computer is
powered down when a maintenance task should run, the task will be run
when the computer is back powered on.

Signed-off-by: Lénaïc Huard <lenaic@lhuard.fr>
---
 Documentation/git-maintenance.txt |  49 ++++++++
 builtin/gc.c                      | 188 +++++++++++++++++++++++++++++-
 t/t7900-maintenance.sh            |  51 ++++++++
 3 files changed, 287 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-maintenance.txt b/Documentation/git-maintenance.txt
index 80ddd33ceb..30443b417a 100644
--- a/Documentation/git-maintenance.txt
+++ b/Documentation/git-maintenance.txt
@@ -279,6 +279,55 @@ schedule to ensure you are executing the correct binaries in your
 schedule.
 
 
+BACKGROUND MAINTENANCE ON LINUX SYSTEMD SYSTEMD
+-----------------------------------------------
+
+While Linux supports `cron`, depending on the distribution, `cron` may
+be an optional package not necessarily installed. On modern Linux
+distributions, systemd timers are superseding it.
+
+If user systemd timers are available, they will be used as a replacement
+of `cron`.
+
+In this case, `git maintenance start` will create user systemd timer units
+and start the timers. The current list of user-scheduled tasks can be found
+by running `systemctl --user list-timers`. The timers written by `git
+maintenance start` are similar to this:
+
+-----------------------------------------------------------------------
+$ systemctl --user list-timers
+NEXT                         LEFT          LAST                         PASSED     UNIT                         ACTIVATES
+Thu 2021-04-29 19:00:00 CEST 42min left    Thu 2021-04-29 18:00:11 CEST 17min ago  git-maintenance@hourly.timer git-maintenance@hourly.service
+Fri 2021-04-30 00:00:00 CEST 5h 42min left Thu 2021-04-29 00:00:11 CEST 18h ago    git-maintenance@daily.timer  git-maintenance@daily.service
+Mon 2021-05-03 00:00:00 CEST 3 days left   Mon 2021-04-26 00:00:11 CEST 3 days ago git-maintenance@weekly.timer git-maintenance@weekly.service
+
+3 timers listed.
+Pass --all to see loaded but inactive timers, too.
+-----------------------------------------------------------------------
+
+One timer is registered for each `--schedule=<frequency>` option.
+
+The definition of the systemd units can be inspected in the following files:
+
+-----------------------------------------------------------------------
+~/.config/systemd/user/git-maintenance@.timer
+~/.config/systemd/user/git-maintenance@.service
+~/.config/systemd/user/timers.target.wants/git-maintenance@hourly.timer
+~/.config/systemd/user/timers.target.wants/git-maintenance@daily.timer
+~/.config/systemd/user/timers.target.wants/git-maintenance@weekly.timer
+-----------------------------------------------------------------------
+
+`git maintenance start` will overwrite these files and start the timer
+again with `systemctl --user`, so any customization should be done by
+creating a drop-in file
+`~/.config/systemd/user/git-maintenance@.service.d/*.conf`.
+
+`git maintenance stop` will stop the user systemd timers and delete
+the above mentioned files.
+
+For more details, see systemd.timer(5)
+
+
 BACKGROUND MAINTENANCE ON MACOS SYSTEMS
 ---------------------------------------
 
diff --git a/builtin/gc.c b/builtin/gc.c
index ef7226d7bc..913fcfc882 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -1872,6 +1872,25 @@ static int schtasks_update_schedule(int run_maintenance, int fd, const char *cmd
 		return schtasks_remove_tasks(cmd);
 }
 
+static int is_crontab_available(const char *cmd)
+{
+	struct child_process child = CHILD_PROCESS_INIT;
+
+	strvec_split(&child.args, cmd);
+	strvec_push(&child.args, "-l");
+	child.no_stdin = 1;
+	child.no_stdout = 1;
+	child.no_stderr = 1;
+	child.silent_exec_failure = 1;
+
+	if (start_command(&child))
+		return 0;
+	/* Ignore exit code, as an empty crontab will return error. */
+	finish_command(&child);
+
+	return 1;
+}
+
 #define BEGIN_LINE "# BEGIN GIT MAINTENANCE SCHEDULE"
 #define END_LINE "# END GIT MAINTENANCE SCHEDULE"
 
@@ -1959,10 +1978,164 @@ static int crontab_update_schedule(int run_maintenance, int fd, const char *cmd)
 	return result;
 }
 
+static int is_systemd_timer_available(const char *cmd)
+{
+	struct child_process child = CHILD_PROCESS_INIT;
+
+	strvec_split(&child.args, cmd);
+	strvec_pushl(&child.args, "--user", "list-timers", NULL);
+	child.no_stdin = 1;
+	child.no_stdout = 1;
+	child.no_stderr = 1;
+	child.silent_exec_failure = 1;
+
+	if (start_command(&child))
+		return 0;
+	if (finish_command(&child))
+		return 0;
+
+	return 1;
+}
+
+static char *systemd_timer_timer_filename()
+{
+	const char *filename = "~/.config/systemd/user/git-maintenance@.timer";
+	char *expanded = expand_user_path(filename, 0);
+	if (!expanded)
+		die(_("failed to expand path '%s'"), filename);
+
+	return expanded;
+}
+
+static char *systemd_timer_service_filename()
+{
+	const char *filename =
+		"~/.config/systemd/user/git-maintenance@.service";
+	char *expanded = expand_user_path(filename, 0);
+	if (!expanded)
+		die(_("failed to expand path '%s'"), filename);
+
+	return expanded;
+}
+
+static int systemd_timer_enable_unit(int enable,
+				     enum schedule_priority schedule,
+				     const char *cmd)
+{
+	struct child_process child = CHILD_PROCESS_INIT;
+	const char *frequency = get_frequency(schedule);
+
+	strvec_split(&child.args, cmd);
+	strvec_push(&child.args, "--user");
+	if (enable)
+		strvec_push(&child.args, "enable");
+	else
+		strvec_push(&child.args, "disable");
+	strvec_push(&child.args, "--now");
+	strvec_pushf(&child.args, "git-maintenance@%s.timer", frequency);
+
+	if (start_command(&child))
+		die(_("failed to run systemctl"));
+	return finish_command(&child);
+}
+
+static int systemd_timer_delete_unit_templates()
+{
+	char *filename = systemd_timer_timer_filename();
+	unlink(filename);
+	free(filename);
+
+	filename = systemd_timer_service_filename();
+	unlink(filename);
+	free(filename);
+
+	return 0;
+}
+
+static int systemd_timer_delete_units(const char *cmd)
+{
+	return systemd_timer_enable_unit(0, SCHEDULE_HOURLY, cmd) ||
+	       systemd_timer_enable_unit(0, SCHEDULE_DAILY, cmd) ||
+	       systemd_timer_enable_unit(0, SCHEDULE_WEEKLY, cmd) ||
+	       systemd_timer_delete_unit_templates();
+}
+
+static int systemd_timer_write_unit_templates(const char *exec_path)
+{
+	char *filename;
+	FILE *file;
+	const char *unit;
+
+	filename = systemd_timer_timer_filename();
+	if (safe_create_leading_directories(filename))
+		die(_("failed to create directories for '%s'"), filename);
+	file = xfopen(filename, "w");
+	free(filename);
+
+	unit = "[Unit]\n"
+	       "Description=Optimize Git repositories data\n"
+	       "\n"
+	       "[Timer]\n"
+	       "OnCalendar=%i\n"
+	       "Persistent=true\n"
+	       "\n"
+	       "[Install]\n"
+	       "WantedBy=timers.target\n";
+	fputs(unit, file);
+	fclose(file);
+
+	filename = systemd_timer_service_filename();
+	if (safe_create_leading_directories(filename))
+		die(_("failed to create directories for '%s'"), filename);
+	file = xfopen(filename, "w");
+	free(filename);
+
+	unit = "[Unit]\n"
+	       "Description=Optimize Git repositories data\n"
+	       "\n"
+	       "[Service]\n"
+	       "Type=oneshot\n"
+	       "ExecStart=\"%1$s/git\" --exec-path=\"%1$s\" for-each-repo --config=maintenance.repo maintenance run --schedule=%%i\n"
+	       "LockPersonality=yes\n"
+	       "MemoryDenyWriteExecute=yes\n"
+	       "NoNewPrivileges=yes\n"
+	       "RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6\n"
+	       "RestrictNamespaces=yes\n"
+	       "RestrictRealtime=yes\n"
+	       "RestrictSUIDSGID=yes\n"
+	       "SystemCallArchitectures=native\n"
+	       "SystemCallFilter=@system-service\n";
+	fprintf(file, unit, exec_path);
+	fclose(file);
+
+	return 0;
+}
+
+static int systemd_timer_setup_units(const char *cmd)
+{
+	const char *exec_path = git_exec_path();
+
+	return systemd_timer_write_unit_templates(exec_path) ||
+	       systemd_timer_enable_unit(1, SCHEDULE_HOURLY, cmd) ||
+	       systemd_timer_enable_unit(1, SCHEDULE_DAILY, cmd) ||
+	       systemd_timer_enable_unit(1, SCHEDULE_WEEKLY, cmd);
+}
+
+static int systemd_timer_update_schedule(int run_maintenance, int fd,
+					 const char *cmd)
+{
+	if (run_maintenance)
+		return systemd_timer_setup_units(cmd);
+	else
+		return systemd_timer_delete_units(cmd);
+}
+
 #if defined(__APPLE__)
 static const char platform_scheduler[] = "launchctl";
 #elif defined(GIT_WINDOWS_NATIVE)
 static const char platform_scheduler[] = "schtasks";
+#elif defined(__linux__)
+static const char platform_scheduler[] = "crontab_or_systemctl";
 #else
 static const char platform_scheduler[] = "crontab";
 #endif
@@ -1986,6 +2159,15 @@ static int update_background_schedule(int enable)
 		cmd = sep + 1;
 	}
 
+	if (!strcmp(scheduler, "crontab_or_systemctl")) {
+		if (is_systemd_timer_available("systemctl"))
+			scheduler = cmd = "systemctl";
+		else if (is_crontab_available("crontab"))
+			scheduler = cmd = "crontab";
+		else
+			die(_("Neither systemd timers nor crontab are available"));
+	}
+
 	if (hold_lock_file_for_update(&lk, lock_path, LOCK_NO_DEREF) < 0)
 		return error(_("another process is scheduling background maintenance"));
 
@@ -1995,10 +2177,14 @@ static int update_background_schedule(int enable)
 		result = schtasks_update_schedule(enable, get_lock_file_fd(&lk), cmd);
 	else if (!strcmp(scheduler, "crontab"))
 		result = crontab_update_schedule(enable, get_lock_file_fd(&lk), cmd);
+	else if (!strcmp(scheduler, "systemctl"))
+		result = systemd_timer_update_schedule(
+			enable, get_lock_file_fd(&lk), cmd);
 	else
-		die("unknown background scheduler: %s", scheduler);
+		die(_("unknown background scheduler: %s"), scheduler);
 
 	rollback_lock_file(&lk);
+	free(lock_path);
 	free(testing);
 	return result;
 }
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index 2412d8c5c0..dd281789f4 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -20,6 +20,20 @@ test_xmllint () {
 	fi
 }
 
+test_lazy_prereq SYSTEMD_ANALYZE '
+	systemd-analyze --help >out &&
+	grep -w verify out
+'
+
+test_systemd_analyze_verify () {
+	if test_have_prereq SYSTEMD_ANALYZE
+	then
+		systemd-analyze verify "$@"
+	else
+		true
+	fi
+}
+
 test_expect_success 'help text' '
 	test_expect_code 129 git maintenance -h 2>err &&
 	test_i18ngrep "usage: git maintenance <subcommand>" err &&
@@ -615,6 +629,43 @@ test_expect_success 'start and stop Windows maintenance' '
 	test_cmp expect args
 '
 
+test_expect_success 'start and stop Linux/systemd maintenance' '
+	write_script print-args <<-\EOF &&
+	echo $* >>args
+	EOF
+
+	rm -f args &&
+	GIT_TEST_MAINT_SCHEDULER="systemctl:./print-args" git maintenance start &&
+
+	# start registers the repo
+	git config --get --global --fixed-value maintenance.repo "$(pwd)" &&
+
+	test_systemd_analyze_verify "$HOME/.config/systemd/user/git-maintenance@.service" &&
+
+	rm -f expect &&
+	for frequency in hourly daily weekly
+	do
+		echo "--user enable --now git-maintenance@${frequency}.timer" >>expect || return 1
+	done &&
+	test_cmp expect args &&
+
+	rm -f args &&
+	GIT_TEST_MAINT_SCHEDULER="systemctl:./print-args" git maintenance stop &&
+
+	# stop does not unregister the repo
+	git config --get --global --fixed-value maintenance.repo "$(pwd)" &&
+
+	test_path_is_missing "$HOME/.config/systemd/user/git-maintenance@.timer" &&
+	test_path_is_missing "$HOME/.config/systemd/user/git-maintenance@.service" &&
+
+	rm -f expect &&
+	for frequency in hourly daily weekly
+	do
+		echo "--user disable --now git-maintenance@${frequency}.timer" >>expect || return 1
+	done &&
+	test_cmp expect args
+'
+
 test_expect_success 'register preserves existing strategy' '
 	git config maintenance.strategy none &&
 	git maintenance register &&
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 138+ messages in thread

end of thread, other threads:[~2021-09-27 21:44 UTC | newest]

Thread overview: 138+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-01 14:52 [PATCH] maintenance: use systemd timers on Linux Lénaïc Huard
2021-05-01 20:02 ` brian m. carlson
2021-05-02  5:28 ` Bagas Sanjaya
2021-05-02  6:49   ` Eric Sunshine
2021-05-02  6:45 ` Eric Sunshine
2021-05-02 14:10   ` Phillip Wood
2021-05-05 12:19     ` Đoàn Trần Công Danh
2021-05-05 14:57       ` Phillip Wood
2021-05-05 12:01   ` Ævar Arnfjörð Bjarmason
2021-05-09 22:34     ` Lénaïc Huard
2021-05-10 13:03       ` Ævar Arnfjörð Bjarmason
2021-05-02 11:12 ` Bagas Sanjaya
2021-05-03 12:04 ` Derrick Stolee
2021-05-09 21:32 ` [PATCH v2 0/1] " Lénaïc Huard
2021-05-09 21:32   ` [PATCH v2 1/1] " Lénaïc Huard
2021-05-10  1:20     ` Đoàn Trần Công Danh
2021-05-10  2:48       ` Eric Sunshine
2021-05-10  6:25         ` Junio C Hamano
2021-05-12  0:29           ` Đoàn Trần Công Danh
2021-05-12  6:59             ` Felipe Contreras
2021-05-12 13:26               ` Phillip Wood
2021-05-12 13:38             ` Phillip Wood
2021-05-12 15:41               ` Đoàn Trần Công Danh
2021-05-10 18:03     ` Phillip Wood
2021-05-10 18:25       ` Eric Sunshine
2021-05-10 20:09         ` Phillip Wood
2021-05-10 20:52           ` Eric Sunshine
2021-06-08 14:55       ` Lénaïc Huard
2021-05-10 19:15     ` Martin Ågren
2021-05-11 14:50     ` Phillip Wood
2021-05-11 17:31     ` Derrick Stolee
2021-05-20 22:13   ` [PATCH v3 0/4] " Lénaïc Huard
2021-05-20 22:13     ` [PATCH v3 1/4] cache.h: rename "xdg_config_home" to "xdg_config_home_git" Lénaïc Huard
2021-05-20 23:44       ` Đoàn Trần Công Danh
2021-05-20 22:13     ` [PATCH v3 2/4] maintenance: introduce ENABLE/DISABLE for code clarity Lénaïc Huard
2021-05-20 22:13     ` [PATCH v3 3/4] maintenance: `git maintenance run` learned `--scheduler=<scheduler>` Lénaïc Huard
2021-05-21  9:52       ` Bagas Sanjaya
2021-05-20 22:13     ` [PATCH v3 4/4] maintenance: optionally use systemd timers on Linux Lénaïc Huard
2021-05-21  9:59       ` Bagas Sanjaya
2021-05-21 16:59         ` Derrick Stolee
2021-05-22  6:57           ` Johannes Schindelin
2021-05-23 18:36             ` Felipe Contreras
2021-05-23 23:27               ` brian m. carlson
2021-05-24  1:18                 ` Felipe Contreras
2021-05-24  7:03                 ` Ævar Arnfjörð Bjarmason
2021-05-24 15:51                   ` Junio C Hamano
2021-05-25  1:50                     ` Johannes Schindelin
2021-05-25 11:13                       ` Felipe Contreras
2021-05-26 10:29                       ` CoC, inclusivity etc. (was "Re: [...] systemd timers on Linux") Ævar Arnfjörð Bjarmason
2021-05-26 16:05                         ` Felipe Contreras
2021-05-27 14:24                         ` Jeff King
2021-05-27 17:30                           ` Felipe Contreras
2021-05-27 23:58                           ` Junio C Hamano
2021-05-28 14:44                           ` Phillip Susi
2021-05-30 21:58                             ` Jeff King
2021-05-24 17:52                   ` [PATCH v3 4/4] maintenance: optionally use systemd timers on Linux Felipe Contreras
2021-05-24  7:15     ` [PATCH v4 0/4] add support for " Lénaïc Huard
2021-05-24  7:15       ` [PATCH v4 1/4] cache.h: Introduce a generic "xdg_config_home_for(…)" function Lénaïc Huard
2021-05-24  9:33         ` Phillip Wood
2021-05-24 12:23           ` Đoàn Trần Công Danh
2021-05-24  7:15       ` [PATCH v4 2/4] maintenance: introduce ENABLE/DISABLE for code clarity Lénaïc Huard
2021-05-24  9:41         ` Phillip Wood
2021-05-24 12:36           ` Đoàn Trần Công Danh
2021-05-25  7:18             ` Lénaïc Huard
2021-05-25  8:02               ` Junio C Hamano
2021-05-24  9:47         ` Ævar Arnfjörð Bjarmason
2021-05-24  7:15       ` [PATCH v4 3/4] maintenance: `git maintenance run` learned `--scheduler=<scheduler>` Lénaïc Huard
2021-05-24 10:12         ` Phillip Wood
2021-05-30  6:39           ` Lénaïc Huard
2021-05-30 10:16             ` Phillip Wood
2021-05-24  7:15       ` [PATCH v4 4/4] maintenance: add support for systemd timers on Linux Lénaïc Huard
2021-05-24  9:55         ` Ævar Arnfjörð Bjarmason
2021-05-24 16:39           ` Eric Sunshine
2021-05-24 18:08         ` Felipe Contreras
2021-05-26 10:26         ` Phillip Wood
2021-05-24  9:04       ` [PATCH v4 0/4] " Junio C Hamano
2021-06-08 13:39       ` [PATCH v5 0/3] " Lénaïc Huard
2021-06-08 13:39         ` [PATCH v5 1/3] cache.h: Introduce a generic "xdg_config_home_for(…)" function Lénaïc Huard
2021-06-08 13:39         ` [PATCH v5 2/3] maintenance: `git maintenance run` learned `--scheduler=<scheduler>` Lénaïc Huard
2021-06-08 13:40         ` [PATCH v5 3/3] maintenance: add support for systemd timers on Linux Lénaïc Huard
2021-06-09  9:34           ` Jeff King
2021-06-09 15:01           ` Phillip Wood
2021-06-09  0:21         ` [PATCH v5 0/3] " Junio C Hamano
2021-06-09 14:54         ` Phillip Wood
2021-06-12 16:50         ` [PATCH v6 0/3] maintenance: " Lénaïc Huard
2021-06-12 16:50           ` [PATCH v6 1/3] cache.h: Introduce a generic "xdg_config_home_for(…)" function Lénaïc Huard
2021-06-12 16:50           ` [PATCH v6 2/3] maintenance: `git maintenance run` learned `--scheduler=<scheduler>` Lénaïc Huard
2021-06-14  4:36             ` Eric Sunshine
2021-06-16 18:12               ` Derrick Stolee
2021-06-17  4:11                 ` Eric Sunshine
2021-06-17 14:26               ` Phillip Wood
2021-07-02 15:04               ` Lénaïc Huard
2021-06-12 16:50           ` [PATCH v6 3/3] maintenance: add support for systemd timers on Linux Lénaïc Huard
2021-07-02 14:25           ` [PATCH v7 0/3] " Lénaïc Huard
2021-07-02 14:25             ` [PATCH v7 1/3] cache.h: Introduce a generic "xdg_config_home_for(…)" function Lénaïc Huard
2021-07-02 14:25             ` [PATCH v7 2/3] maintenance: `git maintenance run` learned `--scheduler=<scheduler>` Lénaïc Huard
2021-07-06 19:56               ` Ævar Arnfjörð Bjarmason
2021-07-06 20:52                 ` Junio C Hamano
2021-07-13  0:15                   ` Jeff King
2021-07-13  2:22                     ` Eric Sunshine
2021-07-13  3:56                       ` Jeff King
2021-07-13  5:17                         ` Eric Sunshine
2021-07-13  7:04                       ` Bagas Sanjaya
2021-07-06 21:18                 ` Felipe Contreras
2021-08-23 20:06                 ` Lénaïc Huard
2021-08-23 22:30                   ` Junio C Hamano
2021-07-02 14:25             ` [PATCH v7 3/3] maintenance: add support for systemd timers on Linux Lénaïc Huard
2021-07-06 20:03               ` Ævar Arnfjörð Bjarmason
2021-07-02 18:18             ` [PATCH v7 0/3] " Junio C Hamano
2021-07-06 13:18             ` Phillip Wood
2021-08-23 20:40             ` [PATCH v8 " Lénaïc Huard
2021-08-23 20:40               ` [PATCH v8 1/3] cache.h: Introduce a generic "xdg_config_home_for(…)" function Lénaïc Huard
2021-08-23 20:40               ` [PATCH v8 2/3] maintenance: `git maintenance run` learned `--scheduler=<scheduler>` Lénaïc Huard
2021-08-24 17:45                 ` Derrick Stolee
2021-08-23 20:40               ` [PATCH v8 3/3] maintenance: add support for systemd timers on Linux Lénaïc Huard
2021-08-24 17:45                 ` Derrick Stolee
2021-08-24 17:47               ` [PATCH v8 0/3] " Derrick Stolee
2021-08-27 21:02               ` [PATCH v9 " Lénaïc Huard
2021-08-27 21:02                 ` [PATCH v9 1/3] cache.h: Introduce a generic "xdg_config_home_for(…)" function Lénaïc Huard
2021-08-27 21:02                 ` [PATCH v9 2/3] maintenance: `git maintenance run` learned `--scheduler=<scheduler>` Lénaïc Huard
2021-08-27 23:54                   ` Ramsay Jones
2021-08-27 21:02                 ` [PATCH v9 3/3] maintenance: add support for systemd timers on Linux Lénaïc Huard
2021-09-04 20:54                 ` [PATCH v10 0/3] " Lénaïc Huard
2021-09-04 20:54                   ` [PATCH v10 1/3] cache.h: Introduce a generic "xdg_config_home_for(…)" function Lénaïc Huard
2021-09-04 20:54                   ` [PATCH v10 2/3] maintenance: `git maintenance run` learned `--scheduler=<scheduler>` Lénaïc Huard
2021-09-04 20:55                   ` [PATCH v10 3/3] maintenance: add support for systemd timers on Linux Lénaïc Huard
2021-09-07 16:48                   ` [PATCH v10 0/3] " Derrick Stolee
2021-09-08 11:44                     ` Derrick Stolee
2021-09-09  5:52                       ` Lénaïc Huard
2021-09-09 19:55                         ` Derrick Stolee
2021-09-27 12:50                           ` Ævar Arnfjörð Bjarmason
2021-09-27 21:44                             ` Lénaïc Huard
2021-08-17 17:22         ` [PATCH v5 0/3] " Derrick Stolee
2021-08-17 19:43           ` Phillip Wood
2021-08-17 20:29             ` Derrick Stolee
2021-08-18  5:56           ` Lénaïc Huard
2021-08-18 13:28             ` Derrick Stolee
2021-08-18 18:23               ` Junio C Hamano

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.