1 Return-Path: <peterz@infradead.org>
\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 3C0FD431E82
\r
6 for <notmuch@notmuchmail.org>; Wed, 13 Nov 2013 12:09:02 -0800 (PST)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
11 X-Spam-Status: No, score=-2.3 tagged_above=-999 required=5
\r
12 tests=[RCVD_IN_DNSWL_MED=-2.3] 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 svZTLYEtPkGu for <notmuch@notmuchmail.org>;
\r
16 Wed, 13 Nov 2013 12:08:56 -0800 (PST)
\r
17 Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134])
\r
18 (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
\r
19 (No client certificate requested)
\r
20 by olra.theworths.org (Postfix) with ESMTPS id 71331431FD0
\r
21 for <notmuch@notmuchmail.org>; Wed, 13 Nov 2013 12:08:56 -0800 (PST)
\r
22 Received: from dhcp-077-248-225-117.chello.nl ([77.248.225.117] helo=laptop)
\r
23 by merlin.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux))
\r
24 id 1VggkA-0004CF-5F; Wed, 13 Nov 2013 20:08:54 +0000
\r
25 Received: by laptop (Postfix, from userid 1000)
\r
26 id 5CD05103BA2D3; Wed, 13 Nov 2013 21:08:52 +0100 (CET)
\r
27 Date: Wed, 13 Nov 2013 21:08:52 +0100
\r
28 From: Peter Zijlstra <peterz@infradead.org>
\r
29 To: Austin Clements <aclements@csail.mit.edu>
\r
30 Subject: Re: [PATCH] notmuch: Add "maildir:" search option
\r
31 Message-ID: <20131113200852.GG16796@laptop.programming.kicks-ass.net>
\r
32 References: <20131112155637.GA16796@laptop.programming.kicks-ass.net>
\r
33 <87mwl94dte.fsf@awakening.csail.mit.edu>
\r
34 <87k3gd4dfb.fsf@awakening.csail.mit.edu>
\r
36 Content-Type: text/plain; charset=us-ascii
\r
37 Content-Disposition: inline
\r
38 In-Reply-To: <87k3gd4dfb.fsf@awakening.csail.mit.edu>
\r
39 User-Agent: Mutt/1.5.21 (2012-12-30)
\r
40 Cc: notmuch@notmuchmail.org
\r
41 X-BeenThere: notmuch@notmuchmail.org
\r
42 X-Mailman-Version: 2.1.13
\r
44 List-Id: "Use and development of the notmuch mail system."
\r
45 <notmuch.notmuchmail.org>
\r
46 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
47 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
48 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
49 List-Post: <mailto:notmuch@notmuchmail.org>
\r
50 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
51 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
52 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
53 X-List-Received-Date: Wed, 13 Nov 2013 20:09:02 -0000
\r
55 On Tue, Nov 12, 2013 at 02:39:52PM -0500, Austin Clements wrote:
\r
56 > On Tue, 12 Nov 2013, Austin Clements <aclements@csail.mit.edu> wrote:
\r
57 > > I think this is a great idea. Personally I think this is how folder:
\r
58 > > should work. I find the semantics of folder: to be useless except where
\r
59 > > they happen to coincide with the boolean semantics used here.
\r
60 > > Unfortunately, changing folder: would require versioning the database,
\r
61 > > which we have only primordial support for right now.
\r
63 > > Various comments below, though nothing major. Of course, we'd also need
\r
64 > > some tests and man page updates for this.
\r
66 > Sorry, one important thing I missed: this doesn't correctly handle when
\r
67 > file names are removed from a message
\r
68 > (_notmuch_message_remove_filename). Probably the simplest thing would
\r
69 > be to follow the template for how folder: works by first removing *all*
\r
70 > folder terms and then adding back the still-valid ones. (Unfortunately,
\r
71 > just removing the term for the removed filename's directory won't work
\r
72 > because the message could have other filenames in the same directory,
\r
73 > though maybe you could just scan for that possibility?)
\r
75 Oh, right you are. A little something like the below? Its compile tested
\r
76 only and I've not yet had time to look at how the test infrastructure
\r
81 lib/database.cc | 3 +-
\r
82 lib/message.cc | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
\r
83 2 files changed, 104 insertions(+), 10 deletions(-)
\r
85 diff --git a/lib/database.cc b/lib/database.cc
\r
86 index a021bf17253c..e43e17dffcd0 100644
\r
87 --- a/lib/database.cc
\r
88 +++ b/lib/database.cc
\r
89 @@ -208,7 +208,8 @@ static prefix_t BOOLEAN_PREFIX_EXTERNAL[] = {
\r
95 + { "maildir", "XMAILDIR:" },
\r
98 static prefix_t PROBABILISTIC_PREFIX[]= {
\r
99 diff --git a/lib/message.cc b/lib/message.cc
\r
100 index 1b4637950f8e..73d3bb65ab67 100644
\r
101 --- a/lib/message.cc
\r
102 +++ b/lib/message.cc
\r
104 #include "database-private.h"
\r
106 #include <stdint.h>
\r
107 +#include <string.h>
\r
109 #include <gmime/gmime.h>
\r
111 @@ -473,6 +474,71 @@ notmuch_message_get_replies (notmuch_message_t *message)
\r
112 return _notmuch_messages_create (message->replies);
\r
115 +/* Construct a proper 'maildir' from 'directory'
\r
117 + * Takes the relative directory component inside the maildir pathname and
\r
118 + * construct a maildir path from it.
\r
120 + * For filesystem layout Maildir we use the regular filesystem path except the
\r
121 + * trailing "cur"/"new" component.
\r
123 + * For Maildir++ we strip the leading '.' and replace subsequent '.'s with '/'s
\r
126 +_notmuch_message_maildir (void *ctx, const char *directory)
\r
131 + maildir = talloc_strdup (ctx, directory);
\r
132 + i = strlen (maildir);
\r
134 + /* Strip trailing '/' */
\r
135 + while (i && maildir[i - 1] == '/') {
\r
136 + maildir[i - 1] = '\0';
\r
140 + /* Strip leading '/' */
\r
141 + while (maildir[0] == '/') {
\r
147 + /* Consume trailing maildir directory entries */
\r
148 + if (STRNCMP_LITERAL (maildir, "cur") == 0 ||
\r
149 + STRNCMP_LITERAL (maildir, "new") == 0)
\r
151 + maildir[i - 3] = '\0';
\r
155 + /* Strip trailing '/' */
\r
156 + while (i && maildir[i - 1] == '/') {
\r
157 + maildir[i-1] = '\0';
\r
163 + if (maildir[0] == '.') {
\r
166 + /* Replace all remaining '.' with '/' */
\r
167 + for (i = 0; maildir[i]; i++) {
\r
168 + if (maildir[i] == '.')
\r
169 + maildir[i] = '/';
\r
173 + /* If there's no string left, we're the "INBOX" */
\r
174 + if (maildir[0] == '\0')
\r
175 + maildir = talloc_strdup (ctx, "INBOX");
\r
180 /* Add an additional 'filename' for 'message'.
\r
182 * This change will not be reflected in the database until the next
\r
183 @@ -485,6 +551,7 @@ _notmuch_message_add_filename (notmuch_message_t *message,
\r
184 notmuch_status_t status;
\r
185 void *local = talloc_new (message);
\r
189 if (filename == NULL)
\r
190 INTERNAL_ERROR ("Message filename cannot be NULL.");
\r
191 @@ -507,6 +574,10 @@ _notmuch_message_add_filename (notmuch_message_t *message,
\r
192 /* New terms allow user to search with folder: specification. */
\r
193 _notmuch_message_gen_terms (message, "folder", directory);
\r
195 + /* New terms allow user to serarch with maildir: specification. */
\r
196 + maildir = _notmuch_message_maildir (local, directory);
\r
197 + _notmuch_message_add_term (message, "maildir", maildir);
\r
199 talloc_free (local);
\r
201 return NOTMUCH_STATUS_SUCCESS;
\r
202 @@ -535,11 +606,18 @@ _notmuch_message_remove_filename (notmuch_message_t *message,
\r
203 void *local = talloc_new (message);
\r
204 char *zfolder_prefix = talloc_asprintf(local, "Z%s", folder_prefix);
\r
205 int zfolder_prefix_len = strlen (zfolder_prefix);
\r
207 + const char *relative, *directory;
\r
208 + char *direntry, *maildir;
\r
209 notmuch_private_status_t private_status;
\r
210 notmuch_status_t status;
\r
211 Xapian::TermIterator i, last;
\r
213 + relative = _notmuch_database_relative_path (message->notmuch, filename);
\r
215 + status = _notmuch_database_split_path (local, relative, &directory, NULL);
\r
219 status = _notmuch_database_filename_to_direntry (
\r
220 local, message->notmuch, filename, NOTMUCH_FIND_LOOKUP, &direntry);
\r
221 if (status || !direntry)
\r
222 @@ -553,12 +631,21 @@ _notmuch_message_remove_filename (notmuch_message_t *message,
\r
226 - /* Re-synchronize "folder:" terms for this message. This requires:
\r
227 - * 1. removing all "folder:" terms
\r
228 - * 2. removing all "folder:" stemmed terms
\r
229 - * 3. adding back terms for all remaining filenames of the message. */
\r
231 - /* 1. removing all "folder:" terms */
\r
232 + /* Re-synchronize "folder:" and "maildir:" terms for this message. This
\r
234 + * 1. removing "maildir:" for this filename
\r
235 + * 2. removing all "folder:" terms
\r
236 + * 3. removing all "folder:" stemmed terms
\r
238 + * For all remaining filenames of the message:
\r
239 + * 4. adding back "folder:" terms
\r
240 + * 5. adding back "maildir:" */
\r
242 + /* 1. remove "maildir:" for this message */
\r
243 + maildir = _notmuch_message_maildir (local, directory);
\r
244 + _notmuch_message_remove_term (message, "maildir", maildir);
\r
246 + /* 2. removing all "folder:" terms */
\r
248 i = message->doc.termlist_begin ();
\r
249 i.skip_to (folder_prefix);
\r
250 @@ -577,7 +664,7 @@ _notmuch_message_remove_filename (notmuch_message_t *message,
\r
254 - /* 2. removing all "folder:" stemmed terms */
\r
255 + /* 3. removing all "folder:" stemmed terms */
\r
257 i = message->doc.termlist_begin ();
\r
258 i.skip_to (zfolder_prefix);
\r
259 @@ -596,7 +683,7 @@ _notmuch_message_remove_filename (notmuch_message_t *message,
\r
263 - /* 3. adding back terms for all remaining filenames of the message. */
\r
264 + /* for all remaining filenames of the message */
\r
265 i = message->doc.termlist_begin ();
\r
266 i.skip_to (direntry_prefix);
\r
268 @@ -623,8 +710,14 @@ _notmuch_message_remove_filename (notmuch_message_t *message,
\r
269 directory = _notmuch_database_get_directory_path (local,
\r
273 + /* 4. adding back "folder:" terms */
\r
274 if (strlen (directory))
\r
275 _notmuch_message_gen_terms (message, "folder", directory);
\r
277 + /* 5. adding back "maildir:" */
\r
278 + maildir = _notmuch_message_maildir (local, directory);
\r
279 + _notmuch_message_add_term (message, "maildir", maildir);
\r
282 talloc_free (local);
\r