]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'lh/systemd-timers'
authorJunio C Hamano <gitster@pobox.com>
Mon, 20 Sep 2021 22:20:40 +0000 (15:20 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 20 Sep 2021 22:20:40 +0000 (15:20 -0700)
"git maintenance" scheduler learned to use systemd timers as a
possible backend.

* lh/systemd-timers:
  maintenance: add support for systemd timers on Linux
  maintenance: `git maintenance run` learned `--scheduler=<scheduler>`
  cache.h: Introduce a generic "xdg_config_home_for(…)" function

1  2 
builtin/gc.c
cache.h
path.c
t/t7900-maintenance.sh

diff --cc builtin/gc.c
index 43c36024cbeae1bcc0c5d8b70885421e5bc588c8,5d8b8234b45ca91859a1d1cf5577ede17d5ddc66..84d77104c29ec43e725748be630bab78ca3000d7
@@@ -1593,48 -1678,26 +1678,50 @@@ static int launchctl_remove_plist(enum 
        return result;
  }
  
- static int launchctl_remove_plists(const char *cmd)
+ static int launchctl_remove_plists(void)
  {
-       return launchctl_remove_plist(SCHEDULE_HOURLY, cmd) ||
-               launchctl_remove_plist(SCHEDULE_DAILY, cmd) ||
-               launchctl_remove_plist(SCHEDULE_WEEKLY, cmd);
+       return launchctl_remove_plist(SCHEDULE_HOURLY) ||
+              launchctl_remove_plist(SCHEDULE_DAILY) ||
+              launchctl_remove_plist(SCHEDULE_WEEKLY);
  }
  
- static int launchctl_schedule_plist(const char *exec_path, enum schedule_priority schedule, const char *cmd)
 +static int launchctl_list_contains_plist(const char *name, const char *cmd)
 +{
 +      int result;
 +      struct child_process child = CHILD_PROCESS_INIT;
 +      char *uid = launchctl_get_uid();
 +
 +      strvec_split(&child.args, cmd);
 +      strvec_pushl(&child.args, "list", name, NULL);
 +
 +      child.no_stderr = 1;
 +      child.no_stdout = 1;
 +
 +      if (start_command(&child))
 +              die(_("failed to start launchctl"));
 +
 +      result = finish_command(&child);
 +
 +      free(uid);
 +
 +      /* Returns failure if 'name' doesn't exist. */
 +      return !result;
 +}
 +
+ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priority schedule)
  {
 -      FILE *plist;
 -      int i;
 +      int i, fd;
        const char *preamble, *repeat;
        const char *frequency = get_frequency(schedule);
        char *name = launchctl_service_name(frequency);
        char *filename = launchctl_service_filename(name);
 +      struct lock_file lk = LOCK_INIT;
 +      static unsigned long lock_file_timeout_ms = ULONG_MAX;
 +      struct strbuf plist = STRBUF_INIT, plist2 = STRBUF_INIT;
 +      struct stat st;
++      const char *cmd = "launchctl";
  
 -      if (safe_create_leading_directories(filename))
 -              die(_("failed to create directories for '%s'"), filename);
 -      plist = xfopen(filename, "w");
 -
++      get_schedule_cmd(&cmd, NULL);
        preamble = "<?xml version=\"1.0\"?>\n"
                   "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
                   "<plist version=\"1.0\">"
                /* unreachable */
                break;
        }
 -      fprintf(plist, "</array>\n</dict>\n</plist>\n");
 -      fclose(plist);
 +      strbuf_addstr(&plist, "</array>\n</dict>\n</plist>\n");
  
 -      /* bootout might fail if not already running, so ignore */
 -      launchctl_boot_plist(0, filename);
 -      if (launchctl_boot_plist(1, filename))
 -              die(_("failed to bootstrap service %s"), filename);
 +      if (safe_create_leading_directories(filename))
 +              die(_("failed to create directories for '%s'"), filename);
 +
 +      if ((long)lock_file_timeout_ms < 0 &&
 +          git_config_get_ulong("gc.launchctlplistlocktimeoutms",
 +                               &lock_file_timeout_ms))
 +              lock_file_timeout_ms = 150;
 +
 +      fd = hold_lock_file_for_update_timeout(&lk, filename, LOCK_DIE_ON_ERROR,
 +                                             lock_file_timeout_ms);
 +
 +      /*
 +       * Does this file already exist? With the intended contents? Is it
 +       * registered already? Then it does not need to be re-registered.
 +       */
 +      if (!stat(filename, &st) && st.st_size == plist.len &&
 +          strbuf_read_file(&plist2, filename, plist.len) == plist.len &&
 +          !strbuf_cmp(&plist, &plist2) &&
 +          launchctl_list_contains_plist(name, cmd))
 +              rollback_lock_file(&lk);
 +      else {
 +              if (write_in_full(fd, plist.buf, plist.len) < 0 ||
 +                  commit_lock_file(&lk))
 +                      die_errno(_("could not write '%s'"), filename);
 +
 +              /* bootout might fail if not already running, so ignore */
-               launchctl_boot_plist(0, filename, cmd);
-               if (launchctl_boot_plist(1, filename, cmd))
++              launchctl_boot_plist(0, filename);
++              if (launchctl_boot_plist(1, filename))
 +                      die(_("failed to bootstrap service %s"), filename);
 +      }
  
        free(filename);
        free(name);
diff --cc cache.h
Simple merge
diff --cc path.c
Simple merge
index fc16ac22585b90911e9ec6e6a62fdad407a99ba1,b289cae6b9e20be1d6f01218224ccc34791fca1f..36a4218745bda747e5d3f3c8252ea1913130318a
@@@ -582,23 -609,6 +607,23 @@@ test_expect_success 'start and stop mac
        test_line_count = 0 actual
  '
  
-       GIT_TEST_MAINT_SCHEDULER=launchctl:./print-args git maintenance start &&
 +test_expect_success 'use launchctl list to prevent extra work' '
 +      # ensure we are registered
-       GIT_TEST_MAINT_SCHEDULER=launchctl:./print-args git maintenance start &&
++      GIT_TEST_MAINT_SCHEDULER=launchctl:./print-args git maintenance start --scheduler=launchctl &&
 +
 +      # do it again on a fresh args file
 +      rm -f args &&
++      GIT_TEST_MAINT_SCHEDULER=launchctl:./print-args git maintenance start --scheduler=launchctl &&
 +
 +      ls "$HOME/Library/LaunchAgents" >actual &&
 +      cat >expect <<-\EOF &&
 +      list org.git-scm.git.hourly
 +      list org.git-scm.git.daily
 +      list org.git-scm.git.weekly
 +      EOF
 +      test_cmp expect args
 +'
 +
  test_expect_success 'start and stop Windows maintenance' '
        write_script print-args <<-\EOF &&
        echo $* >>args