Re: [PATCH] cli: Hooks for tag-command
authorJani Nikula <jani@nikula.org>
Wed, 18 Jul 2012 11:52:34 +0000 (14:52 +0300)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:48:22 +0000 (09:48 -0800)
16/e0a54b620b7466a30fe896aa5c4b7f0d54928d [new file with mode: 0644]

diff --git a/16/e0a54b620b7466a30fe896aa5c4b7f0d54928d b/16/e0a54b620b7466a30fe896aa5c4b7f0d54928d
new file mode 100644 (file)
index 0000000..ab5bcf4
--- /dev/null
@@ -0,0 +1,599 @@
+Return-Path: <jani@nikula.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 39488431FB6\r
+       for <notmuch@notmuchmail.org>; Wed, 18 Jul 2012 04:52:37 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.699\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.699 tagged_above=-999 required=5\r
+       tests=[HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\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 6BMZQPrWO5QB for <notmuch@notmuchmail.org>;\r
+       Wed, 18 Jul 2012 04:52:35 -0700 (PDT)\r
+Received: from mail-ob0-f181.google.com (mail-ob0-f181.google.com\r
+       [209.85.214.181]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
+       (No client certificate requested)\r
+       by olra.theworths.org (Postfix) with ESMTPS id 88BD7431FAF\r
+       for <notmuch@notmuchmail.org>; Wed, 18 Jul 2012 04:52:35 -0700 (PDT)\r
+Received: by obbup19 with SMTP id up19so2227710obb.26\r
+       for <notmuch@notmuchmail.org>; Wed, 18 Jul 2012 04:52:34 -0700 (PDT)\r
+X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r
+       d=google.com; s=20120113;\r
+       h=mime-version:in-reply-to:references:date:message-id:subject:from:to\r
+       :cc:content-type:x-gm-message-state;\r
+       bh=szFe+tbP4vhSsiVQcwK2pyRelN6tNIiQe+eJbuEH9AQ=;\r
+       b=LKQYgyw8RquqVlBa/xN9l4M5WPfmvjsfb4y3TgEqHP+CgVvZlGgopYXfRkDrOxODuY\r
+       ojaLUXEs5MpnaFqr1Z7vvVbSHDLM3vv41yObGl0oJropH8PxXvDUZ2VtajLOEuJb15hv\r
+       4i2Ob4Kn1/bLfJObtuKe3HBxEVxeNPczZ03pg8TEAowi2PHEZZQ4aG3ZjZyLm2sppwyz\r
+       oUR9K7if9g9KbgWzhciK+fzhUJsnV0KWZweRlm8uJAwiyO50ZpWLD27x43UyEZhFyug+\r
+       iwb+KvBkbRyMXMUrYWvsgK2FQ767FBPp3Kffz9iQQqvtJnhvZtlkJBMKG5hZFRppNmHg\r
+       hiug==\r
+MIME-Version: 1.0\r
+Received: by 10.60.3.194 with SMTP id e2mr928976oee.1.1342612354849; Wed, 18\r
+       Jul 2012 04:52:34 -0700 (PDT)\r
+Received: by 10.76.10.102 with HTTP; Wed, 18 Jul 2012 04:52:34 -0700 (PDT)\r
+Received: by 10.76.10.102 with HTTP; Wed, 18 Jul 2012 04:52:34 -0700 (PDT)\r
+In-Reply-To: <1342503373-16979-1-git-send-email-dominik@with-h.at>\r
+References: <1342503373-16979-1-git-send-email-dominik@with-h.at>\r
+Date: Wed, 18 Jul 2012 14:52:34 +0300\r
+Message-ID:\r
+ <CAB+hUn_XHQQ9MDaVXvOMzfM8SdKCWUgnjNQvxJaQWWyc3H621Q@mail.gmail.com>\r
+Subject: Re: [PATCH] cli: Hooks for tag-command\r
+From: Jani Nikula <jani@nikula.org>\r
+To: Dominik Peteler <dominik@with-h.at>\r
+Content-Type: multipart/alternative; boundary=e89a8fb202a07b599a04c5194c52\r
+X-Gm-Message-State:\r
+ ALoCoQnFyFI4a9F6koReLgdbcLuZMr7tmka2Y3JAIg9ess0UPa+mDB5WHWjsTmkrT+43jQKkOm0p\r
+Cc: notmuch@notmuchmail.org\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\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: Wed, 18 Jul 2012 11:52:37 -0000\r
+\r
+--e89a8fb202a07b599a04c5194c52\r
+Content-Type: text/plain; charset=UTF-8\r
+\r
+On Jul 18, 2012 12:25 AM, "Dominik Peteler" <dominik@with-h.at> wrote:\r
+>\r
+> hello,\r
+>\r
+> I attached some modifications which I made to notmuch. Comes with man\r
+pages and test.\r
+>\r
+\r
+Hi Dominik, please find a couple of comments below. I'm on the road,\r
+replying on a phone, so this is not very thorough...\r
+\r
+BR,\r
+Jani.\r
+\r
+> regards\r
+>\r
+> dominik\r
+>\r
+>\r
+>\r
+> There are two hooks:\r
+>  * pre-tag: Run before tagging\r
+>  * post-tag: Run after\r
+>\r
+> This allows users to react on changes of tags. For example,\r
+> you might want to move a message to a special Maildir\r
+> depending on its notmuch tags.\r
+> ---\r
+>  man/man1/notmuch-tag.1   | 17 +++++++++++++++++\r
+>  man/man5/notmuch-hooks.5 | 23 +++++++++++++++++++++++\r
+>  notmuch-tag.c            | 25 +++++++++++++++++++++----\r
+>  test/hooks               | 36 ++++++++++++++++++++++++++++++++++++\r
+>  4 files changed, 97 insertions(+), 4 deletions(-)\r
+>\r
+> diff --git a/man/man1/notmuch-tag.1 b/man/man1/notmuch-tag.1\r
+> index d810e1b..8d8b7b2 100644\r
+> --- a/man/man1/notmuch-tag.1\r
+> +++ b/man/man1/notmuch-tag.1\r
+> @@ -4,6 +4,7 @@ notmuch-tag \- add/remove tags for all messages matching\r
+the search terms\r
+>\r
+>  .SH SYNOPSIS\r
+>  .B notmuch tag\r
+> +.RB "[" --no-hooks "]"\r
+>  .RI  "+<" tag> "|\-<" tag "> [...] [\-\-] <" search-term ">..."\r
+>\r
+>  .SH DESCRIPTION\r
+> @@ -29,6 +30,22 @@ updates the maildir flags according to tag changes if\r
+the\r
+>  configuration option is enabled. See \fBnotmuch-config\fR(1) for\r
+>  details.\r
+>\r
+> +The\r
+> +.B tag\r
+> +command supports hooks. See  \fBnotmuch-hooks(5)\fR\r
+> +for more details on hooks.\r
+> +\r
+> +Supported options for\r
+> +.B tag\r
+> +include\r
+> +.RS 4\r
+> +.TP 4\r
+> +.BR \-\-no\-hooks\r
+> +\r
+> +Prevents hooks from being run.\r
+> +.RE\r
+> +.RE\r
+> +\r
+>  .SH SEE ALSO\r
+>\r
+>  \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1),\r
+> diff --git a/man/man5/notmuch-hooks.5 b/man/man5/notmuch-hooks.5\r
+> index b914a29..7399627 100644\r
+> --- a/man/man5/notmuch-hooks.5\r
+> +++ b/man/man5/notmuch-hooks.5\r
+> @@ -38,6 +38,29 @@ the scan or import.\r
+>  Typically this hook is used to perform additional query\-based tagging\r
+on the\r
+>  imported messages.\r
+>  .RE\r
+> +.RS 4\r
+> +.TP 4\r
+> +.B pre\-tag\r
+> +This hook is invoked by the\r
+> +.B tag\r
+> +command before tagging messages. If this\r
+> +hook exits with a non-zero status, notmuch will abort further processing\r
+of the\r
+> +.B tag\r
+> +command.\r
+> +\r
+> +Typically this hook is used for syncing the Maildir with notmuch tags.\r
+\r
+Maildir syncing usually refers to the maildir flag and notmuch tag syncing\r
+in the notmuch context. The above is bound to be confusing.\r
+\r
+> +.RE\r
+> +.RS 4\r
+> +.TP 4\r
+> +.B post\-tag\r
+> +This hook is invoked by the\r
+> +.B tag\r
+> +command after messages have been tagged. The hook will not be run if\r
+there have been any errors during\r
+> +the tagging.\r
+> +\r
+> +Typically this hook is used for syncing the Maildir with notmuch tags.\r
+\r
+Ditto.\r
+\r
+> +.RE\r
+> +\r
+>\r
+>  .SH SEE ALSO\r
+>\r
+> diff --git a/notmuch-tag.c b/notmuch-tag.c\r
+> index 7d18639..e98d3a0 100644\r
+> --- a/notmuch-tag.c\r
+> +++ b/notmuch-tag.c\r
+> @@ -174,9 +174,11 @@ notmuch_tag_command (void *ctx, int argc, char\r
+*argv[])\r
+>      int tag_ops_count = 0;\r
+>      char *query_string;\r
+>      notmuch_config_t *config;\r
+> +    const char *db_path;\r
+>      notmuch_database_t *notmuch;\r
+>      struct sigaction action;\r
+>      notmuch_bool_t synchronize_flags;\r
+> +    notmuch_bool_t run_hooks = TRUE;\r
+>      int i;\r
+>      int ret;\r
+>\r
+> @@ -198,11 +200,12 @@ notmuch_tag_command (void *ctx, int argc, char\r
+*argv[])\r
+>      }\r
+>\r
+>      for (i = 0; i < argc; i++) {\r
+> -       if (strcmp (argv[i], "--") == 0) {\r
+> +       if (strcmp (argv[i], "--no-hooks") == 0) {\r
+> +               run_hooks = FALSE;\r
+\r
+This is subtler than it looks. This would allow --no-hooks to be placed in\r
+the middle of tag operations. Same for any future arguments. And it would\r
+prevent removal of a hypothetical -no-hooks tag... I think we'll want to\r
+support specifying "--" twice to separate arguments from tag ops, and ops\r
+from query. And it must be forbidden to mix them.\r
+\r
+> +       } else if (strcmp (argv[i], "--") == 0) {\r
+>             i++;\r
+>             break;\r
+> -       }\r
+> -       if (argv[i][0] == '+' || argv[i][0] == '-') {\r
+> +       } else if (argv[i][0] == '+' || argv[i][0] == '-') {\r
+>             tag_ops[tag_ops_count].tag = argv[i] + 1;\r
+>             tag_ops[tag_ops_count].remove = (argv[i][0] == '-');\r
+>             tag_ops_count++;\r
+> @@ -229,7 +232,15 @@ notmuch_tag_command (void *ctx, int argc, char\r
+*argv[])\r
+>      if (config == NULL)\r
+>         return 1;\r
+>\r
+> -    if (notmuch_database_open (notmuch_config_get_database_path (config),\r
+> +    db_path = notmuch_config_get_database_path (config);\r
+> +\r
+> +    if (run_hooks) {\r
+> +       ret = notmuch_run_hook (db_path, "pre-tag");\r
+> +       if (ret)\r
+> +           return ret;\r
+> +    }\r
+> +\r
+> +    if (notmuch_database_open (db_path,\r
+>                                NOTMUCH_DATABASE_MODE_READ_WRITE,\r
+&notmuch))\r
+>         return 1;\r
+>\r
+> @@ -239,5 +250,11 @@ notmuch_tag_command (void *ctx, int argc, char\r
+*argv[])\r
+>\r
+>      notmuch_database_destroy (notmuch);\r
+>\r
+> +    if (run_hooks) {\r
+\r
+Can't check further context atm, are you sure not to run post-tag if\r
+there's an error?\r
+\r
+> +       ret = notmuch_run_hook (db_path, "post-tag");\r
+> +       if (ret)\r
+> +           return ret;\r
+> +    }\r
+> +\r
+>      return ret;\r
+>  }\r
+> diff --git a/test/hooks b/test/hooks\r
+> index 77e8569..ae857cc 100755\r
+> --- a/test/hooks\r
+> +++ b/test/hooks\r
+> @@ -31,6 +31,7 @@ rm_hooks () {\r
+>  # add a message to generate mail dir and database\r
+>  add_message\r
+>\r
+> +# {pre,post}-new hooks\r
+>  test_begin_subtest "pre-new is run"\r
+>  rm_hooks\r
+>  generate_message\r
+> @@ -101,4 +102,39 @@ EOF\r
+>  chmod +x "${HOOK_DIR}/pre-new"\r
+>  test_expect_code 1 "hook execution failure" "notmuch new"\r
+>\r
+> +\r
+> +\r
+> +# {pre,post}-tag hooks\r
+> +test_begin_subtest "pre-tag is run"\r
+> +rm_hooks\r
+> +generate_message\r
+> +create_echo_hook "pre-tag" expected output\r
+> +notmuch tag +foo -- '*' > /dev/null\r
+> +test_expect_equal_file expected output\r
+> +\r
+> +test_begin_subtest "post-tag is run"\r
+> +rm_hooks\r
+> +generate_message\r
+> +create_echo_hook "post-tag" expected output\r
+> +notmuch tag +foo -- '*'  > /dev/null\r
+> +test_expect_equal_file expected output\r
+> +\r
+> +test_begin_subtest "pre-tag is run before post-new"\r
+> +rm_hooks\r
+> +generate_message\r
+> +create_echo_hook "pre-tag" pre-tag.expected pre-tag.output\r
+> +create_echo_hook "post-tag" post-tag.expected post-tag.output\r
+> +notmuch tag +foo -- '*'  > /dev/null\r
+> +test_expect_equal_file post-tag.expected post-tag.output\r
+> +\r
+> +test_begin_subtest "pre-tag non-zero exit status (hook status)"\r
+> +rm_hooks\r
+> +generate_message\r
+> +create_failing_hook "pre-tag"\r
+> +output=`notmuch tag +foo -- '*'  2>&1`\r
+> +test_expect_equal "$output" "Error: pre-tag hook failed with status 13"\r
+> +\r
+> +# depends on the previous subtest leaving broken hook behind\r
+> +test_expect_code 1 "pre-tag non-zero exit status (notmuch status)"\r
+"notmuch tag +foo -- '*'"\r
+> +\r
+>  test_done\r
+> --\r
+> 1.7.11.2\r
+>\r
+> _______________________________________________\r
+> notmuch mailing list\r
+> notmuch@notmuchmail.org\r
+> http://notmuchmail.org/mailman/listinfo/notmuch\r
+\r
+--e89a8fb202a07b599a04c5194c52\r
+Content-Type: text/html; charset=UTF-8\r
+Content-Transfer-Encoding: quoted-printable\r
+\r
+<p><br>\r
+On Jul 18, 2012 12:25 AM, &quot;Dominik Peteler&quot; &lt;<a href=3D"mailto=\r
+:dominik@with-h.at">dominik@with-h.at</a>&gt; wrote:<br>\r
+&gt;<br>\r
+&gt; hello,<br>\r
+&gt;<br>\r
+&gt; I attached some modifications which I made to notmuch. Comes with man =\r
+pages and test.<br>\r
+&gt;</p>\r
+<p>Hi Dominik, please find a couple of comments below. I&#39;m on the road,=\r
+ replying on a phone, so this is not very thorough...</p>\r
+<p>BR,<br>\r
+Jani.<br></p>\r
+<p>&gt; regards<br>\r
+&gt;<br>\r
+&gt; dominik<br>\r
+&gt;<br>\r
+&gt;<br>\r
+&gt;<br>\r
+&gt; There are two hooks:<br>\r
+&gt; =C2=A0* pre-tag: Run before tagging<br>\r
+&gt; =C2=A0* post-tag: Run after<br>\r
+&gt;<br>\r
+&gt; This allows users to react on changes of tags. For example,<br>\r
+&gt; you might want to move a message to a special Maildir<br>\r
+&gt; depending on its notmuch tags.<br>\r
+&gt; ---<br>\r
+&gt; =C2=A0man/man1/notmuch-tag.1 =C2=A0 | 17 +++++++++++++++++<br>\r
+&gt; =C2=A0man/man5/notmuch-hooks.5 | 23 +++++++++++++++++++++++<br>\r
+&gt; =C2=A0notmuch-tag.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| 25 ++++=\r
++++++++++++++++++----<br>\r
+&gt; =C2=A0test/hooks =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 | 36=\r
+ ++++++++++++++++++++++++++++++++++++<br>\r
+&gt; =C2=A04 files changed, 97 insertions(+), 4 deletions(-)<br>\r
+&gt;<br>\r
+&gt; diff --git a/man/man1/notmuch-tag.1 b/man/man1/notmuch-tag.1<br>\r
+&gt; index d810e1b..8d8b7b2 100644<br>\r
+&gt; --- a/man/man1/notmuch-tag.1<br>\r
+&gt; +++ b/man/man1/notmuch-tag.1<br>\r
+&gt; @@ -4,6 +4,7 @@ notmuch-tag \- add/remove tags for all messages matchi=\r
+ng the search terms<br>\r
+&gt;<br>\r
+&gt; =C2=A0.SH SYNOPSIS<br>\r
+&gt; =C2=A0.B notmuch tag<br>\r
+&gt; +.RB &quot;[&quot; --no-hooks &quot;]&quot;<br>\r
+&gt; =C2=A0.RI =C2=A0&quot;+&lt;&quot; tag&gt; &quot;|\-&lt;&quot; tag &quo=\r
+t;&gt; [...] [\-\-] &lt;&quot; search-term &quot;&gt;...&quot;<br>\r
+&gt;<br>\r
+&gt; =C2=A0.SH DESCRIPTION<br>\r
+&gt; @@ -29,6 +30,22 @@ updates the maildir flags according to tag changes =\r
+if the<br>\r
+&gt; =C2=A0configuration option is enabled. See \fBnotmuch-config\fR(1) for=\r
+<br>\r
+&gt; =C2=A0details.<br>\r
+&gt;<br>\r
+&gt; +The<br>\r
+&gt; +.B tag<br>\r
+&gt; +command supports hooks. See =C2=A0\fBnotmuch-hooks(5)\fR<br>\r
+&gt; +for more details on hooks.<br>\r
+&gt; +<br>\r
+&gt; +Supported options for<br>\r
+&gt; +.B tag<br>\r
+&gt; +include<br>\r
+&gt; +.RS 4<br>\r
+&gt; +.TP 4<br>\r
+&gt; +.BR \-\-no\-hooks<br>\r
+&gt; +<br>\r
+&gt; +Prevents hooks from being run.<br>\r
+&gt; +.RE<br>\r
+&gt; +.RE<br>\r
+&gt; +<br>\r
+&gt; =C2=A0.SH SEE ALSO<br>\r
+&gt;<br>\r
+&gt; =C2=A0\fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1=\r
+),<br>\r
+&gt; diff --git a/man/man5/notmuch-hooks.5 b/man/man5/notmuch-hooks.5<br>\r
+&gt; index b914a29..7399627 100644<br>\r
+&gt; --- a/man/man5/notmuch-hooks.5<br>\r
+&gt; +++ b/man/man5/notmuch-hooks.5<br>\r
+&gt; @@ -38,6 +38,29 @@ the scan or import.<br>\r
+&gt; =C2=A0Typically this hook is used to perform additional query\-based t=\r
+agging on the<br>\r
+&gt; =C2=A0imported messages.<br>\r
+&gt; =C2=A0.RE<br>\r
+&gt; +.RS 4<br>\r
+&gt; +.TP 4<br>\r
+&gt; +.B pre\-tag<br>\r
+&gt; +This hook is invoked by the<br>\r
+&gt; +.B tag<br>\r
+&gt; +command before tagging messages. If this<br>\r
+&gt; +hook exits with a non-zero status, notmuch will abort further process=\r
+ing of the<br>\r
+&gt; +.B tag<br>\r
+&gt; +command.<br>\r
+&gt; +<br>\r
+&gt; +Typically this hook is used for syncing the Maildir with notmuch tags=\r
+.</p>\r
+<p>Maildir syncing usually refers to the maildir flag and notmuch tag synci=\r
+ng in the notmuch context. The above is bound to be confusing.</p>\r
+<p>&gt; +.RE<br>\r
+&gt; +.RS 4<br>\r
+&gt; +.TP 4<br>\r
+&gt; +.B post\-tag<br>\r
+&gt; +This hook is invoked by the<br>\r
+&gt; +.B tag<br>\r
+&gt; +command after messages have been tagged. The hook will not be run if =\r
+there have been any errors during<br>\r
+&gt; +the tagging.<br>\r
+&gt; +<br>\r
+&gt; +Typically this hook is used for syncing the Maildir with notmuch tags=\r
+.</p>\r
+<p>Ditto.</p>\r
+<p>&gt; +.RE<br>\r
+&gt; +<br>\r
+&gt;<br>\r
+&gt; =C2=A0.SH SEE ALSO<br>\r
+&gt;<br>\r
+&gt; diff --git a/notmuch-tag.c b/notmuch-tag.c<br>\r
+&gt; index 7d18639..e98d3a0 100644<br>\r
+&gt; --- a/notmuch-tag.c<br>\r
+&gt; +++ b/notmuch-tag.c<br>\r
+&gt; @@ -174,9 +174,11 @@ notmuch_tag_command (void *ctx, int argc, char *a=\r
+rgv[])<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0int tag_ops_count =3D 0;<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0char *query_string;<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0notmuch_config_t *config;<br>\r
+&gt; + =C2=A0 =C2=A0const char *db_path;<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0notmuch_database_t *notmuch;<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0struct sigaction action;<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0notmuch_bool_t synchronize_flags;<br>\r
+&gt; + =C2=A0 =C2=A0notmuch_bool_t run_hooks =3D TRUE;<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0int i;<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0int ret;<br>\r
+&gt;<br>\r
+&gt; @@ -198,11 +200,12 @@ notmuch_tag_command (void *ctx, int argc, char *=\r
+argv[])<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0}<br>\r
+&gt;<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0for (i =3D 0; i &lt; argc; i++) {<br>\r
+&gt; - =C2=A0 =C2=A0 =C2=A0 if (strcmp (argv[i], &quot;--&quot;) =3D=3D 0) =\r
+{<br>\r
+&gt; + =C2=A0 =C2=A0 =C2=A0 if (strcmp (argv[i], &quot;--no-hooks&quot;) =\r
+=3D=3D 0) {<br>\r
+&gt; + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 run_hooks =3D FALSE=\r
+;</p>\r
+<p>This is subtler than it looks. This would allow --no-hooks to be placed =\r
+in the middle of tag operations. Same for any future arguments. And it woul=\r
+d prevent removal of a hypothetical -no-hooks tag... I think we&#39;ll want=\r
+ to support specifying &quot;--&quot; twice to separate arguments from tag =\r
+ops, and ops from query. And it must be forbidden to mix them.</p>\r
+\r
+<p>&gt; + =C2=A0 =C2=A0 =C2=A0 } else if (strcmp (argv[i], &quot;--&quot;) =\r
+=3D=3D 0) {<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 i++;<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 break;<br>\r
+&gt; - =C2=A0 =C2=A0 =C2=A0 }<br>\r
+&gt; - =C2=A0 =C2=A0 =C2=A0 if (argv[i][0] =3D=3D &#39;+&#39; || argv[i][0]=\r
+ =3D=3D &#39;-&#39;) {<br>\r
+&gt; + =C2=A0 =C2=A0 =C2=A0 } else if (argv[i][0] =3D=3D &#39;+&#39; || arg=\r
+v[i][0] =3D=3D &#39;-&#39;) {<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 tag_ops[tag_ops_count].tag =\r
+=3D argv[i] + 1;<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 tag_ops[tag_ops_count].remov=\r
+e =3D (argv[i][0] =3D=3D &#39;-&#39;);<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 tag_ops_count++;<br>\r
+&gt; @@ -229,7 +232,15 @@ notmuch_tag_command (void *ctx, int argc, char *a=\r
+rgv[])<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0if (config =3D=3D NULL)<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 return 1;<br>\r
+&gt;<br>\r
+&gt; - =C2=A0 =C2=A0if (notmuch_database_open (notmuch_config_get_database_=\r
+path (config),<br>\r
+&gt; + =C2=A0 =C2=A0db_path =3D notmuch_config_get_database_path (config);<=\r
+br>\r
+&gt; +<br>\r
+&gt; + =C2=A0 =C2=A0if (run_hooks) {<br>\r
+&gt; + =C2=A0 =C2=A0 =C2=A0 ret =3D notmuch_run_hook (db_path, &quot;pre-ta=\r
+g&quot;);<br>\r
+&gt; + =C2=A0 =C2=A0 =C2=A0 if (ret)<br>\r
+&gt; + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return ret;<br>\r
+&gt; + =C2=A0 =C2=A0}<br>\r
+&gt; +<br>\r
+&gt; + =C2=A0 =C2=A0if (notmuch_database_open (db_path,<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =\r
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0NOTMUCH_DATABASE_MODE_READ_WRITE, =\r
+&amp;notmuch))<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 return 1;<br>\r
+&gt;<br>\r
+&gt; @@ -239,5 +250,11 @@ notmuch_tag_command (void *ctx, int argc, char *a=\r
+rgv[])<br>\r
+&gt;<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0notmuch_database_destroy (notmuch);<br>\r
+&gt;<br>\r
+&gt; + =C2=A0 =C2=A0if (run_hooks) {</p>\r
+<p>Can&#39;t check further context atm, are you sure not to run post-tag if=\r
+ there&#39;s an error?</p>\r
+<p>&gt; + =C2=A0 =C2=A0 =C2=A0 ret =3D notmuch_run_hook (db_path, &quot;pos=\r
+t-tag&quot;);<br>\r
+&gt; + =C2=A0 =C2=A0 =C2=A0 if (ret)<br>\r
+&gt; + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return ret;<br>\r
+&gt; + =C2=A0 =C2=A0}<br>\r
+&gt; +<br>\r
+&gt; =C2=A0 =C2=A0 =C2=A0return ret;<br>\r
+&gt; =C2=A0}<br>\r
+&gt; diff --git a/test/hooks b/test/hooks<br>\r
+&gt; index 77e8569..ae857cc 100755<br>\r
+&gt; --- a/test/hooks<br>\r
+&gt; +++ b/test/hooks<br>\r
+&gt; @@ -31,6 +31,7 @@ rm_hooks () {<br>\r
+&gt; =C2=A0# add a message to generate mail dir and database<br>\r
+&gt; =C2=A0add_message<br>\r
+&gt;<br>\r
+&gt; +# {pre,post}-new hooks<br>\r
+&gt; =C2=A0test_begin_subtest &quot;pre-new is run&quot;<br>\r
+&gt; =C2=A0rm_hooks<br>\r
+&gt; =C2=A0generate_message<br>\r
+&gt; @@ -101,4 +102,39 @@ EOF<br>\r
+&gt; =C2=A0chmod +x &quot;${HOOK_DIR}/pre-new&quot;<br>\r
+&gt; =C2=A0test_expect_code 1 &quot;hook execution failure&quot; &quot;notm=\r
+uch new&quot;<br>\r
+&gt;<br>\r
+&gt; +<br>\r
+&gt; +<br>\r
+&gt; +# {pre,post}-tag hooks<br>\r
+&gt; +test_begin_subtest &quot;pre-tag is run&quot;<br>\r
+&gt; +rm_hooks<br>\r
+&gt; +generate_message<br>\r
+&gt; +create_echo_hook &quot;pre-tag&quot; expected output<br>\r
+&gt; +notmuch tag +foo -- &#39;*&#39; &gt; /dev/null<br>\r
+&gt; +test_expect_equal_file expected output<br>\r
+&gt; +<br>\r
+&gt; +test_begin_subtest &quot;post-tag is run&quot;<br>\r
+&gt; +rm_hooks<br>\r
+&gt; +generate_message<br>\r
+&gt; +create_echo_hook &quot;post-tag&quot; expected output<br>\r
+&gt; +notmuch tag +foo -- &#39;*&#39; =C2=A0&gt; /dev/null<br>\r
+&gt; +test_expect_equal_file expected output<br>\r
+&gt; +<br>\r
+&gt; +test_begin_subtest &quot;pre-tag is run before post-new&quot;<br>\r
+&gt; +rm_hooks<br>\r
+&gt; +generate_message<br>\r
+&gt; +create_echo_hook &quot;pre-tag&quot; pre-tag.expected pre-tag.output<=\r
+br>\r
+&gt; +create_echo_hook &quot;post-tag&quot; post-tag.expected post-tag.outp=\r
+ut<br>\r
+&gt; +notmuch tag +foo -- &#39;*&#39; =C2=A0&gt; /dev/null<br>\r
+&gt; +test_expect_equal_file post-tag.expected post-tag.output<br>\r
+&gt; +<br>\r
+&gt; +test_begin_subtest &quot;pre-tag non-zero exit status (hook status)&q=\r
+uot;<br>\r
+&gt; +rm_hooks<br>\r
+&gt; +generate_message<br>\r
+&gt; +create_failing_hook &quot;pre-tag&quot;<br>\r
+&gt; +output=3D`notmuch tag +foo -- &#39;*&#39; =C2=A02&gt;&amp;1`<br>\r
+&gt; +test_expect_equal &quot;$output&quot; &quot;Error: pre-tag hook faile=\r
+d with status 13&quot;<br>\r
+&gt; +<br>\r
+&gt; +# depends on the previous subtest leaving broken hook behind<br>\r
+&gt; +test_expect_code 1 &quot;pre-tag non-zero exit status (notmuch status=\r
+)&quot; &quot;notmuch tag +foo -- &#39;*&#39;&quot;<br>\r
+&gt; +<br>\r
+&gt; =C2=A0test_done<br>\r
+&gt; --<br>\r
+&gt; 1.7.11.2<br>\r
+&gt;<br>\r
+&gt; _______________________________________________<br>\r
+&gt; notmuch mailing list<br>\r
+&gt; <a href=3D"mailto:notmuch@notmuchmail.org">notmuch@notmuchmail.org</a>=\r
+<br>\r
+&gt; <a href=3D"http://notmuchmail.org/mailman/listinfo/notmuch">http://not=\r
+muchmail.org/mailman/listinfo/notmuch</a><br>\r
+</p>\r
+\r
+--e89a8fb202a07b599a04c5194c52--\r