Return-Path: X-Original-To: notmuch@notmuchmail.org Delivered-To: notmuch@notmuchmail.org Received: from localhost (localhost [127.0.0.1]) by olra.theworths.org (Postfix) with ESMTP id 7481B431FBF for ; Mon, 30 Jul 2012 05:41:19 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Spam-Flag: NO X-Spam-Score: 0 X-Spam-Level: X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none] autolearn=disabled Received: from olra.theworths.org ([127.0.0.1]) by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Uss7dRFTcjhE for ; Mon, 30 Jul 2012 05:41:17 -0700 (PDT) Received: from www73.your-server.de (www73.your-server.de [213.133.104.73]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by olra.theworths.org (Postfix) with ESMTPS id 126A9431FAE for ; Mon, 30 Jul 2012 05:41:17 -0700 (PDT) Received: from [78.46.5.203] (helo=sslproxy01.your-server.de) by www73.your-server.de with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.74) (envelope-from ) id 1SvpHa-0002ER-O6 for notmuch@notmuchmail.org; Mon, 30 Jul 2012 14:41:10 +0200 Received: from [132.187.246.115] (helo=fuckup.uni-wuerzburg.de) by sslproxy01.your-server.de with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.72) (envelope-from ) id 1SvpHR-0003tl-IF for notmuch@notmuchmail.org; Mon, 30 Jul 2012 14:41:02 +0200 Date: Mon, 30 Jul 2012 14:39:28 +0200 From: Dominik Peteler To: notmuch@notmuchmail.org Subject: Re: [PATCHv2] cli: Hooks for tag-command Message-ID: <20120730123928.GA749@fuckup.uni-wuerzburg.de> References: <1342634970-12991-1-git-send-email-dominik@with-h.at> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="5vNYLRcllDrimb99" Content-Disposition: inline In-Reply-To: <1342634970-12991-1-git-send-email-dominik@with-h.at> X-PGP-Key: http://www.with-h.at/pubkey.asc User-Agent: Mutt/1.5.21 (2011-07-01) X-Authenticated-Sender: dude@with-h.at X-Virus-Scanned: Clear (ClamAV 0.97.3/15190/Mon Jul 30 10:41:49 2012) X-Mailman-Approved-At: Mon, 30 Jul 2012 06:47:37 -0700 X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 30 Jul 2012 12:41:19 -0000 --5vNYLRcllDrimb99 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable hello, I hope I don't bother you but so far I didn't get any reply to my last mail= with the patch for tag-command hooks. Did you accept the patch or not ? If not, please tell my if I can improve i= t. And do you have a opinion about my suggestion to pass the message-ids of re= tagged mails to the hook ? regards dominik On Wed 2012-07-18 20:09, Dominik Peteler wrote: > hello, >=20 > I improved my patch according to Janis mail: > * new cli syntax: notmuch tag [ --no-hooks ] -- [ -- ] > * adjusted man pages and wrote tests >=20 > I had the idea to improve this feature by passing the message-ids or the = filename to the hooks. > What's your opinion about that ? Any suggestions ? >=20 > regards >=20 > dominik >=20 >=20 >=20 > There are two hooks: > * pre-tag: Run before tagging > * post-tag: Run after >=20 > This allows users to react on changes of tags. For example, > you might want to move a message to a special Maildir > depending on its notmuch tags. > --- > man/man1/notmuch-tag.1 | 22 +++++++++++++++++++- > man/man5/notmuch-hooks.5 | 19 ++++++++++++++++++ > notmuch-tag.c | 52 ++++++++++++++++++++++++++++++++++++++++++= +++--- > test/hooks | 36 +++++++++++++++++++++++++++++++++ > test/tagging | 28 ++++++++++++++++++++++++++ > 5 files changed, 153 insertions(+), 4 deletions(-) >=20 > diff --git a/man/man1/notmuch-tag.1 b/man/man1/notmuch-tag.1 > index d810e1b..e00e189 100644 > --- a/man/man1/notmuch-tag.1 > +++ b/man/man1/notmuch-tag.1 > @@ -4,7 +4,11 @@ notmuch-tag \- add/remove tags for all messages matching= the search terms > =20 > .SH SYNOPSIS > .B notmuch tag > -.RI "+<" tag> "|\-<" tag "> [...] [\-\-] <" search-term ">..." > +.RI "+<" tag "> |\-<" tag "> [...] [\-\-] <" search-term ">..." > + > +.B notmuch tag > +.RB "[" --no-hooks "]" > +.RI "\-\- +<" tag "> |\-<" tag "> [...] \-\- <" search-term ">..." > =20 > .SH DESCRIPTION > =20 > @@ -29,6 +33,22 @@ updates the maildir flags according to tag changes if = the > configuration option is enabled. See \fBnotmuch-config\fR(1) for > details. > =20 > +The > +.B tag > +command supports hooks. See \fBnotmuch-hooks(5)\fR > +for more details on hooks. > + > +Supported options for > +.B tag > +include > +.RS 4 > +.TP 4 > +.BR \-\-no\-hooks > + > +Prevents hooks from being run. > +.RE > +.RE > + > .SH SEE ALSO > =20 > \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1), > diff --git a/man/man5/notmuch-hooks.5 b/man/man5/notmuch-hooks.5 > index b914a29..e193ef5 100644 > --- a/man/man5/notmuch-hooks.5 > +++ b/man/man5/notmuch-hooks.5 > @@ -38,6 +38,25 @@ the scan or import. > Typically this hook is used to perform additional query\-based tagging o= n the > imported messages. > .RE > +.RS 4 > +.TP 4 > +.B pre\-tag > +This hook is invoked by the > +.B tag > +command before tagging messages. If this > +hook exits with a non-zero status, notmuch will abort further processing= of the > +.B tag > +command. > +.RE > +.RS 4 > +.TP 4 > +.B post\-tag > +This hook is invoked by the > +.B tag > +command after messages have been tagged. The hook will not be run if the= re have been any errors during > +the tagging. > +.RE > + > =20 > .SH SEE ALSO > =20 > diff --git a/notmuch-tag.c b/notmuch-tag.c > index 7d18639..7572059 100644 > --- a/notmuch-tag.c > +++ b/notmuch-tag.c > @@ -174,9 +174,17 @@ notmuch_tag_command (void *ctx, int argc, char *argv= []) > int tag_ops_count =3D 0; > char *query_string; > notmuch_config_t *config; > + const char *db_path; > notmuch_database_t *notmuch; > struct sigaction action; > notmuch_bool_t synchronize_flags; > + /* Points to the position of the "--" delimiters, e. g. > + * arg_delimiters[0] arg_delimiter= s[1] > + * > + * arg_delimiters[0] may remain -1 if there are no arguments given > + * arg_delimiters[0] may remain -1 if there is no delimiter between = tag ops and search terms */ > + int arg_delimiters[2] =3D {-1, -1}; > + notmuch_bool_t run_hooks =3D TRUE; > int i; > int ret; > =20 > @@ -197,11 +205,37 @@ notmuch_tag_command (void *ctx, int argc, char *arg= v[]) > return 1; > } > =20 > + /* Determine position of delimiters */ > for (i =3D 0; i < argc; i++) { > if (strcmp (argv[i], "--") =3D=3D 0) { > - i++; > - break; > + if (arg_delimiters[1] =3D=3D -1) { > + arg_delimiters[1] =3D i; > + } else if (arg_delimiters[0] =3D=3D -1) { > + arg_delimiters[0] =3D arg_delimiters[1]; > + arg_delimiters[1] =3D i; > + } else { > + fprintf (stderr, "Error: 'notmuch tag' requires delimiter \"--\" at mo= st two times.\n"); > + return 1; > + } > } > + } > + > + /* Process arguments if present */ > + for (i =3D 0; i < arg_delimiters[0]; i++) { > + if (strcmp (argv[i], "--no-hooks") =3D=3D 0) { > + run_hooks =3D FALSE; > + } else { > + fprintf (stderr, "Error: 'notmuch tag' doesn't recognize argument '= %s'.\n", argv[i]); > + return 1; > + } > + } > + > + /* Set arg_delimiters[1] to argc if no delimiters at all are present= */ > + if (arg_delimiters[1] =3D=3D -1) > + arg_delimiters[1] =3D argc; > + > + /* Read tag ops */ > + for (i =3D arg_delimiters[0]+1; i < arg_delimiters[1]; i++) { > if (argv[i][0] =3D=3D '+' || argv[i][0] =3D=3D '-') { > tag_ops[tag_ops_count].tag =3D argv[i] + 1; > tag_ops[tag_ops_count].remove =3D (argv[i][0] =3D=3D '-'); > @@ -229,7 +263,15 @@ notmuch_tag_command (void *ctx, int argc, char *argv= []) > if (config =3D=3D NULL) > return 1; > =20 > - if (notmuch_database_open (notmuch_config_get_database_path (config), > + db_path =3D notmuch_config_get_database_path (config); > + > + if (run_hooks) { > + ret =3D notmuch_run_hook (db_path, "pre-tag"); > + if (ret) > + return ret; > + } > + > + if (notmuch_database_open (db_path, > NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much)) > return 1; > =20 > @@ -239,5 +281,9 @@ notmuch_tag_command (void *ctx, int argc, char *argv[= ]) > =20 > notmuch_database_destroy (notmuch); > =20 > + if (!ret && run_hooks) { > + ret =3D notmuch_run_hook (db_path, "post-tag"); > + } > + > return ret; > } > diff --git a/test/hooks b/test/hooks > index 77e8569..ae857cc 100755 > --- a/test/hooks > +++ b/test/hooks > @@ -31,6 +31,7 @@ rm_hooks () { > # add a message to generate mail dir and database > add_message > =20 > +# {pre,post}-new hooks > test_begin_subtest "pre-new is run" > rm_hooks > generate_message > @@ -101,4 +102,39 @@ EOF > chmod +x "${HOOK_DIR}/pre-new" > test_expect_code 1 "hook execution failure" "notmuch new" > =20 > + > + > +# {pre,post}-tag hooks > +test_begin_subtest "pre-tag is run" > +rm_hooks > +generate_message > +create_echo_hook "pre-tag" expected output > +notmuch tag +foo -- '*' > /dev/null > +test_expect_equal_file expected output > + > +test_begin_subtest "post-tag is run" > +rm_hooks > +generate_message > +create_echo_hook "post-tag" expected output > +notmuch tag +foo -- '*' > /dev/null > +test_expect_equal_file expected output > + > +test_begin_subtest "pre-tag is run before post-new" > +rm_hooks > +generate_message > +create_echo_hook "pre-tag" pre-tag.expected pre-tag.output > +create_echo_hook "post-tag" post-tag.expected post-tag.output > +notmuch tag +foo -- '*' > /dev/null > +test_expect_equal_file post-tag.expected post-tag.output > + > +test_begin_subtest "pre-tag non-zero exit status (hook status)" > +rm_hooks > +generate_message > +create_failing_hook "pre-tag" > +output=3D`notmuch tag +foo -- '*' 2>&1` > +test_expect_equal "$output" "Error: pre-tag hook failed with status 13" > + > +# depends on the previous subtest leaving broken hook behind > +test_expect_code 1 "pre-tag non-zero exit status (notmuch status)" "notm= uch tag +foo -- '*'" > + > test_done > diff --git a/test/tagging b/test/tagging > index e4782ed..5167f4f 100755 > --- a/test/tagging > +++ b/test/tagging > @@ -46,4 +46,32 @@ test_expect_equal "$output" "\ > thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (:\" inbox tag1 u= nread) > thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 tag4 u= nread)" > =20 > +test_begin_subtest "Arguments mixed with tag ops" > +notmuch tag +-no-hooks --no-hooks -- One > +notmuch tag --no-hooks +-no-hooks -tag4 -- Two > +output=3D$(notmuch search \* | notmuch_search_sanitize) > +test_expect_equal "$output" "\ > +thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (:\" inbox tag1 u= nread) > +thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (-no-hooks inbox t= ag1 unread)" > +notmuch tag --no-hooks -- Two > + > +test_begin_subtest "Arguments with correct position" > +notmuch tag --no-hooks -- +tag4 -tag4 -- One > +output=3D$(notmuch search \* | notmuch_search_sanitize) > +test_expect_equal "$output" "\ > +thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (:\" inbox tag1 u= nread) > +thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 unread= )" > + > +test_begin_subtest "Missing arguments" > +notmuch tag -- +tag4 -tag4 -- One > +output=3D$(notmuch search \* | notmuch_search_sanitize) > +test_expect_equal "$output" "\ > +thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (:\" inbox tag1 u= nread) > +thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 unread= )" > + > +test_begin_subtest "Unknown argument" > +output=3D$(notmuch tag --no-blubb -- +tag4 -tag4 -- One 2>&1) > +test_expect_equal "$output" "\ > +Error: 'notmuch tag' doesn't recognize argument '--no-blubb'." > + > test_done > --=20 > 1.7.11.2 >=20 --5vNYLRcllDrimb99 Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAEBAgAGBQJQFoCAAAoJEFxmf0CweVkTFrkQAJtoYSf5F5C4+sRjc4QAqzZN Sa9ZUgDpacVhx5jcPgEwJpyAmTIoBl70jpZtUyz/r2/jb9ofcaRhRWi+SUhZUSDi cA0lSq4W9HoRvz0AiuggdgzE0ydungL+CJsrWwQZrVYnXMcpoVf+NIKCnkGU2dZo I7fGRWeSklfGysKehsKHX3G8UUzvicnr7EBd7gWN5+x9PE6RJZXNR/cx9YiRS03s n1kvfEPyyK3J8l2Gz42Vh16/RmFPAFc07/aIpylOp8l4qBz6WDWQy7gGFDjwFscU P4NlPC0fugCLawnF4z+H/5zffhLN9BL5LvsQ3p9AZ0PLLlmfVuke54y/g07PuIOO a4HyIeyhHsXdJcJYut7xFxzFN8kt89yfXtLVUSRO6OOAOwcGF8UEhdf6UYGKn3wZ zLMkF+vXmkDIKq7RfwvNX++pR/NXU14zDfZ5s1ywuZ0tBmmiqjfVa8hh1zh3HrdB PQGh2AnSFrZRCCcvXsmVVvCsybC6fKrldrNRB/q7lNyn6W8TyeKZObGu0cshHEi0 KKNl5olunoiKUN2cSc8uoa9Kc1BFek91SLz0+gdOlV3FKlEGGBPnmihDanDFZATg 07qw8XvcdK3/pSgNVVGRc6Lcr+xyYLJ1dC0dBB+jDQBlE4dj0guChF93IEa/MXTv Od3M+3RH8oSHRGMUvL1a =eWDC -----END PGP SIGNATURE----- --5vNYLRcllDrimb99--