[notmuch] [PATCH] Add post-add and post-tag hooks
authorTomas Carnecky <tom@dbservice.com>
Tue, 22 Dec 2009 02:56:57 +0000 (03:56 +0100)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:35:55 +0000 (09:35 -0800)
c0/4c739c23a8c125deb17d8c148aa723a4e96ee7 [new file with mode: 0644]

diff --git a/c0/4c739c23a8c125deb17d8c148aa723a4e96ee7 b/c0/4c739c23a8c125deb17d8c148aa723a4e96ee7
new file mode 100644 (file)
index 0000000..fbb4c59
--- /dev/null
@@ -0,0 +1,211 @@
+Return-Path: <tomc@caurea.org>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+       by olra.theworths.org (Postfix) with ESMTP id 8F53C431FBC\r
+       for <notmuch@notmuchmail.org>; Mon, 21 Dec 2009 18:57:06 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+       by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+       with ESMTP id v-NFs4nqX+IY for <notmuch@notmuchmail.org>;\r
+       Mon, 21 Dec 2009 18:57:06 -0800 (PST)\r
+X-Greylist: delayed 135368 seconds by postgrey-1.32 at olra;\r
+       Mon, 21 Dec 2009 18:57:05 PST\r
+Received: from hobbes.caurea.org\r
+       (gw.ptr-62-65-144-46.customer.ch.netstream.com [62.65.144.46])\r
+       by olra.theworths.org (Postfix) with ESMTP id DB350431FAE\r
+       for <notmuch@notmuchmail.org>; Mon, 21 Dec 2009 18:57:05 -0800 (PST)\r
+Received: by hobbes.caurea.org (Postfix, from userid 101)\r
+       id 255592A5F5; Tue, 22 Dec 2009 03:57:03 +0100 (CET)\r
+From: Tomas Carnecky <tom@dbservice.com>\r
+To: notmuch@notmuchmail.org\r
+Date: Tue, 22 Dec 2009 03:56:57 +0100\r
+Message-Id: <1261450617-24616-1-git-send-email-tom@dbservice.com>\r
+X-Mailer: git-send-email 1.6.6.rc3\r
+Subject: [notmuch] [PATCH] Add post-add and post-tag hooks\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.12\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+       <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Tue, 22 Dec 2009 02:57:06 -0000\r
+\r
+The post-add hook is run by 'notmuch new' after each new message is added,\r
+post-tag is run after a tag has been added or removed. The hooks are stored\r
+in the users home directory (~/.notmuch/hooks/).\r
+\r
+Since post-tag is run unconditionally every time a new tag is added or removed,\r
+that means it is also invoked when 'notmuch new' adds the two implicit\r
+tags (inbox, unread). So make sure your scripts don't choke on that and can\r
+be both executed in parallel.\r
+\r
+Signed-off-by: Tomas Carnecky <tom@dbservice.com>\r
+---\r
+ lib/message.cc |   45 ++++++++++++++++++++++++++++++++++++++\r
+ notmuch-new.c  |   66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+ 2 files changed, 111 insertions(+), 0 deletions(-)\r
+\r
+diff --git a/lib/message.cc b/lib/message.cc\r
+index 49519f1..bcd8abb 100644\r
+--- a/lib/message.cc\r
++++ b/lib/message.cc\r
+@@ -664,6 +664,47 @@ _notmuch_message_remove_term (notmuch_message_t *message,\r
+     return NOTMUCH_PRIVATE_STATUS_SUCCESS;\r
+ }\r
\r
++/* Run the post-tag hook */\r
++static void\r
++post_tag_hook (notmuch_message_t *message, const char *tag, int added)\r
++{\r
++    /* Skip tags that notmuch itself assigns to new messages */\r
++    const char *skip[] = {\r
++        "inbox", "unread"\r
++    };\r
++\r
++    for (int i = 0; i < sizeof (skip) / sizeof (skip[0]); ++i) {\r
++        if (strcmp(skip[i], tag) == 0)\r
++            return;\r
++    }\r
++\r
++    char proc[PATH_MAX];\r
++    snprintf (proc, PATH_MAX, "%s/.notmuch/hooks/post-tag", getenv("HOME"));\r
++    if (access (proc, X_OK))\r
++        return;\r
++\r
++    int pid = fork ();\r
++    if (pid == -1)\r
++        return;\r
++\r
++    /* Wait for the hook to finish. This behaviour might be changed in the\r
++     * future, but for now I think it's better to take the safe route. */\r
++    if (pid > 0) {\r
++        waitpid (0, NULL, 0);\r
++        return;\r
++    }\r
++\r
++    const char *filename = notmuch_message_get_filename (message);\r
++    const char *message_id = notmuch_message_get_message_id (message);\r
++\r
++    const char *args[] = {\r
++        proc, message_id, filename, tag, added ? "added" : "removed", NULL\r
++    };\r
++\r
++    execv (proc, (char *const *) &args);\r
++    exit (0);\r
++}\r
++\r
+ notmuch_status_t\r
+ notmuch_message_add_tag (notmuch_message_t *message, const char *tag)\r
+ {\r
+@@ -684,6 +725,8 @@ notmuch_message_add_tag (notmuch_message_t *message, const char *tag)\r
+     if (! message->frozen)\r
+       _notmuch_message_sync (message);\r
\r
++    post_tag_hook (message, tag, 1);\r
++\r
+     return NOTMUCH_STATUS_SUCCESS;\r
+ }\r
\r
+@@ -707,6 +750,8 @@ notmuch_message_remove_tag (notmuch_message_t *message, const char *tag)\r
+     if (! message->frozen)\r
+       _notmuch_message_sync (message);\r
\r
++    post_tag_hook (message, tag, 0);\r
++\r
+     return NOTMUCH_STATUS_SUCCESS;\r
+ }\r
\r
+diff --git a/notmuch-new.c b/notmuch-new.c\r
+index 837ae4f..d984aae 100644\r
+--- a/notmuch-new.c\r
++++ b/notmuch-new.c\r
+@@ -42,6 +42,71 @@ handle_sigint (unused (int sig))\r
+     interrupted = 1;\r
+ }\r
\r
++/* Run the post-add hook. The hook is given the chance to specify additional tags\r
++ * that should be added to the message. The hook writes the tags to its stdout,\r
++ * separated by a newline. The script's stdout is redirected to a pipe so that\r
++ * notmuch can process its output. The tags can be prefixed with '+' or '-' to\r
++ * indicate if the tag should be added or removed. Absence of one of these prefixes\r
++ * means that the tag will be added. */\r
++static void\r
++post_add_hook (notmuch_message_t *message)\r
++{\r
++    char proc[PATH_MAX];\r
++    snprintf (proc, PATH_MAX, "%s/.notmuch/hooks/post-add", getenv ("HOME"));\r
++    if (access (proc, X_OK))\r
++        return;\r
++\r
++    /* The pipe between the hook and the notmuch process. The script writes\r
++     * into fds[0], notmuch reads from fds[1]. */\r
++    int fds[2];\r
++    if (pipe (fds))\r
++      return;\r
++\r
++    int pid = fork ();\r
++    if (pid == -1) {\r
++      close (fds[0]);\r
++      close (fds[1]);\r
++      return;\r
++    } else if (pid > 0) {\r
++      close (fds[0]);\r
++      waitpid (0, NULL, 0);\r
++\r
++      char buffer[256] = { 0, };\r
++      read (fds[1], buffer, sizeof (buffer));\r
++\r
++      char *tag;\r
++      for (tag = buffer; tag && *tag; ) {\r
++          char *end = strchr (tag, '\n');\r
++          if (end)\r
++              *end = 0;\r
++\r
++          if (tag[0] == '+')\r
++              notmuch_message_add_tag (message, tag + 1);\r
++          else if (tag[0] == '-')\r
++              notmuch_message_remove_tag (message, tag + 1);\r
++          else\r
++              notmuch_message_add_tag (message, tag);\r
++\r
++          tag = end ? end + 1 : end;\r
++      }\r
++\r
++      return;\r
++    }\r
++\r
++    /* This is the child process (where the hook runs) */\r
++    close (fds[1]);\r
++    dup2 (fds[0], 1);\r
++\r
++    const char *filename = notmuch_message_get_filename (message);\r
++    const char *message_id = notmuch_message_get_message_id (message);\r
++    const char *args[] = {\r
++      proc, message_id, filename, NULL\r
++    };\r
++\r
++    execv (proc, (char *const *) &args);\r
++    exit (0);\r
++}\r
++\r
+ static void\r
+ tag_inbox_and_unread (notmuch_message_t *message)\r
+ {\r
+@@ -253,6 +318,7 @@ add_files_recursive (notmuch_database_t *notmuch,\r
+                   case NOTMUCH_STATUS_SUCCESS:\r
+                       state->added_messages++;\r
+                       tag_inbox_and_unread (message);\r
++                      post_add_hook (message);\r
+                       break;\r
+                   /* Non-fatal issues (go on to next file) */\r
+                   case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:\r
+-- \r
+1.6.6.rc3\r
+\r