Re: notmuch-emacs should correctly handle signature status on reply
[notmuch-archives.git] / a7 / 33d4eac154ac3ee69aaaad2d6b387c632b9448
1 Return-Path: <amthrax@awakening.csail.mit.edu>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5         by olra.theworths.org (Postfix) with ESMTP id E5B50431FD0\r
6         for <notmuch@notmuchmail.org>; Wed,  9 Nov 2011 05:42:21 -0800 (PST)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: -0.7\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
12         tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
13 Received: from olra.theworths.org ([127.0.0.1])\r
14         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
15         with ESMTP id 8p5g4EQY-KfC for <notmuch@notmuchmail.org>;\r
16         Wed,  9 Nov 2011 05:42:18 -0800 (PST)\r
17 Received: from dmz-mailsec-scanner-2.mit.edu (DMZ-MAILSEC-SCANNER-2.MIT.EDU\r
18         [18.9.25.13])\r
19         by olra.theworths.org (Postfix) with ESMTP id 0173E431FB6\r
20         for <notmuch@notmuchmail.org>; Wed,  9 Nov 2011 05:42:17 -0800 (PST)\r
21 X-AuditID: 1209190d-b7f726d0000008d1-ba-4eba833978e0\r
22 Received: from mailhub-auth-2.mit.edu ( [18.7.62.36])\r
23         by dmz-mailsec-scanner-2.mit.edu (Symantec Messaging Gateway) with SMTP\r
24         id 4B.35.02257.9338ABE4; Wed,  9 Nov 2011 08:42:17 -0500 (EST)\r
25 Received: from outgoing.mit.edu (OUTGOING-AUTH.MIT.EDU [18.7.22.103])\r
26         by mailhub-auth-2.mit.edu (8.13.8/8.9.2) with ESMTP id pA9DgGlS016121; \r
27         Wed, 9 Nov 2011 08:42:16 -0500\r
28 Received: from awakening.csail.mit.edu (awakening.csail.mit.edu [18.26.4.91])\r
29         (authenticated bits=0)\r
30         (User authenticated as amdragon@ATHENA.MIT.EDU)\r
31         by outgoing.mit.edu (8.13.6/8.12.4) with ESMTP id pA9DgFsq019353\r
32         (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT);\r
33         Wed, 9 Nov 2011 08:42:16 -0500 (EST)\r
34 Received: from amthrax by awakening.csail.mit.edu with local (Exim 4.77)\r
35         (envelope-from <amthrax@awakening.csail.mit.edu>)\r
36         id 1RO8SO-0007Qk-Fi; Wed, 09 Nov 2011 08:44:48 -0500\r
37 From: Austin Clements <amdragon@MIT.EDU>\r
38 To: notmuch@notmuchmail.org\r
39 Subject: [PATCH v2] tag: Automatically limit to messages whose tags will\r
40         actually change.\r
41 Date: Wed,  9 Nov 2011 08:44:35 -0500\r
42 Message-Id: <1320846275-28520-1-git-send-email-amdragon@mit.edu>\r
43 X-Mailer: git-send-email 1.7.7.1\r
44 In-Reply-To: <1320724523-23568-1-git-send-email-amdragon@mit.edu>\r
45 References: <1320724523-23568-1-git-send-email-amdragon@mit.edu>\r
46 X-Brightmail-Tracker:\r
47  H4sIAAAAAAAAA+NgFtrFIsWRmVeSWpSXmKPExsUixG6nomvZvMvPoPmJpsX1mzOZHRg9nq26\r
48         xRzAGMVlk5Kak1mWWqRvl8CV8eeVcMEq1YrNHy8yNjAeluli5OSQEDCRWNIylwnCFpO4cG89\r
49         WxcjF4eQwD5Gia/9k5lBEkIC6xklDl0JhkicYJKYNq2dCcLZzChxeUk7I0gVm4CGxLb9y8Fs\r
50         EQFpiZ13Z7N2MXJwMAuoSfzpUgExhQUiJX7+4gKpYBFQlTjxbDojSJhXwEHi2UpZEFNCQEFi\r
51         2Y5qkApOAUeJU3PmsUJc4CBx48hT1gmM/AsYGVYxyqbkVunmJmbmFKcm6xYnJ+blpRbpGunl\r
52         ZpbopaaUbmIEBQunJO8OxncHlQ4xCnAwKvHwXira6SfEmlhWXJl7iFGSg0lJlFevYZefEF9S\r
53         fkplRmJxRnxRaU5q8SFGCQ5mJRFe/WqgHG9KYmVValE+TEqag0VJnLdwh4OfkEB6Yklqdmpq\r
54         QWoRTFaGg0NJgndSE1CjYFFqempFWmZOCUKaiYMTZDgP0PAekBre4oLE3OLMdIj8KUZdjtN/\r
55         Lp1iFGLJy89LlRLnnQNSJABSlFGaBzcHFuWvGMWB3hLm7Qap4gEmCLhJr4CWMAEtUTUEW1KS\r
56         iJCSamDcsKfgYrOz3aYpLjJC4m7svE7r45s7FmaoWlRmCy5y+c0Z6betwvLthC0GzQwiRudU\r
57         PXTnN5RM6pA/y2ms/q58c9Vp4RA5tt7HR4Je28l5v3Zf4PFjrvOKOxuNM08uKRA6vsW8bc/m\r
58         Rm/xq9GZjj8WnldYONnxdA5P7+k3FyaeYLKLVFgjn6HEUpyRaKjFXFScCACT70dfzQIAAA==\r
59 X-BeenThere: notmuch@notmuchmail.org\r
60 X-Mailman-Version: 2.1.13\r
61 Precedence: list\r
62 List-Id: "Use and development of the notmuch mail system."\r
63         <notmuch.notmuchmail.org>\r
64 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
65         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
66 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
67 List-Post: <mailto:notmuch@notmuchmail.org>\r
68 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
69 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
70         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
71 X-List-Received-Date: Wed, 09 Nov 2011 13:42:22 -0000\r
72 \r
73 This optimizes the user's tagging query to exclude messages that won't\r
74 be affected by the tagging operation, saving computation and IO for\r
75 redundant tagging operations.\r
76 \r
77 For example,\r
78   notmuch tag +notmuch to:notmuch@notmuchmail.org\r
79 will now use the query\r
80   ( to:notmuch@notmuchmail.org ) and (not tag:"notmuch")\r
81 \r
82 In the past, we've often suggested that people do this exact\r
83 transformation by hand for slow tagging operations.  This makes that\r
84 unnecessary.\r
85 ---\r
86 This version addresses Jani's comments.\r
87 \r
88  NEWS          |    9 ++++++\r
89  notmuch-tag.c |   85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
90  2 files changed, 94 insertions(+), 0 deletions(-)\r
91 \r
92 diff --git a/NEWS b/NEWS\r
93 index e00452a..9ca5e0c 100644\r
94 --- a/NEWS\r
95 +++ b/NEWS\r
96 @@ -16,6 +16,15 @@ Add search terms to  "notmuch dump"\r
97    search/show/tag. The output file argument of dump is deprecated in\r
98    favour of using stdout.\r
99  \r
100 +Optimizations\r
101 +-------------\r
102 +\r
103 +Automatic tag query optimization\r
104 +\r
105 +  "notmuch tag" now automatically optimizes the user's query to\r
106 +  exclude messages whose tags won't change.  In the past, we've\r
107 +  suggested that people do this by hand; this is no longer necessary.\r
108 +\r
109  Notmuch 0.9 (2011-10-01)\r
110  ========================\r
111  \r
112 diff --git a/notmuch-tag.c b/notmuch-tag.c\r
113 index dded39e..537d5a4 100644\r
114 --- a/notmuch-tag.c\r
115 +++ b/notmuch-tag.c\r
116 @@ -30,6 +30,81 @@ handle_sigint (unused (int sig))\r
117      interrupted = 1;\r
118  }\r
119  \r
120 +static char *\r
121 +_escape_tag (char *buf, const char *tag)\r
122 +{\r
123 +    const char *in = tag;\r
124 +    char *out = buf;\r
125 +    /* Boolean terms surrounded by double quotes can contain any\r
126 +     * character.  Double quotes are quoted by doubling them. */\r
127 +    *out++ = '"';\r
128 +    while (*in) {\r
129 +       if (*in == '"')\r
130 +           *out++ = '"';\r
131 +       *out++ = *in++;\r
132 +    }\r
133 +    *out++ = '"';\r
134 +    *out = 0;\r
135 +    return buf;\r
136 +}\r
137 +\r
138 +static char *\r
139 +_optimize_tag_query (void *ctx, const char *orig_query_string, char *argv[],\r
140 +                    int *add_tags, int add_tags_count,\r
141 +                    int *remove_tags, int remove_tags_count)\r
142 +{\r
143 +    /* This is subtler than it looks.  Xapian ignores the '-' operator\r
144 +     * at the beginning both queries and parenthesized groups and,\r
145 +     * furthermore, the presence of a '-' operator at the beginning of\r
146 +     * a group can inhibit parsing of the previous operator.  Hence,\r
147 +     * the user-provided query MUST appear first, but it is safe to\r
148 +     * parenthesize and the exclusion part of the query must not use\r
149 +     * the '-' operator (though the NOT operator is fine). */\r
150 +\r
151 +    char *escaped, *query_string;\r
152 +    const char *join = "";\r
153 +    int i;\r
154 +    unsigned int max_tag_len = 0;\r
155 +\r
156 +    /* Allocate a buffer for escaping tags.  This is large enough to\r
157 +     * hold a fully escaped tag with every character doubled plus\r
158 +     * enclosing quotes and a NUL. */\r
159 +    for (i = 0; i < add_tags_count; i++)\r
160 +       if (strlen (argv[add_tags[i]] + 1) > max_tag_len)\r
161 +           max_tag_len = strlen (argv[add_tags[i]] + 1);\r
162 +    for (i = 0; i < remove_tags_count; i++)\r
163 +       if (strlen (argv[remove_tags[i]] + 1) > max_tag_len)\r
164 +           max_tag_len = strlen (argv[remove_tags[i]] + 1);\r
165 +    escaped = talloc_array(ctx, char, max_tag_len * 2 + 3);\r
166 +    if (!escaped)\r
167 +       return NULL;\r
168 +\r
169 +    /* Build the new query string */\r
170 +    if (strcmp (orig_query_string, "*") == 0)\r
171 +       query_string = talloc_strdup (ctx, "(");\r
172 +    else\r
173 +       query_string = talloc_asprintf (ctx, "( %s ) and (", orig_query_string);\r
174 +\r
175 +    for (i = 0; i < add_tags_count && query_string; i++) {\r
176 +       query_string = talloc_asprintf_append_buffer (\r
177 +           query_string, "%snot tag:%s", join,\r
178 +           _escape_tag (escaped, argv[add_tags[i]] + 1));\r
179 +       join = " or ";\r
180 +    }\r
181 +    for (i = 0; i < remove_tags_count && query_string; i++) {\r
182 +       query_string = talloc_asprintf_append_buffer (\r
183 +           query_string, "%stag:%s", join,\r
184 +           _escape_tag (escaped, argv[remove_tags[i]] + 1));\r
185 +       join = " or ";\r
186 +    }\r
187 +\r
188 +    if (query_string)\r
189 +       query_string = talloc_strdup_append_buffer (query_string, ")");\r
190 +\r
191 +    talloc_free (escaped);\r
192 +    return query_string;\r
193 +}\r
194 +\r
195  int\r
196  notmuch_tag_command (void *ctx, unused (int argc), unused (char *argv[]))\r
197  {\r
198 @@ -93,6 +168,16 @@ notmuch_tag_command (void *ctx, unused (int argc), unused (char *argv[]))\r
199         return 1;\r
200      }\r
201  \r
202 +    /* Optimize the query so it excludes messages that already have\r
203 +     * the specified set of tags. */\r
204 +    query_string = _optimize_tag_query (ctx, query_string, argv,\r
205 +                                       add_tags, add_tags_count,\r
206 +                                       remove_tags, remove_tags_count);\r
207 +    if (query_string == NULL) {\r
208 +       fprintf (stderr, "Out of memory.\n");\r
209 +       return 1;\r
210 +    }\r
211 +\r
212      config = notmuch_config_open (ctx, NULL, NULL);\r
213      if (config == NULL)\r
214         return 1;\r
215 -- \r
216 1.7.7.1\r
217 \r