All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] builtin/gc: Ignore random minute field when registering macOS services
@ 2024-12-28  3:13 Byoungchan Lee
  2024-12-28 17:09 ` Junio C Hamano
  0 siblings, 1 reply; 3+ messages in thread
From: Byoungchan Lee @ 2024-12-28  3:13 UTC (permalink / raw)
  To: git

In macOS, `git-maintenance` registers several launchctl services
to periodically run Git maintenance tasks by creating plist files
in `~/Library/LaunchAgents/`.
To avoid re-registering services unnecessarily, we check if a service
is already registered by verifying the existence and contents
of the corresponding plist file.

However, these plist files include a random value in the minute field
to distribute maintenance tasks over time. Because this value changes
with each registration attempt, a direct comparison of the entire file
(via `strbuf_cmp()`) often fails, causing services to be erroneously
re-registered. As a result, users may see multiple services registered
and receive repeated “Background Items Added” notifications.

To resolve this, introduce `launchctl_plist_cmp_ignore_minute()`,
which compares the content of the plist file while ignoring
the random minute field. This ensures that services are not
needlessly re-registered when the only difference in the plist file
is the randomized minute value.

Signed-off-by: Byoungchan Lee <byoungchan.lee@gmx.com>
---
 builtin/gc.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 47 insertions(+), 4 deletions(-)

diff --git a/builtin/gc.c b/builtin/gc.c
index a9b1c36de2..6405f4d332 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -1951,6 +1951,51 @@ static char *launchctl_get_uid(void)
  return xstrfmt("gui/%d", getuid());
 }

+/*
+ * Compare two buffers that represent launchctl property lists, but ignore
+ * lines that contain <key>Minute</key><integer>...</integer> because the
+ * minute values are not significant for comparison.
+ */
+static int launchctl_plist_cmp_ignore_minute(const struct strbuf *a,
+          const struct strbuf *b)
+{
+ char *buf_a = xstrndup(a->buf, a->len);
+ char *buf_b = xstrndup(b->buf, b->len);
+ char *line_a = buf_a;
+ char *line_b = buf_b;
+ int result = 0;
+
+ while (line_a && line_b) {
+  char *next_line_a = strchr(line_a, '\n');
+  char *next_line_b = strchr(line_b, '\n');
+
+  if (next_line_a)
+   *next_line_a = '\0';
+  if (next_line_b)
+   *next_line_b = '\0';
+
+  if (strstr(line_a, "<key>Minute</key><integer>") &&
+      strstr(line_a, "</integer>") &&
+      strstr(line_b, "<key>Minute</key><integer>") &&
+      strstr(line_b, "</integer>")) {
+   line_a = next_line_a ? next_line_a + 1 : NULL;
+   line_b = next_line_b ? next_line_b + 1 : NULL;
+   continue;
+  }
+
+  result = strcmp(line_a, line_b);
+  if (result)
+   break;
+
+  line_a = next_line_a ? next_line_a + 1 : NULL;
+  line_b = next_line_b ? next_line_b + 1 : NULL;
+ }
+
+ free(buf_a);
+ free(buf_b);
+ return result;
+}
+
 static int launchctl_boot_plist(int enable, const char *filename)
 {
  char *cmd;
@@ -2022,7 +2067,6 @@ static int launchctl_schedule_plist(const char
*exec_path, enum schedule_priorit
  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;
  char *cmd;
  int minute = get_random_minute();

@@ -2100,9 +2144,8 @@ static int launchctl_schedule_plist(const char
*exec_path, enum schedule_priorit
   * 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) &&
+ if (strbuf_read_file(&plist2, filename, plist.len) >= 0 &&
+     !launchctl_plist_cmp_ignore_minute(&plist, &plist2) &&
      launchctl_list_contains_plist(name, cmd))
   rollback_lock_file(&lk);
  else {
-- 
2.47.1

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

end of thread, other threads:[~2024-12-28 18:58 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-28  3:13 [PATCH] builtin/gc: Ignore random minute field when registering macOS services Byoungchan Lee
2024-12-28 17:09 ` Junio C Hamano
2024-12-28 18:57   ` Byoungchan Lee

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.