Subject: [PATCH v6 0/4] Maintenance IV: Platform-specific background maintenance

From: "Derrick Stolee via GitGitGadget" <[email-masked]>
Date: Wed, 09 Dec 2020 19:28:58 +0000

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.

Update in V6
============

 * The Windows platform uses the tempfile API a bit better, including using
   the frequency in the filename to make the test simpler.

Thanks, -Stolee

cc: [email-masked] cc: [email-masked] cc: [email-masked]
cc: Đoàn Trần Công Danh [email-masked] cc: Martin Ågren
[email-masked] cc: Eric Sunshine [email-masked] cc: Derrick
Stolee [email-masked]

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                      | 421 ++++++++++++++++++++++++++++--
 t/t7900-maintenance.sh            | 105 +++++++-
 t/test-lib.sh                     |   7 +-
 4 files changed, 615 insertions(+), 34 deletions(-)

base-commit: 0016b618182f642771dc589cf0090289f9fe1b4f
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-776%2Fderrickstolee%2Fmaintenance%2FmacOS-v6
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-776/derrickstolee/maintenance/macOS-v6
Pull-Request: https://github.com/gitgitgadget/git/pull/776

Range-diff vs v5:

 1:  4807342b001 = 1:  4807342b001 maintenance: extract platform-specific scheduling
 2:  7cc70a8fe7b = 2:  7cc70a8fe7b maintenance: include 'cron' details in docs
 3:  cd015a5cbd7 = 3:  cd015a5cbd7 maintenance: use launchctl on macOS
 4:  ac9a28bea39 ! 4:  6ad4a6b98c6 maintenance: use Windows scheduled tasks
     @@ Commit message
          by Git is valid when xmllint exists on the system.
      
          Since we use a temporary file for the XML files sent to 'schtasks', we
     -    must copy the file to a predictable filename. Use the number of lines in
     -    the 'args' file to provide a filename for xmllint. Instead of an exact
     -    match on the 'args' file, we 'grep' for the arguments other than the
     -    filename.
     +    prefix the random characters with the frequency so it is easier to
     +    examine the proper file during tests. Instead of an exact match on the
     +    'args' file, we 'grep' for the arguments other than the filename.
      
          There is a deficiency in the current design. Windows has two kinds of
          applications: GUI applications that start by "winmain()" and console
     @@ builtin/gc.c: static int launchctl_update_schedule(int run_maintenance, int fd,
      +	struct tempfile *tfile;
      +	const char *frequency = get_frequency(schedule);
      +	char *name = schtasks_task_name(frequency);
     ++	struct strbuf tfilename = STRBUF_INIT;
      +
     -+	tfile = xmks_tempfile("schedule_XXXXXX");
     -+	if (!tfile || !fdopen_tempfile(tfile, "w"))
     ++	strbuf_addf(&tfilename, "schedule_%s_XXXXXX", frequency);
     ++	tfile = xmks_tempfile(tfilename.buf);
     ++	strbuf_release(&tfilename);
     ++
     ++	if (!fdopen_tempfile(tfile, "w"))
      +		die(_("failed to create temp xml file"));
      +
      +	xml = "<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n"
     @@ builtin/gc.c: static int launchctl_update_schedule(int run_maintenance, int fd,
      +	      "</Task>\n";
      +	fprintf(tfile->fp, xml, exec_path, exec_path, frequency);
      +	strvec_split(&child.args, cmd);
     -+	strvec_pushl(&child.args, "/create", "/tn", name, "/f", "/xml", tfile->filename.buf, NULL);
     ++	strvec_pushl(&child.args, "/create", "/tn", name, "/f", "/xml",
     ++				  get_tempfile_path(tfile), NULL);
      +	close_tempfile_gently(tfile);
      +
      +	child.no_stdout = 1;
     @@ t/t7900-maintenance.sh: test_expect_success !MINGW 'start and stop macOS mainten
      +		*) shift ;;
      +		esac
      +	done
     -+	lines=$(wc -l args | awk "{print \$1;}")
     -+	test -z "$xmlfile" || cp "$xmlfile" "schedule-$lines.xml"
     ++	test -z "$xmlfile" || cp "$xmlfile" "$xmlfile.xml"
      +	EOF
      +
      +	rm -f args &&
     -+	GIT_TEST_MAINT_SCHEDULER="schtasks:./print-args" git maintenance start &&
     ++	GIT_TEST_MAINT_SCHEDULER="schtasks:./print-args" GIT_TRACE2_PERF=1 git maintenance start &&
      +
      +	# start registers the repo
      +	git config --get --global maintenance.repo "$(pwd)" &&
      +
      +	for frequency in hourly daily weekly
      +	do
     -+		grep "/create /tn Git Maintenance ($frequency) /f /xml" args \
     -+			|| return 1
     -+	done &&
     -+
     -+	for i in 1 2 3
     -+	do
     -+		test_xmllint "schedule-$i.xml" &&
     -+		grep "encoding=.US-ASCII." "schedule-$i.xml" || return 1
     ++		grep "/create /tn Git Maintenance ($frequency) /f /xml" args &&
     ++		file=$(ls schedule_$frequency*.xml) &&
     ++		test_xmllint "$file" &&
     ++		grep "encoding=.US-ASCII." "$file" || return 1
      +	done &&
      +
      +	rm -f args &&

-- 
gitgitgadget