From: "Derrick Stolee via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Eric Sunshine <sunshine@sunshineco.com>,
Derrick Stolee <stolee@gmail.com>,
Derrick Stolee <derrickstolee@github.com>
Subject: [PATCH v3 0/4] Maintenance IV: Platform-specific background maintenance
Date: Fri, 13 Nov 2020 14:00:20 +0000 [thread overview]
Message-ID: <pull.776.v3.git.1605276024.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.776.v2.git.1604520368.gitgitgadget@gmail.com>
This is based on ds/maintenance-part-3.
After sitting with the background maintenance as it has been cooking, I
wanted to come back around and implement the background maintenance for
Windows. However, I noticed that there were some things bothering me with
background maintenance on my macOS machine. These are detailed in PATCH 3,
but the tl;dr is that 'cron' is not recommended by Apple and instead
'launchd' satisfies our needs.
This series implements the background scheduling so git maintenance
(start|stop) works on those platforms. I've been operating with these
schedules for a while now without the problems described in the patches.
There is a particularly annoying case about console windows popping up on
Windows, but PATCH 4 describes a plan to get around that.
Updates in V3
=============
* This actually includes the feedback responses I had intended for v2.
Sorry about that!
* One major change is the use of a 'struct child_process' instead of just
run_command_v_opt() so we can suppress error messages from the schedule
helpers. We will rely on exit code and present our own error messages, as
necessary.
* Some doc and test fixes.
Updates in V2
=============
* This is a faster turnaround for a v2 than I would normally like, but Eric
inspired extra documentation about how to customize background schedules.
* New extensions to git-maintenance.txt include guidelines for inspecting
what git maintenance start does and how to customize beyond that. This
includes a new PATCH 2 that includes documentation for 'cron' on
non-macOS non-Windows systems.
* Several improvements, especially in the tests, are included.
* While testing manually, I noticed that somehow I had incorrectly had an
opening <dict> tag instead of a closing </dict> tag in the hourly format
on macOS. I found that the xmllint tool can verify the XML format of a
file, which catches the bug. This seems like a good approach since the
test is macOS-only. Does anyone have concerns about adding this
dependency?
Thanks, -Stolee
cc: jrnieder@gmail.com [jrnieder@gmail.com], jonathantanmy@google.com
[jonathantanmy@google.com], sluongng@gmail.com [sluongng@gmail.com]cc:
Derrick Stolee stolee@gmail.com [stolee@gmail.com]cc: Đoàn Trần Công Danh
congdanhqx@gmail.com [congdanhqx@gmail.com]cc: Martin Ågren
martin.agren@gmail.com [martin.agren@gmail.com]cc: Eric Sunshine
sunshine@sunshineco.com [sunshine@sunshineco.com]cc: Derrick Stolee
stolee@gmail.com [stolee@gmail.com]
Derrick Stolee (4):
maintenance: extract platform-specific scheduling
maintenance: include 'cron' details in docs
maintenance: use launchctl on macOS
maintenance: use Windows scheduled tasks
Documentation/git-maintenance.txt | 116 +++++++++
builtin/gc.c | 417 ++++++++++++++++++++++++++++--
t/t7900-maintenance.sh | 75 +++++-
t/test-lib.sh | 4 +
4 files changed, 592 insertions(+), 20 deletions(-)
base-commit: 0016b618182f642771dc589cf0090289f9fe1b4f
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-776%2Fderrickstolee%2Fmaintenance%2FmacOS-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-776/derrickstolee/maintenance/macOS-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/776
Range-diff vs v2:
1: d35f1aa162 = 1: d35f1aa162 maintenance: extract platform-specific scheduling
2: 709a173720 ! 2: 0dfe53092e maintenance: include 'cron' details in docs
@@ Commit message
baseline can provide a way forward for users who have never worked with
cron schedules.
+ Helped-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
## Documentation/git-maintenance.txt ##
@@ Documentation/git-maintenance.txt: Further, the `git gc` command should not be c
+---------------------------------------
+
+The standard mechanism for scheduling background tasks on POSIX systems
-+is `cron`. This tool executes commands based on a given schedule. The
++is cron(8). This tool executes commands based on a given schedule. The
+current list of user-scheduled tasks can be found by running `crontab -l`.
+The schedule written by `git maintenance start` is similar to this:
+
@@ Documentation/git-maintenance.txt: Further, the `git gc` command should not be c
+Any modifications within this region will be completely deleted by
+`git maintenance stop` or overwritten by `git maintenance start`.
+
-+The `<path>` string is loaded to specifically use the location for the
-+`git` executable used in the `git maintenance start` command. This allows
-+for multiple versions to be compatible. However, if the same user runs
-+`git maintenance start` with multiple Git executables, then only the
-+latest executable will be used.
++The `crontab` entry specifies the full path of the `git` executable to
++ensure that the executed `git` command is the same one with which
++`git maintenance start` was issued independent of `PATH`. If the same user
++runs `git maintenance start` with multiple Git executables, then only the
++latest executable is used.
+
+These commands use `git for-each-repo --config=maintenance.repo` to run
+`git maintenance run --schedule=<frequency>` on each repository listed in
+the multi-valued `maintenance.repo` config option. These are typically
-+loaded from the user-specific global config located at `~/.gitconfig`.
-+The `git maintenance` process then determines which maintenance tasks
-+are configured to run on each repository with each `<frequency>` using
-+the `maintenance.<task>.schedule` config options. These values are loaded
-+from the global or repository config values.
++loaded from the user-specific global config. The `git maintenance` process
++then determines which maintenance tasks are configured to run on each
++repository with each `<frequency>` using the `maintenance.<task>.schedule`
++config options. These values are loaded from the global or repository
++config values.
+
+If the config values are insufficient to achieve your desired background
+maintenance schedule, then you can create your own schedule. If you run
+`crontab -e`, then an editor will load with your user-specific `cron`
+schedule. In that editor, you can add your own schedule lines. You could
+start by adapting the default schedule listed earlier, or you could read
-+https://man7.org/linux/man-pages/man5/crontab.5.html[the `crontab` documentation]
-+for advanced scheduling techniques. Please do use the full path and
-+`--exec-path` techniques from the default schedule to ensure you are
-+executing the correct binaries in your schedule.
++the crontab(5) documentation for advanced scheduling techniques. Please
++do use the full path and `--exec-path` techniques from the default
++schedule to ensure you are executing the correct binaries in your
++schedule.
+
GIT
3: 0fafd75d10 ! 3: 1629bcfcf8 maintenance: use launchctl on macOS
@@ Commit message
of macOS 10.11, which was released in September 2015. Before that
release the 'launchctl load' subcommand was recommended. The best
source of information on this transition I have seen is available
- at [2].
+ at [2]. The current design does not preclude a future version that
+ detects the available fatures of 'launchctl' to use the older
+ commands. However, it is best to rely on the newest version since
+ Apple might completely remove the deprecated version on short
+ notice.
[2] https://babodee.wordpress.com/2016/04/09/launchctl-2-0-syntax/
@@ Commit message
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
## Documentation/git-maintenance.txt ##
-@@ Documentation/git-maintenance.txt: for advanced scheduling techniques. Please do use the full path and
- executing the correct binaries in your schedule.
+@@ Documentation/git-maintenance.txt: schedule to ensure you are executing the correct binaries in your
+ schedule.
+BACKGROUND MAINTENANCE ON MACOS SYSTEMS
+---------------------------------------
+
+While macOS technically supports `cron`, using `crontab -e` requires
-+elevated privileges and the executed process do not have a full user
++elevated privileges and the executed process does not have a full user
+context. Without a full user context, Git and its credential helpers
+cannot access stored credentials, so some maintenance tasks are not
+functional.
+
+Instead, `git maintenance start` interacts with the `launchctl` tool,
-+which is the recommended way to
-+https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/ScheduledJobs.html[schedule timed jobs in macOS].
-+
-+Scheduling maintenance through `git maintenance (start|stop)` requires
-+some `launchctl` features available only in macOS 10.11 or later.
++which is the recommended way to schedule timed jobs in macOS. Scheduling
++maintenance through `git maintenance (start|stop)` requires some
++`launchctl` features available only in macOS 10.11 or later.
+
+Your user-specific scheduled tasks are stored as XML-formatted `.plist`
+files in `~/Library/LaunchAgents/`. You can see the currently-registered
+tasks using the following command:
+
+-----------------------------------------------------------------------
-+$ ls ~/Library/LaunchAgents/ | grep org.git-scm.git
++$ ls ~/Library/LaunchAgents/org.git-scm.git*
+org.git-scm.git.daily.plist
+org.git-scm.git.hourly.plist
+org.git-scm.git.weekly.plist
@@ Documentation/git-maintenance.txt: for advanced scheduling techniques. Please do
+and delete the `.plist` files.
+
+To create more advanced customizations to your background tasks, see
-+https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html#//apple_ref/doc/uid/TP40001762-104142[the `launchctl` documentation]
-+for more information.
++launchctl.plist(5) for more information.
+
+
GIT
@@ builtin/gc.c: static int maintenance_unregister(void)
+ return strbuf_detach(&output, NULL);
+}
+
-+static int bootout(const char *filename)
++static int boot_plist(int enable, const char *filename)
+{
+ int result;
-+ struct strvec args = STRVEC_INIT;
++ struct child_process child = CHILD_PROCESS_INIT;
+ char *uid = get_uid();
+ const char *launchctl = getenv("GIT_TEST_CRONTAB");
+ if (!launchctl)
+ launchctl = "/bin/launchctl";
+
-+ strvec_split(&args, launchctl);
-+ strvec_push(&args, "bootout");
-+ strvec_pushf(&args, "gui/%s", uid);
-+ strvec_push(&args, filename);
++ strvec_split(&child.args, launchctl);
+
-+ result = run_command_v_opt(args.v, 0);
++ if (enable)
++ strvec_push(&child.args, "bootstrap");
++ else
++ strvec_push(&child.args, "bootout");
++ strvec_pushf(&child.args, "gui/%s", uid);
++ strvec_push(&child.args, filename);
+
-+ strvec_clear(&args);
-+ free(uid);
-+ return result;
-+}
++ child.no_stderr = 1;
++ child.no_stdout = 1;
+
-+static int bootstrap(const char *filename)
-+{
-+ int result;
-+ struct strvec args = STRVEC_INIT;
-+ char *uid = get_uid();
-+ const char *launchctl = getenv("GIT_TEST_CRONTAB");
-+ if (!launchctl)
-+ launchctl = "/bin/launchctl";
++ if (start_command(&child))
++ die(_("failed to start launchctl"));
+
-+ strvec_split(&args, launchctl);
-+ strvec_push(&args, "bootstrap");
-+ strvec_pushf(&args, "gui/%s", uid);
-+ strvec_push(&args, filename);
++ result = finish_command(&child);
+
-+ result = run_command_v_opt(args.v, 0);
-+
-+ strvec_clear(&args);
+ free(uid);
+ return result;
+}
@@ builtin/gc.c: static int maintenance_unregister(void)
+ const char *frequency = get_frequency(schedule);
+ char *name = get_service_name(frequency);
+ char *filename = get_service_filename(name);
-+ int result = bootout(filename);
++ int result = boot_plist(0, filename);
++ unlink(filename);
+ free(filename);
+ free(name);
+ return result;
@@ builtin/gc.c: static int maintenance_unregister(void)
+
+ if (safe_create_leading_directories(filename))
+ die(_("failed to create directories for '%s'"), filename);
-+ plist = fopen(filename, "w");
-+
-+ if (!plist)
-+ die(_("failed to open '%s'"), filename);
++ plist = xfopen(filename, "w");
+
+ preamble = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
@@ builtin/gc.c: static int maintenance_unregister(void)
+ fprintf(plist, "</array>\n</dict>\n</plist>\n");
+
+ /* bootout might fail if not already running, so ignore */
-+ bootout(filename);
-+ if (bootstrap(filename))
++ boot_plist(0, filename);
++ if (boot_plist(1, filename))
+ die(_("failed to bootstrap service %s"), filename);
+
+ fclose(plist);
@@ t/t7900-maintenance.sh: test_expect_success 'stop from existing schedule' '
'
+test_expect_success MACOS_MAINTENANCE 'start and stop macOS maintenance' '
-+ echo "#!/bin/sh\necho \$@ >>args" >print-args &&
-+ chmod a+x print-args &&
++ write_script print-args "#!/bin/sh\necho \$* >>args" &&
+
+ rm -f args &&
+ GIT_TEST_CRONTAB="./print-args" git maintenance start &&
@@ t/t7900-maintenance.sh: test_expect_success 'stop from existing schedule' '
+ for frequency in hourly daily weekly
+ do
+ PLIST="$HOME/Library/LaunchAgents/org.git-scm.git.$frequency.plist" &&
-+ xmllint "$PLIST" >/dev/null &&
++ xmllint --noout "$PLIST" &&
+ grep schedule=$frequency "$PLIST" &&
+ echo "bootout gui/$UID $PLIST" >>expect &&
+ echo "bootstrap gui/$UID $PLIST" >>expect || return 1
@@ t/t7900-maintenance.sh: test_expect_success 'stop from existing schedule' '
+ test_cmp expect args &&
+
+ rm -f args &&
-+ GIT_TEST_CRONTAB="./print-args" git maintenance stop &&
++ GIT_TEST_CRONTAB="./print-args" git maintenance stop &&
+
+ # stop does not unregister the repo
+ git config --get --global maintenance.repo "$(pwd)" &&
+
-+ # stop does not remove plist files, but boots them out
-+ rm expect &&
-+ for frequency in hourly daily weekly
-+ do
-+ PLIST="$HOME/Library/LaunchAgents/org.git-scm.git.$frequency.plist" &&
-+ grep schedule=$frequency "$PLIST" &&
-+ echo "bootout gui/$UID $PLIST" >>expect || return 1
-+ done &&
-+ test_cmp expect args
++ printf "bootout gui/$UID $HOME/Library/LaunchAgents/org.git-scm.git.%s.plist\n" \
++ hourly daily weekly >expect &&
++ test_cmp expect args &&
++ ls "$HOME/Library/LaunchAgents" >actual &&
++ test_line_count = 0 actual
+'
+
test_expect_success 'register preserves existing strategy' '
4: 84eb44de31 ! 4: ed7a61978f maintenance: use Windows scheduled tasks
@@ Commit message
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
## Documentation/git-maintenance.txt ##
-@@ Documentation/git-maintenance.txt: https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSy
- for more information.
+@@ Documentation/git-maintenance.txt: To create more advanced customizations to your background tasks, see
+ launchctl.plist(5) for more information.
+BACKGROUND MAINTENANCE ON WINDOWS SYSTEMS
@@ builtin/gc.c: static int platform_update_schedule(int run_maintenance, int fd)
+static int schedule_task(const char *exec_path, enum schedule_priority schedule)
+{
+ int result;
-+ struct strvec args = STRVEC_INIT;
++ struct child_process child = CHILD_PROCESS_INIT;
+ const char *xml, *schtasks;
-+ char *xmlpath;
++ char *xmlpath, *tempDir;
+ FILE *xmlfp;
+ const char *frequency = get_frequency(schedule);
+ char *name = get_task_name(frequency);
+
-+ xmlpath = xstrfmt("%s/schedule-%s.xml",
-+ the_repository->objects->odb->path,
-+ frequency);
-+ xmlfp = fopen(xmlpath, "w");
-+ if (!xmlfp)
-+ die(_("failed to open '%s'"), xmlpath);
++ tempDir = xstrfmt("%s/temp", the_repository->objects->odb->path);
++ xmlpath = xstrfmt("%s/schedule-%s.xml", tempDir, frequency);
++ safe_create_leading_directories(xmlpath);
++ xmlfp = xfopen(xmlpath, "w");
+
+ xml = "<?xml version=\"1.0\" encoding=\"UTF-16\"?>\n"
+ "<Task version=\"1.4\" xmlns=\"http://schemas.microsoft.com/windows/2004/02/mit/task\">\n"
@@ builtin/gc.c: static int platform_update_schedule(int run_maintenance, int fd)
+ schtasks = getenv("GIT_TEST_CRONTAB");
+ if (!schtasks)
+ schtasks = "schtasks";
-+ strvec_split(&args, schtasks);
-+ strvec_pushl(&args, "/create", "/tn", name, "/f", "/xml", xmlpath, NULL);
++ strvec_split(&child.args, schtasks);
++ strvec_pushl(&child.args, "/create", "/tn", name, "/f", "/xml", xmlpath, NULL);
+
-+ result = run_command_v_opt(args.v, 0);
++ child.no_stdout = 1;
++ child.no_stderr = 1;
++
++ if (start_command(&child))
++ die(_("failed to start schtasks"));
++ result = finish_command(&child);
+
-+ strvec_clear(&args);
+ unlink(xmlpath);
++ rmdir(tempDir);
+ free(xmlpath);
+ free(name);
+ return result;
@@ t/t7900-maintenance.sh: test_expect_success !MACOS_MAINTENANCE 'stop from existi
GIT_TEST_CRONTAB="test-tool crontab cron.txt" git maintenance start &&
grep "Important information!" cron.txt
@@ t/t7900-maintenance.sh: test_expect_success MACOS_MAINTENANCE 'start and stop macOS maintenance' '
- test_cmp expect args
+ test_line_count = 0 actual
'
+test_expect_success MINGW 'start and stop Windows maintenance' '
@@ t/t7900-maintenance.sh: test_expect_success MACOS_MAINTENANCE 'start and stop ma
+ # start registers the repo
+ git config --get --global maintenance.repo "$(pwd)" &&
+
-+ for frequency in hourly daily weekly
-+ do
-+ printf "/create /tn Git Maintenance (%s) /f /xml .git/objects/schedule-%s.xml\n" \
-+ $frequency $frequency
-+ done >expect &&
++ printf "/create /tn Git Maintenance (%s) /f /xml .git/objects/temp/schedule-%s.xml\n" \
++ hourly hourly daily daily weekly weekly >expect &&
+ test_cmp expect args &&
+
+ rm -f args &&
--
gitgitgadget
next prev parent reply other threads:[~2020-11-13 14:00 UTC|newest]
Thread overview: 83+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-03 14:03 [PATCH 0/3] Maintenance IV: Platform-specific background maintenance Derrick Stolee via GitGitGadget
2020-11-03 14:03 ` [PATCH 1/3] maintenance: extract platform-specific scheduling Derrick Stolee via GitGitGadget
2020-11-03 14:03 ` [PATCH 2/3] maintenance: use launchctl on macOS Derrick Stolee via GitGitGadget
2020-11-03 18:45 ` Eric Sunshine
2020-11-03 21:21 ` Derrick Stolee
2020-11-03 22:27 ` Eric Sunshine
2020-11-04 13:33 ` Derrick Stolee
2020-11-04 14:17 ` Derrick Stolee
2020-11-03 14:03 ` [PATCH 3/3] maintenance: use Windows scheduled tasks Derrick Stolee via GitGitGadget
2020-11-03 19:06 ` Eric Sunshine
2020-11-03 21:23 ` Derrick Stolee
2020-11-03 20:18 ` [PATCH 0/3] Maintenance IV: Platform-specific background maintenance Junio C Hamano
2020-11-03 20:21 ` Junio C Hamano
2020-11-03 21:09 ` Derrick Stolee
2020-11-03 22:30 ` Junio C Hamano
2020-11-04 13:02 ` Derrick Stolee
2020-11-04 17:00 ` Junio C Hamano
2020-11-04 18:43 ` Derrick Stolee
2020-11-04 20:06 ` [PATCH v2 0/4] " Derrick Stolee via GitGitGadget
2020-11-04 20:06 ` [PATCH v2 1/4] maintenance: extract platform-specific scheduling Derrick Stolee via GitGitGadget
2020-11-04 20:06 ` [PATCH v2 2/4] maintenance: include 'cron' details in docs Derrick Stolee via GitGitGadget
2020-11-11 7:10 ` Eric Sunshine
2020-11-04 20:06 ` [PATCH v2 3/4] maintenance: use launchctl on macOS Derrick Stolee via GitGitGadget
2020-11-11 8:12 ` Eric Sunshine
2020-11-12 13:42 ` Derrick Stolee
2020-11-12 16:43 ` Eric Sunshine
2020-11-04 20:06 ` [PATCH v2 4/4] maintenance: use Windows scheduled tasks Derrick Stolee via GitGitGadget
2020-11-11 8:59 ` Eric Sunshine
2020-11-12 13:56 ` Derrick Stolee
2020-11-13 14:00 ` Derrick Stolee via GitGitGadget [this message]
2020-11-13 14:00 ` [PATCH v3 1/4] maintenance: extract platform-specific scheduling Derrick Stolee via GitGitGadget
2020-11-13 14:00 ` [PATCH v3 2/4] maintenance: include 'cron' details in docs Derrick Stolee via GitGitGadget
2020-11-13 14:00 ` [PATCH v3 3/4] maintenance: use launchctl on macOS Derrick Stolee via GitGitGadget
2020-11-13 20:19 ` Eric Sunshine
2020-11-13 20:42 ` Derrick Stolee
2020-11-13 20:53 ` Eric Sunshine
2020-11-13 20:56 ` Eric Sunshine
2020-11-13 14:00 ` [PATCH v3 4/4] maintenance: use Windows scheduled tasks Derrick Stolee via GitGitGadget
2020-11-13 20:44 ` Eric Sunshine
2020-11-13 21:32 ` Derrick Stolee
2020-11-13 21:40 ` Eric Sunshine
2020-11-16 13:13 ` Derrick Stolee
2020-11-13 20:47 ` [PATCH v3 0/4] Maintenance IV: Platform-specific background maintenance Eric Sunshine
2020-11-14 9:23 ` Eric Sunshine
2020-11-16 13:17 ` Derrick Stolee
2020-11-17 21:13 ` [PATCH v4 " Derrick Stolee via GitGitGadget
2020-11-17 21:13 ` [PATCH v4 1/4] maintenance: extract platform-specific scheduling Derrick Stolee via GitGitGadget
2020-11-17 21:13 ` [PATCH v4 2/4] maintenance: include 'cron' details in docs Derrick Stolee via GitGitGadget
2020-11-18 0:34 ` Eric Sunshine
2020-11-18 18:30 ` Derrick Stolee
2020-11-17 21:13 ` [PATCH v4 3/4] maintenance: use launchctl on macOS Derrick Stolee via GitGitGadget
2020-11-18 6:45 ` Eric Sunshine
2020-11-18 18:22 ` Derrick Stolee
2020-11-17 21:13 ` [PATCH v4 4/4] maintenance: use Windows scheduled tasks Derrick Stolee via GitGitGadget
2020-11-18 7:15 ` Eric Sunshine
2020-11-18 18:30 ` Derrick Stolee
2020-11-18 20:54 ` Eric Sunshine
2020-11-18 21:16 ` Derrick Stolee
2020-11-17 23:36 ` [PATCH v4 0/4] Maintenance IV: Platform-specific background maintenance Eric Sunshine
2020-11-24 2:20 ` Derrick Stolee
2020-11-24 2:59 ` Eric Sunshine
2020-11-17 23:54 ` Eric Sunshine
2020-11-24 4:16 ` [PATCH v5 " Derrick Stolee via GitGitGadget
2020-11-24 4:16 ` [PATCH v5 1/4] maintenance: extract platform-specific scheduling Derrick Stolee via GitGitGadget
2020-11-24 4:16 ` [PATCH v5 2/4] maintenance: include 'cron' details in docs Derrick Stolee via GitGitGadget
2020-11-24 4:16 ` [PATCH v5 3/4] maintenance: use launchctl on macOS Derrick Stolee via GitGitGadget
2020-11-24 4:16 ` [PATCH v5 4/4] maintenance: use Windows scheduled tasks Derrick Stolee via GitGitGadget
2020-11-27 9:08 ` Eric Sunshine
2020-12-09 19:28 ` [PATCH v6 0/4] Maintenance IV: Platform-specific background maintenance Derrick Stolee via GitGitGadget
2020-12-09 19:28 ` [PATCH v6 1/4] maintenance: extract platform-specific scheduling Derrick Stolee via GitGitGadget
2020-12-09 19:29 ` [PATCH v6 2/4] maintenance: include 'cron' details in docs Derrick Stolee via GitGitGadget
2020-12-09 19:29 ` [PATCH v6 3/4] maintenance: use launchctl on macOS Derrick Stolee via GitGitGadget
2020-12-09 19:29 ` [PATCH v6 4/4] maintenance: use Windows scheduled tasks Derrick Stolee via GitGitGadget
2020-12-10 0:32 ` [PATCH v6 0/4] Maintenance IV: Platform-specific background maintenance Junio C Hamano
2020-12-10 0:49 ` Eric Sunshine
2020-12-10 1:04 ` Junio C Hamano
2021-01-05 12:17 ` Derrick Stolee
2021-01-05 13:08 ` [PATCH v7 " Derrick Stolee via GitGitGadget
2021-01-05 13:08 ` [PATCH v7 1/4] maintenance: extract platform-specific scheduling Derrick Stolee via GitGitGadget
2021-01-05 13:08 ` [PATCH v7 2/4] maintenance: include 'cron' details in docs Derrick Stolee via GitGitGadget
2021-01-05 13:08 ` [PATCH v7 3/4] maintenance: use launchctl on macOS Derrick Stolee via GitGitGadget
2021-01-10 6:34 ` Eric Sunshine
2021-01-05 13:08 ` [PATCH v7 4/4] maintenance: use Windows scheduled tasks Derrick Stolee via GitGitGadget
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pull.776.v3.git.1605276024.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=derrickstolee@github.com \
--cc=git@vger.kernel.org \
--cc=stolee@gmail.com \
--cc=sunshine@sunshineco.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).