[PATCH] Add a few tests for searching LWN emails.

2011-01-29 Thread Chris Wilson
On Fri, 28 Jan 2011 15:17:54 -0700, Jake Edge  wrote:
> Hi Carl and Thomas, 
> 
> On Sat, 29 Jan 2011 05:59:38 +1000 Carl Worth wrote:
> 
> > Yes, I believe this is related to the dot in the name. From my
> > recollection a name with an address requires quoting. So the header
> > that is currently formatted as:
> > 
> > From: LWN.net Weekly Notification 
> > 
> > should instead be:
> > 
> > From: "LWN.net Weekly Notification" 
> 
> I am by no means an expert, but http://www.ietf.org/rfc/rfc2821.txt
> would seem to indicate that names with a '.' in them don't need to be
> quoted as there are several lines in the Scenarios section that look
> like:
> 
> C: From: John Q. Public 
> 
> unless the problem is XXX.yyy (i.e. no spaces on either side of the
> '.'), but that seems like a pretty arbitrary differentiator (i.e. 'Q. '
> is fine, but 'LWN.net' isn't)

The syntax is defined in http://www.faqs.org/rfcs/rfc2822.html in
particular section 3.2.4. From that it appears the unquoted use of
[a-Z][.a-Z]* is valid. However, I shall leave the intricacies to those
whose understand and appreciate the whole problem...
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre


Re: [PATCH] Add a few tests for searching LWN emails.

2011-01-29 Thread Chris Wilson
On Fri, 28 Jan 2011 15:17:54 -0700, Jake Edge j...@lwn.net wrote:
 Hi Carl and Thomas, 
 
 On Sat, 29 Jan 2011 05:59:38 +1000 Carl Worth wrote:
 
  Yes, I believe this is related to the dot in the name. From my
  recollection a name with an address requires quoting. So the header
  that is currently formatted as:
  
  From: LWN.net Weekly Notification l...@lwn.net
  
  should instead be:
  
  From: LWN.net Weekly Notification l...@lwn.net
 
 I am by no means an expert, but http://www.ietf.org/rfc/rfc2821.txt
 would seem to indicate that names with a '.' in them don't need to be
 quoted as there are several lines in the Scenarios section that look
 like:
 
 C: From: John Q. Public j...@bar.com
 
 unless the problem is XXX.yyy (i.e. no spaces on either side of the
 '.'), but that seems like a pretty arbitrary differentiator (i.e. 'Q. '
 is fine, but 'LWN.net' isn't)

The syntax is defined in http://www.faqs.org/rfcs/rfc2822.html in
particular section 3.2.4. From that it appears the unquoted use of
[a-Z][.a-Z]* is valid. However, I shall leave the intricacies to those
whose understand and appreciate the whole problem...
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH] Makefile: specify libnotmuch.so location with -rpath

2010-04-25 Thread Chris Wilson
In order to handle installation into user directories, it is convenient
to encode the library location into the search path for the notmuch
executable. This is achieved for the GNU linker with the -rpath
argument.
---
 Makefile.local |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/Makefile.local b/Makefile.local
index 5bb570b..77d2c45 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -31,7 +31,7 @@ GPG_FILE=$(SHA1_FILE).asc
 # Smash together user's values with our extra values
 FINAL_CFLAGS = -DNOTMUCH_VERSION=$(VERSION) $(CFLAGS) $(WARN_CFLAGS) 
$(CONFIGURE_CFLAGS) $(extra_cflags)
 FINAL_CXXFLAGS = $(CXXFLAGS) $(WARN_CXXFLAGS) $(CONFIGURE_CXXFLAGS) 
$(extra_cflags) $(extra_cxxflags)
-FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Llib -lnotmuch
+FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Wl,-rpath=$(prefix)/lib -Llib -lnotmuch
 FINAL_NOTMUCH_LINKER = CC
 ifneq ($(LINKER_RESOLVES_LIBRARY_DEPENDENCIES),1)
 FINAL_NOTMUCH_LDFLAGS += $(CONFIGURE_LDFLAGS)
-- 
1.7.0.5



[PATCH] Makefile: specify libnotmuch.so location with -rpath

2010-04-25 Thread Chris Wilson
In order to handle installation into user directories, it is convenient
to encode the library location into the search path for the notmuch
executable. This is achieved for the GNU linker with the -rpath
argument.
---
 Makefile.local |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/Makefile.local b/Makefile.local
index 5bb570b..77d2c45 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -31,7 +31,7 @@ GPG_FILE=$(SHA1_FILE).asc
 # Smash together user's values with our extra values
 FINAL_CFLAGS = -DNOTMUCH_VERSION=$(VERSION) $(CFLAGS) $(WARN_CFLAGS) 
$(CONFIGURE_CFLAGS) $(extra_cflags)
 FINAL_CXXFLAGS = $(CXXFLAGS) $(WARN_CXXFLAGS) $(CONFIGURE_CXXFLAGS) 
$(extra_cflags) $(extra_cxxflags)
-FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Llib -lnotmuch
+FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Wl,-rpath=$(prefix)/lib -Llib -lnotmuch
 FINAL_NOTMUCH_LINKER = CC
 ifneq ($(LINKER_RESOLVES_LIBRARY_DEPENDENCIES),1)
 FINAL_NOTMUCH_LDFLAGS += $(CONFIGURE_LDFLAGS)
-- 
1.7.0.5

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[notmuch] [PATCH] [RFC] notmuch search: Return a non-zero exitcode if the search returns no hits.

2010-01-15 Thread Chris Wilson
If the user is explicitly searching for a message, then if notmuch
fails to find it, it is useful to set a failure exit code. This makes it
easier for scripting. However, we will want to then distinguish between
fatal errors (such as out-of-memory, invalid arguments, corrupt db, etc)
from the simple no message. To that end, we introduce a set of
enumerated exit-codes which may prove useful to use consistently across
notmuch. (I'm not that convinced highly differentiated errors is
particularly useful, though separate CONFIG_ERROR and DATABASE_ERROR
would seem to have value for scripts.)
---
 notmuch-search.c |   34 --
 1 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/notmuch-search.c b/notmuch-search.c
index dc44eb6..6ca903b 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -20,7 +20,17 @@

 #include "notmuch-client.h"

-static void
+/* XXX After some review, make these universal? */
+enum {
+NOTMUCH_EXIT_SUCCESS = 0,
+NOTMUCH_EXIT_NOT_FOUND,
+NOTMUCH_EXIT_INVALID_ARGUMENT,
+NOTMUCH_EXIT_SYSTEM_ERROR, /* XXX just out-of-memory? */
+NOTMUCH_EXIT_CONFIG_ERROR,
+NOTMUCH_EXIT_DATABASE_ERROR,
+};
+
+static int
 do_search_threads (const void *ctx,
   notmuch_query_t *query,
   notmuch_sort_t sort)
@@ -30,6 +40,7 @@ do_search_threads (const void *ctx,
 notmuch_tags_t *tags;
 time_t date;
 const char *relative_date;
+int count = 0;

 for (threads = notmuch_query_search_threads (query);
 notmuch_threads_has_more (threads);
@@ -67,7 +78,10 @@ do_search_threads (const void *ctx,
printf (")\n");

notmuch_thread_destroy (thread);
+   count++;
 }
+
+return count;
 }

 int
@@ -94,11 +108,11 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
sort = NOTMUCH_SORT_NEWEST_FIRST;
} else {
fprintf (stderr, "Invalid value for --sort: %s\n", opt);
-   return 1;
+   return NOTMUCH_EXIT_INVALID_ARGUMENT;
}
} else {
fprintf (stderr, "Unrecognized option: %s\n", argv[i]);
-   return 1;
+   return NOTMUCH_EXIT_INVALID_ARGUMENT;
}
 }

@@ -107,35 +121,35 @@ notmuch_search_command (void *ctx, int argc, char *argv[])

 config = notmuch_config_open (ctx, NULL, NULL);
 if (config == NULL)
-   return 1;
+   return NOTMUCH_EXIT_CONFIG_ERROR;

 notmuch = notmuch_database_open (notmuch_config_get_database_path (config),
 NOTMUCH_DATABASE_MODE_READ_ONLY);
 if (notmuch == NULL)
-   return 1;
+   return NOTMUCH_EXIT_DATABASE_ERROR;

 query_str = query_string_from_args (ctx, argc, argv);
 if (query_str == NULL) {
fprintf (stderr, "Out of memory.\n");
-   return 1;
+   return NOTMUCH_EXIT_SYSTEM_ERROR;
 }
 if (*query_str == '\0') {
fprintf (stderr, "Error: notmuch search requires at least one search 
term.\n");
-   return 1;
+   return NOTMUCH_EXIT_INVALID_ARGUMENT;
 }

 query = notmuch_query_create (notmuch, query_str);
 if (query == NULL) {
fprintf (stderr, "Out of memory\n");
-   return 1;
+   return NOTMUCH_EXIT_SYSTEM_ERROR;
 }

 notmuch_query_set_sort (query, sort);

-do_search_threads (ctx, query, sort);
+i = do_search_threads (ctx, query, sort);

 notmuch_query_destroy (query);
 notmuch_database_close (notmuch);

-return 0;
+return i ? NOTMUCH_EXIT_SUCCESS : NOTMUCH_EXIT_NOT_FOUND;
 }
-- 
1.6.6



[notmuch] [PATCH] [RFC] notmuch search: Return a non-zero exitcode if the search returns no hits.

2010-01-15 Thread Chris Wilson
If the user is explicitly searching for a message, then if notmuch
fails to find it, it is useful to set a failure exit code. This makes it
easier for scripting. However, we will want to then distinguish between
fatal errors (such as out-of-memory, invalid arguments, corrupt db, etc)
from the simple no message. To that end, we introduce a set of
enumerated exit-codes which may prove useful to use consistently across
notmuch. (I'm not that convinced highly differentiated errors is
particularly useful, though separate CONFIG_ERROR and DATABASE_ERROR
would seem to have value for scripts.)
---
 notmuch-search.c |   34 --
 1 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/notmuch-search.c b/notmuch-search.c
index dc44eb6..6ca903b 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -20,7 +20,17 @@
 
 #include notmuch-client.h
 
-static void
+/* XXX After some review, make these universal? */
+enum {
+NOTMUCH_EXIT_SUCCESS = 0,
+NOTMUCH_EXIT_NOT_FOUND,
+NOTMUCH_EXIT_INVALID_ARGUMENT,
+NOTMUCH_EXIT_SYSTEM_ERROR, /* XXX just out-of-memory? */
+NOTMUCH_EXIT_CONFIG_ERROR,
+NOTMUCH_EXIT_DATABASE_ERROR,
+};
+
+static int
 do_search_threads (const void *ctx,
   notmuch_query_t *query,
   notmuch_sort_t sort)
@@ -30,6 +40,7 @@ do_search_threads (const void *ctx,
 notmuch_tags_t *tags;
 time_t date;
 const char *relative_date;
+int count = 0;
 
 for (threads = notmuch_query_search_threads (query);
 notmuch_threads_has_more (threads);
@@ -67,7 +78,10 @@ do_search_threads (const void *ctx,
printf ()\n);
 
notmuch_thread_destroy (thread);
+   count++;
 }
+
+return count;
 }
 
 int
@@ -94,11 +108,11 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
sort = NOTMUCH_SORT_NEWEST_FIRST;
} else {
fprintf (stderr, Invalid value for --sort: %s\n, opt);
-   return 1;
+   return NOTMUCH_EXIT_INVALID_ARGUMENT;
}
} else {
fprintf (stderr, Unrecognized option: %s\n, argv[i]);
-   return 1;
+   return NOTMUCH_EXIT_INVALID_ARGUMENT;
}
 }
 
@@ -107,35 +121,35 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
 
 config = notmuch_config_open (ctx, NULL, NULL);
 if (config == NULL)
-   return 1;
+   return NOTMUCH_EXIT_CONFIG_ERROR;
 
 notmuch = notmuch_database_open (notmuch_config_get_database_path (config),
 NOTMUCH_DATABASE_MODE_READ_ONLY);
 if (notmuch == NULL)
-   return 1;
+   return NOTMUCH_EXIT_DATABASE_ERROR;
 
 query_str = query_string_from_args (ctx, argc, argv);
 if (query_str == NULL) {
fprintf (stderr, Out of memory.\n);
-   return 1;
+   return NOTMUCH_EXIT_SYSTEM_ERROR;
 }
 if (*query_str == '\0') {
fprintf (stderr, Error: notmuch search requires at least one search 
term.\n);
-   return 1;
+   return NOTMUCH_EXIT_INVALID_ARGUMENT;
 }
 
 query = notmuch_query_create (notmuch, query_str);
 if (query == NULL) {
fprintf (stderr, Out of memory\n);
-   return 1;
+   return NOTMUCH_EXIT_SYSTEM_ERROR;
 }
 
 notmuch_query_set_sort (query, sort);
 
-do_search_threads (ctx, query, sort);
+i = do_search_threads (ctx, query, sort);
 
 notmuch_query_destroy (query);
 notmuch_database_close (notmuch);
 
-return 0;
+return i ? NOTMUCH_EXIT_SUCCESS : NOTMUCH_EXIT_NOT_FOUND;
 }
-- 
1.6.6

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[notmuch] semi-usable notmuch-gtk client

2009-12-07 Thread Chris Wilson
On Mon, 07 Dec 2009 09:57:12 -0800, Carl Worth  wrote:
> On Mon, 07 Dec 2009 16:42:42 +0530, "Aneesh Kumar K. V"  linux.vnet.ibm.com> wrote:
> > While discussing notmuch with some of the gnome developers they pointed
> > me to http://live.gnome.org/Anjal/ . The interface is suited to the way
> > notmuch displays threads. So i guess it would really cool if we can get
> > anjal to use nomuch as one of the backend.
> > 
> > That should also make sure you get a working mailclient in gtk with
> > minimal changes
> 
> Thanks for mentioning this, Aneesh.
> 
> Hooking up Anjal to notmuch was an idea that Chris Wilson had almost
> immediately after playing with notmuch. I think he even started poking
> around in the Anjal code base to see how much work this would be.
> 
> Chris, did you make any progress worth mentioning in your
> investigations?

Before being distracted again, the impression I got from reading Anjal was
that to integrate with it, you needed to understand evolution-data-server
and camel. Anjal itself seems to be a relatively thin message/folder
viewer and composer, with the details hidden behind camel. So the next
step, I felt, would be to see whether you could write a notmuch data store
for evolution.
-ickle

-- 
Chris Wilson, Intel Open Source Technology Centre


Re: [notmuch] semi-usable notmuch-gtk client

2009-12-07 Thread Chris Wilson
On Mon, 07 Dec 2009 09:57:12 -0800, Carl Worth cwo...@cworth.org wrote:
 On Mon, 07 Dec 2009 16:42:42 +0530, Aneesh Kumar K. V 
 aneesh.ku...@linux.vnet.ibm.com wrote:
  While discussing notmuch with some of the gnome developers they pointed
  me to http://live.gnome.org/Anjal/ . The interface is suited to the way
  notmuch displays threads. So i guess it would really cool if we can get
  anjal to use nomuch as one of the backend.
  
  That should also make sure you get a working mailclient in gtk with
  minimal changes
 
 Thanks for mentioning this, Aneesh.
 
 Hooking up Anjal to notmuch was an idea that Chris Wilson had almost
 immediately after playing with notmuch. I think he even started poking
 around in the Anjal code base to see how much work this would be.
 
 Chris, did you make any progress worth mentioning in your
 investigations?

Before being distracted again, the impression I got from reading Anjal was
that to integrate with it, you needed to understand evolution-data-server
and camel. Anjal itself seems to be a relatively thin message/folder
viewer and composer, with the details hidden behind camel. So the next
step, I felt, would be to see whether you could write a notmuch data store
for evolution.
-ickle

-- 
Chris Wilson, Intel Open Source Technology Centre
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[notmuch] [PATCH] notmuch-new: Eliminate tallocs whilst construct filenames.

2009-11-27 Thread Chris Wilson
Excerpts from Carl Worth's message of Fri Nov 27 13:23:06 + 2009:
> On Sun, 22 Nov 2009 00:57:10 +0000, Chris Wilson  chris-wilson.co.uk> wrote:
> > The majority of filenames will fit within PATH_MAX [4096] (because
> > that's a hard limit imposed by the filesystems) so we can avoid an
> > allocation per lookup and thereby eliminate a large proportion of the
> > overhead of scanning a maildir.
> 
> Hi Chris,
> 
> I *know* I composed a reply to this message earlier, but apparently
> you're right that it never went out. (*sigh*---if only I had a reliable
> mail client[*]).

I hear there's one called sup... ;-)

> Anyway, on to the promised review of the patch:
> 
> The basic idea of this I really like, of course. Thanks for helping to
> improve the efficiency of notmuch. But this part I don't:

It's a bit outdated now, the impact of the asprintf overhead is lost
with the introduction of the scandir. I'm sure the profiles will
indicate something else to improve beyond xapian...

> One might argue that the error-cleanup goto is a common and
> well-understood idiom, so that it's not bad to have. The problem I have
> with it is how much work it is to verify. If I'm reading one line of
> code in the middle of a function that's testing for an error case and
> handling it with goto, then I need to:
> 
> 1. Verify this condition, and that a return value variable gets
>set.
> 
> 2. Check down at the end of the function to ensure the correct
>objects are freed and the correct return value is returned.
> 
> 3. Check back up at the beginning of the function to ensure the
>relevant objects are initialized to NULL.
> 
> And beyond verification, one has to code in these three places
> simultaneously as well.
> 
> Meanwhile, by taking advantage of talloc like I did in the original
> version of this code, an error return becomes a much more local decision
> and is much simpler to code.

The issue I see with the "error, continue" pattern is that we are in
danger of not reporting the first error but the last one. The common
practice is abort on error and cleanup, and this single instance is
inconsistent with the rest of the error handling everywhere else in
notmuch-new.c. The argument to counter your 3 points is the unified
unwind approach where there is just a single exit path that handles
both error and normal returns. (You always have to set the appropriate
error value whether you continue or abort.)

The advantage of talloc is that it provides a convenient allocation
context that not only groups object by their associated lifetimes, but
provides a single point of access for reaping allocations on unwind. I
don't see how talloc affects the decision process on how to actually
handle errors, but it does make it easier to cleanup afterwards.

Is notmuch ready for fault-injection yet? Maybe once you have a nasty
testsuite...
-ickle
-- 
Chris Wilson, Intel Open Source Technology Centre


[notmuch] [PATCH] notmuch-new: Check for non-fatal errors from stat()

2009-11-27 Thread Chris Wilson
Currently we assume that all errors on stat() a dname is fatal (but
continue anyway and report the error at the end). However, some errors
reported by stat() such as a missing file or insufficient privilege,
we can simply ignore and skip the file. For the others, such as a fault
(unlikely!) or out-of-memory, we handle like the other fatal errors by
jumping to the end.

Signed-off-by: Chris Wilson 
---
 notmuch-new.c |   13 -
 1 files changed, 12 insertions(+), 1 deletions(-)

diff --git a/notmuch-new.c b/notmuch-new.c
index 3cde3a7..71224c5 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -168,10 +168,21 @@ add_files_recursive (notmuch_database_t *notmuch,
next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name);

if (stat (next, st)) {
+   int err = errno;
+
+   switch (err) {
+   case ENOENT:
+   /* The file was removed between scandir and now... */
+   case EPERM:
+   case EACCES:
+   /* We can't read this file so don't add it to the cache. */
+   continue;
+   }
+
fprintf (stderr, "Error reading %s: %s\n",
 next, strerror (errno));
ret = NOTMUCH_STATUS_FILE_ERROR;
-   continue;
+   goto DONE;
}

if (S_ISREG (st->st_mode)) {
-- 
1.6.5.3



[notmuch] [PATCH] notmuch-new: Remove the tiresome joke from the output.

2009-11-24 Thread Chris Wilson
As I see this every time I poll for new mail, the joke becomes very old
very quickly.  The other instances of "not much" are shown much less
often and have a much more natural style, this one however feels forced,
impairing the humorous effect.

Signed-off-by: Chris "the critic" Wilson 
---
 notmuch-new.c |4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/notmuch-new.c b/notmuch-new.c
index e32b92a..3cde3a7 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -483,12 +483,10 @@ notmuch_new_command (void *ctx, int argc, char *argv[])
}
 }
 if (add_files_state.added_messages) {
-   printf ("Added %d new %s to the database (not much, really).\n",
+   printf ("Added %d new %s to the database.\n",
add_files_state.added_messages,
add_files_state.added_messages == 1 ?
"message" : "messages");
-} else {
-   printf ("No new mail---and that's not much.\n");
 }

 if (elapsed > 1 && ! add_files_state.saw_read_only_directory) {
-- 
1.6.5.3



[notmuch] [PATCH] notmuch-new: Eliminate tallocs whilst construct filenames.

2009-11-22 Thread Chris Wilson
The majority of filenames will fit within PATH_MAX [4096] (because
that's a hard limit imposed by the filesystems) so we can avoid an
allocation per lookup and thereby eliminate a large proportion of the
overhead of scanning a maildir.

Signed-off-by: Chris Wilson 
---
 notmuch-new.c |   75 ++--
 1 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/notmuch-new.c b/notmuch-new.c
index 0dd2784..13559d1 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -107,6 +107,7 @@ add_files_recursive (notmuch_database_t *notmuch,
 add_files_state_t *state)
 {
 DIR *dir = NULL;
+char buf[4096];
 struct dirent *entry = NULL;
 char *next = NULL;
 time_t path_mtime, path_dbtime;
@@ -114,6 +115,7 @@ add_files_recursive (notmuch_database_t *notmuch,
 notmuch_message_t *message = NULL;
 struct dirent **namelist = NULL;
 int num_entries;
+int path_len, dname_len;

 /* If we're told to, we bail out on encountering a read-only
  * directory, (with this being a clear clue from the user to
@@ -140,6 +142,12 @@ add_files_recursive (notmuch_database_t *notmuch,

 int i=0;

+path_len = strlen (path);
+if (path_len + 2 < (int) sizeof (buf)) {
+   memcpy (buf, path, path_len);
+   buf[path_len] = '/';
+}
+
 while (!interrupted) {
if (i == num_entries)
break;
@@ -164,37 +172,42 @@ add_files_recursive (notmuch_database_t *notmuch,
continue;
}

-   next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name);
+   dname_len = strlen (entry->d_name);
+   if (path_len + dname_len + 2 < (int) sizeof (buf)) {
+   memcpy (buf + path_len + 1, entry->d_name, dname_len);
+   buf[path_len + dname_len + 1] = '\0';
+   next = buf;
+   } else {
+   next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name);
+   }

if (stat (next, st)) {
fprintf (stderr, "Error reading %s: %s\n",
 next, strerror (errno));
ret = NOTMUCH_STATUS_FILE_ERROR;
-   continue;
-   }
-
-   if (S_ISREG (st->st_mode)) {
-   /* If the file hasn't been modified since the last
-* add_files, then we need not look at it. */
-   if (path_dbtime == 0 || st->st_mtime > path_dbtime) {
-   state->processed_files++;
-
-   status = notmuch_database_add_message (notmuch, next, );
-   switch (status) {
-   /* success */
+   } else {
+   if (S_ISREG (st->st_mode)) {
+   /* If the file hasn't been modified since the last
+* add_files, then we need not look at it. */
+   if (path_dbtime == 0 || st->st_mtime > path_dbtime) {
+   state->processed_files++;
+
+   status = notmuch_database_add_message (notmuch, next, 
);
+   switch (status) {
+   /* success */
case NOTMUCH_STATUS_SUCCESS:
state->added_messages++;
tag_inbox_and_unread (message);
break;
-   /* Non-fatal issues (go on to next file) */
+   /* Non-fatal issues (go on to next file) */
case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:
-   /* Stay silent on this one. */
+   /* Stay silent on this one. */
break;
case NOTMUCH_STATUS_FILE_NOT_EMAIL:
fprintf (stderr, "Note: Ignoring non-mail file: %s\n",
 next);
break;
-   /* Fatal issues. Don't process anymore. */
+   /* Fatal issues. Don't process anymore. */
case NOTMUCH_STATUS_READONLY_DATABASE:
case NOTMUCH_STATUS_XAPIAN_EXCEPTION:
case NOTMUCH_STATUS_OUT_OF_MEMORY:
@@ -210,25 +223,27 @@ add_files_recursive (notmuch_database_t *notmuch,
case NOTMUCH_STATUS_LAST_STATUS:
INTERNAL_ERROR ("add_message returned unexpected value: 
%d",  status);
goto DONE;
-   }
+   }

-   if (message) {
-   notmuch_message_destroy (message);
-   message = NULL;
-   }
+   if (message) {
+   notmuch_message_destroy (message);
+   message = NULL;
+   }

-   if (do_add_files_print_progress) {
-   do_add_files_print_progress = 0;
-   add_files_print_progress (state);
+   if (do_add_files_print_progress) {
+

[notmuch] [PATCH 2/2] notmuch-new: Only print the regular progress report when on a tty

2009-11-22 Thread Chris Wilson
Check that the stdout is connected to an interactive terminal with
isatty() before installing the periodic timer to print progress reports.

Signed-off-by: Chris Wilson 
---
 notmuch-new.c |4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/notmuch-new.c b/notmuch-new.c
index 1616ee9..0dd2784 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -20,6 +20,8 @@

 #include "notmuch-client.h"

+#include 
+
 static volatile sig_atomic_t do_add_files_print_progress = 0;

 static void
@@ -273,7 +275,7 @@ add_files (notmuch_database_t *notmuch,
 }

 /* Setup our handler for SIGALRM */
-if (! debugger_is_active ()) {
+if (isatty (fileno (stdout)) && ! debugger_is_active ()) {
memset (, 0, sizeof (struct sigaction));
action.sa_handler = handle_sigalrm;
sigemptyset (_mask);
-- 
1.6.5.3



[notmuch] [PATCH 1/2] notmuch-new: Only install SIGALRM if not running under gdb

2009-11-22 Thread Chris Wilson
I felt sorry for Carl trying to step through an exception from xapian
and suffering from the SIGALARMs..

We can detect if the user launched notmuch under a debugger by either
checking our cmdline for the presence of the gdb string or querying if
valgrind is controlling our process. For the latter we need to add a
compile time check for the valgrind development library, and so add the
initial support to build Makefile.config from configure.

Signed-off-by: Chris Wilson 
Reviewed-by: Carl Worth 
[ickle: And do not install the timer when under the debugger]
---
 Makefile.config  |1 +
 Makefile.local   |3 ++-
 configure|   21 +
 debugger.c   |   47 +++
 notmuch-client.h |3 +++
 notmuch-new.c|   49 -
 6 files changed, 98 insertions(+), 26 deletions(-)
 create mode 100644 debugger.c

diff --git a/Makefile.config b/Makefile.config
index d72a39e..ddc7436 100644
--- a/Makefile.config
+++ b/Makefile.config
@@ -1,2 +1,3 @@
 prefix = /usr/local
 bash_completion_dir = /etc/bash_completion.d
+CFLAGS += -DHAVE_VALGRIND
diff --git a/Makefile.local b/Makefile.local
index 3c99624..efe76c8 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -3,6 +3,8 @@ all: notmuch notmuch.1.gz
 emacs: notmuch.elc

 notmuch_client_srcs =  \
+   debugger.c  \
+   gmime-filter-reply.c\
notmuch.c   \
notmuch-config.c\
notmuch-dump.c  \
@@ -14,7 +16,6 @@ notmuch_client_srcs = \
notmuch-show.c  \
notmuch-tag.c   \
notmuch-time.c  \
-   gmime-filter-reply.c\
query-string.c  \
show-message.c

diff --git a/configure b/configure
index fe46c8e..b4770ec 100755
--- a/configure
+++ b/configure
@@ -53,6 +53,14 @@ else
 errors=$((errors + 1))
 fi

+if pkg-config --modversion valgrind > /dev/null 2>&1; then
+echo "Checking for valgrind development files... Yes."
+have_valgrind=-DHAVE_VALGRIND
+else
+echo "Checking for valgrind development files... No."
+have_valgrind=
+fi
+
 if [ $errors -gt 0 ]; then
 cat < Makefile.config <http://www.gnu.org/licenses/ .
+ *
+ * Author: Chris Wilson 
+ */
+
+#include "notmuch-client.h"
+
+#include 
+
+#if HAVE_VALGRIND
+#include 
+#else
+#define RUNNING_ON_VALGRIND 0
+#endif
+
+notmuch_bool_t
+debugger_is_active (void)
+{
+char buf[1024];
+
+if (RUNNING_ON_VALGRIND)
+   return TRUE;
+
+sprintf (buf, "/proc/%d/exe", getppid ());
+if (readlink (buf, buf, sizeof (buf)) != -1 &&
+   strncmp (basename (buf), "gdb", 3) == 0)
+{
+   return TRUE;
+}
+
+return FALSE;
+}
diff --git a/notmuch-client.h b/notmuch-client.h
index b65aa77..ea77686 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -179,4 +179,7 @@ notmuch_config_set_user_other_email (notmuch_config_t 
*config,
 const char *other_email[],
 size_t length);

+notmuch_bool_t
+debugger_is_active (void);
+
 #endif
diff --git a/notmuch-new.c b/notmuch-new.c
index 43cc4fb..1616ee9 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -259,6 +259,7 @@ add_files (notmuch_database_t *notmuch,
 notmuch_status_t status;
 struct sigaction action;
 struct itimerval timerval;
+notmuch_bool_t timer_is_active = FALSE;

 if (stat (path, )) {
fprintf (stderr, "Error reading directory %s: %s\n",
@@ -272,31 +273,37 @@ add_files (notmuch_database_t *notmuch,
 }

 /* Setup our handler for SIGALRM */
-memset (, 0, sizeof (struct sigaction));
-action.sa_handler = handle_sigalrm;
-sigemptyset (_mask);
-action.sa_flags = SA_RESTART;
-sigaction (SIGALRM, , NULL);
-
-/* Then start a timer to send SIGALRM once per second. */
-timerval.it_interval.tv_sec = 1;
-timerval.it_interval.tv_usec = 0;
-timerval.it_value.tv_sec = 1;
-timerval.it_value.tv_usec = 0;
-setitimer (ITIMER_REAL, , NULL);
+if (! debugger_is_active ()) {
+   memset (, 0, sizeof (struct sigaction));
+   action.sa_handler = handle_sigalrm;
+   sigemptyset (_mask);
+   action.sa_flags = SA_RESTART;
+   sigaction (SIGALRM, , NULL);
+
+   /* Then start a timer to send SIGALRM once per second. */
+   timerval.it_interval.tv_sec = 1;
+   timerval.it_interval.tv_usec = 0;
+   timerval.it_value.tv_sec = 1;
+   timerval.it_value.tv_usec = 0;
+   setitimer (ITIMER_REAL, , NULL);
+
+   timer_is_active = TRUE;
+}

 status = add_files_recursive (notmuch, path, , state);

 /* Now stop the timer. */
-timerval.it_interval.tv_sec = 0;
-timerval.it_interval.tv_usec = 0;
-timerval.it_value.tv_sec = 0;
-timerval.it_value.tv_usec = 0;
-setitimer (ITIMER_REAL, , 

[notmuch] Avoid installing SIGALRMs when under the debugger.

2009-11-22 Thread Chris Wilson
Gah, I'm tired and using "git send-email HEAD^" is too easy. Here is the
most recent pair of patches in possibly a working state.
-ickle



[notmuch] [PATCH] notmuch-new: Only install SIGALRM if not running under gdb

2009-11-22 Thread Chris Wilson
I felt sorry for Carl trying to step through an exception from xapian
and suffering from the SIGALARMs..

We can detect if the user launched notmuch under a debugger by either
checking our cmdline for the presence of the gdb string or querying if
valgrind is controlling our process. For the latter we need to add a
compile time check for the valgrind development library, and so add the
initial support to build Makefile.config from configure.

Signed-off-by: Chris Wilson 
Reviewed-by: Carl Worth 
[ickle: And do not install the timer]
---
 Makefile.config  |1 +
 Makefile.local   |3 ++-
 configure|   21 +
 debugger.c   |   47 +++
 notmuch-client.h |3 +++
 notmuch-new.c|   12 +++-
 6 files changed, 77 insertions(+), 10 deletions(-)
 create mode 100644 debugger.c

diff --git a/Makefile.config b/Makefile.config
index d72a39e..ddc7436 100644
--- a/Makefile.config
+++ b/Makefile.config
@@ -1,2 +1,3 @@
 prefix = /usr/local
 bash_completion_dir = /etc/bash_completion.d
+CFLAGS += -DHAVE_VALGRIND
diff --git a/Makefile.local b/Makefile.local
index 3c99624..efe76c8 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -3,6 +3,8 @@ all: notmuch notmuch.1.gz
 emacs: notmuch.elc

 notmuch_client_srcs =  \
+   debugger.c  \
+   gmime-filter-reply.c\
notmuch.c   \
notmuch-config.c\
notmuch-dump.c  \
@@ -14,7 +16,6 @@ notmuch_client_srcs = \
notmuch-show.c  \
notmuch-tag.c   \
notmuch-time.c  \
-   gmime-filter-reply.c\
query-string.c  \
show-message.c

diff --git a/configure b/configure
index fe46c8e..b4770ec 100755
--- a/configure
+++ b/configure
@@ -53,6 +53,14 @@ else
 errors=$((errors + 1))
 fi

+if pkg-config --modversion valgrind > /dev/null 2>&1; then
+echo "Checking for valgrind development files... Yes."
+have_valgrind=-DHAVE_VALGRIND
+else
+echo "Checking for valgrind development files... No."
+have_valgrind=
+fi
+
 if [ $errors -gt 0 ]; then
 cat < Makefile.config <http://www.gnu.org/licenses/ .
+ *
+ * Author: Chris Wilson 
+ */
+
+#include "notmuch-client.h"
+
+#include 
+
+#if HAVE_VALGRIND
+#include 
+#else
+#define RUNNING_ON_VALGRIND 0
+#endif
+
+notmuch_bool_t
+debugger_is_active (void)
+{
+char buf[1024];
+
+if (RUNNING_ON_VALGRIND)
+   return TRUE;
+
+sprintf (buf, "/proc/%d/exe", getppid ());
+if (readlink (buf, buf, sizeof (buf)) != -1 &&
+   strncmp (basename (buf), "gdb", 3) == 0)
+{
+   return TRUE;
+}
+
+return FALSE;
+}
diff --git a/notmuch-client.h b/notmuch-client.h
index b65aa77..ea77686 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -179,4 +179,7 @@ notmuch_config_set_user_other_email (notmuch_config_t 
*config,
 const char *other_email[],
 size_t length);

+notmuch_bool_t
+debugger_is_active (void);
+
 #endif
diff --git a/notmuch-new.c b/notmuch-new.c
index 43cc4fb..18ba2bd 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -272,11 +272,13 @@ add_files (notmuch_database_t *notmuch,
 }

 /* Setup our handler for SIGALRM */
-memset (, 0, sizeof (struct sigaction));
-action.sa_handler = handle_sigalrm;
-sigemptyset (_mask);
-action.sa_flags = SA_RESTART;
-sigaction (SIGALRM, , NULL);
+if (! debugger_is_active ()) {
+   memset (, 0, sizeof (struct sigaction));
+   action.sa_handler = handle_sigalrm;
+   sigemptyset (_mask);
+   action.sa_flags = SA_RESTART;
+   sigaction (SIGALRM, , NULL);
+}

 /* Then start a timer to send SIGALRM once per second. */
 timerval.it_interval.tv_sec = 1;
-- 
1.6.5.3



[notmuch] [PATCH] notmuch-new: Only install SIGALRM if not running under gdb

2009-11-22 Thread Chris Wilson
I felt sorry for Carl trying to step through an exception from xapian
and suffering from the SIGALARMs..

We can detect if the user launched notmuch under a debugger by either
checking our cmdline for the presence of the gdb string or querying if
valgrind is controlling our process. For the latter we need to add a
compile time check for the valgrind development library, and so add the
initial support to build Makefile.config from configure.

Signed-off-by: Chris Wilson 
Reviewed-by: Carl Worth 
---
 Makefile.config  |1 +
 Makefile.local   |3 ++-
 configure|   21 +
 debugger.c   |   47 +++
 notmuch-client.h |3 +++
 notmuch-new.c|   12 +++-
 6 files changed, 77 insertions(+), 10 deletions(-)
 create mode 100644 debugger.c

diff --git a/Makefile.config b/Makefile.config
index d72a39e..ddc7436 100644
--- a/Makefile.config
+++ b/Makefile.config
@@ -1,2 +1,3 @@
 prefix = /usr/local
 bash_completion_dir = /etc/bash_completion.d
+CFLAGS += -DHAVE_VALGRIND
diff --git a/Makefile.local b/Makefile.local
index 3c99624..efe76c8 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -3,6 +3,8 @@ all: notmuch notmuch.1.gz
 emacs: notmuch.elc

 notmuch_client_srcs =  \
+   debugger.c  \
+   gmime-filter-reply.c\
notmuch.c   \
notmuch-config.c\
notmuch-dump.c  \
@@ -14,7 +16,6 @@ notmuch_client_srcs = \
notmuch-show.c  \
notmuch-tag.c   \
notmuch-time.c  \
-   gmime-filter-reply.c\
query-string.c  \
show-message.c

diff --git a/configure b/configure
index fe46c8e..b4770ec 100755
--- a/configure
+++ b/configure
@@ -53,6 +53,14 @@ else
 errors=$((errors + 1))
 fi

+if pkg-config --modversion valgrind > /dev/null 2>&1; then
+echo "Checking for valgrind development files... Yes."
+have_valgrind=-DHAVE_VALGRIND
+else
+echo "Checking for valgrind development files... No."
+have_valgrind=
+fi
+
 if [ $errors -gt 0 ]; then
 cat < Makefile.config <http://www.gnu.org/licenses/ .
+ *
+ * Author: Chris Wilson 
+ */
+
+#include "notmuch-client.h"
+
+#include 
+
+#if HAVE_VALGRIND
+#include 
+#else
+#define RUNNING_ON_VALGRIND 0
+#endif
+
+notmuch_bool_t
+debugger_is_active (void)
+{
+char buf[1024];
+
+if (RUNNING_ON_VALGRIND)
+   return TRUE;
+
+sprintf (buf, "/proc/%d/exe", getppid ());
+if (readlink (buf, buf, sizeof (buf)) != -1 &&
+   strncmp (basename (buf), "gdb", 3) == 0)
+{
+   return TRUE;
+}
+
+return FALSE;
+}
diff --git a/notmuch-client.h b/notmuch-client.h
index b65aa77..ea77686 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -179,4 +179,7 @@ notmuch_config_set_user_other_email (notmuch_config_t 
*config,
 const char *other_email[],
 size_t length);

+notmuch_bool_t
+debugger_is_active (void);
+
 #endif
diff --git a/notmuch-new.c b/notmuch-new.c
index 43cc4fb..18ba2bd 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -272,11 +272,13 @@ add_files (notmuch_database_t *notmuch,
 }

 /* Setup our handler for SIGALRM */
-memset (, 0, sizeof (struct sigaction));
-action.sa_handler = handle_sigalrm;
-sigemptyset (_mask);
-action.sa_flags = SA_RESTART;
-sigaction (SIGALRM, , NULL);
+if (! debugger_is_active ()) {
+   memset (, 0, sizeof (struct sigaction));
+   action.sa_handler = handle_sigalrm;
+   sigemptyset (_mask);
+   action.sa_flags = SA_RESTART;
+   sigaction (SIGALRM, , NULL);
+}

 /* Then start a timer to send SIGALRM once per second. */
 timerval.it_interval.tv_sec = 1;
-- 
1.6.5.3



[notmuch] [PATCH] lib/database.cc: coding style

2009-11-21 Thread Chris Wilson
Carl claims he must have been distracted when he wrote this...

Signed-off-by: Chris Wilson 
---
 lib/database.cc |   18 +++---
 1 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 207246c..0f95aa1 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -147,17 +147,20 @@ _find_prefix (const char *name)
 {
 unsigned int i;

-for (i = 0; i < ARRAY_SIZE (BOOLEAN_PREFIX_INTERNAL); i++)
+for (i = 0; i < ARRAY_SIZE (BOOLEAN_PREFIX_INTERNAL); i++) {
if (strcmp (name, BOOLEAN_PREFIX_INTERNAL[i].name) == 0)
return BOOLEAN_PREFIX_INTERNAL[i].prefix;
+}

-for (i = 0; i < ARRAY_SIZE (BOOLEAN_PREFIX_EXTERNAL); i++)
+for (i = 0; i < ARRAY_SIZE (BOOLEAN_PREFIX_EXTERNAL); i++) {
if (strcmp (name, BOOLEAN_PREFIX_EXTERNAL[i].name) == 0)
return BOOLEAN_PREFIX_EXTERNAL[i].prefix;
+}

-for (i = 0; i < ARRAY_SIZE (PROBABILISTIC_PREFIX); i++)
+for (i = 0; i < ARRAY_SIZE (PROBABILISTIC_PREFIX); i++) {
if (strcmp (name, PROBABILISTIC_PREFIX[i].name) == 0)
return PROBABILISTIC_PREFIX[i].prefix;
+}

 INTERNAL_ERROR ("No prefix exists for '%s'\n", name);

@@ -293,13 +296,14 @@ skip_space_and_comments (const char **str)
int nesting = 1;
s++;
while (*s && nesting) {
-   if (*s == '(')
+   if (*s == '(') {
nesting++;
-   else if (*s == ')')
+   } else if (*s == ')') {
nesting--;
-   else if (*s == '\\')
+   } else if (*s == '\\') {
if (*(s+1))
s++;
+   }
s++;
}
}
@@ -508,7 +512,7 @@ notmuch_database_open (const char *path)
 error.get_msg().c_str());
notmuch = NULL;
 }
-
+
   DONE:
 if (notmuch_path)
free (notmuch_path);
-- 
1.6.5.3



[notmuch] [PATCH] Makefile: Magic silent rules.

2009-11-21 Thread Chris Wilson
Use the facilities of GNU make to create a magic function that will
on the first invocation print a description of how to enable verbose
compile lines and then print the quiet rule.

Signed-off-by: Chris Wilson 
Signed-off-by: Carl Worth 
Cc: Mikhail Gusarov 

[ickle: Rebased, and duplicate command string eliminated.]
[ickle: Fixed verbose bug pointed out by Mikhail]
---
 Makefile   |   23 ---
 Makefile.local |4 ++--
 lib/Makefile.local |2 +-
 3 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile
index 3fedcf1..5d8f321 100644
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,10 @@
 WARN_FLAGS=-Wall -Wextra -Wmissing-declarations -Wwrite-strings -Wswitch-enum
 CFLAGS=-O2

+# Additional programs that are used during the compilation process.
+EMACS ?= emacs
+GZIP ?= gzip
+
 # Additional flags that we will append to whatever the user set.
 # These aren't intended for the user to manipulate.
 extra_cflags := $(shell pkg-config --cflags glib-2.0 gmime-2.4 talloc)
@@ -31,14 +35,27 @@ include lib/Makefile.local
 # And get user settings from the output of configure
 include Makefile.config

+# The user has not set any verbosity, default to quiet mode and inform the
+# user how to enable verbose compiles.
+ifeq ($(V),)
+quiet_DOC := "Use \"$(MAKE) V=1\" to see the verbose compile lines.\n"
+quiet = @echo $(quiet_DOC)$(eval quiet_DOC:=)"  $1 $@"; $($1)
+endif
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @echo "  $1$@"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
 %.o: %.cc $(all_deps)
-   $(CXX) -c $(CXXFLAGS) $< -o $@
+   $(call quiet,CXX) -c $(CXXFLAGS) $< -o $@

 %.o: %.c $(all_deps)
-   $(CC) -c $(CFLAGS) $< -o $@
+   $(call quiet,CC) -c $(CFLAGS) $< -o $@

 %.elc: %.el
-   emacs -batch -f batch-byte-compile $<
+   $(call quiet,EMACS) -batch -f batch-byte-compile $<

 .deps/%.d: %.c $(all_deps)
@set -e; rm -f $@; mkdir -p $$(dirname $@) ; \
diff --git a/Makefile.local b/Makefile.local
index 3c99624..5fd5d4f 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -20,10 +20,10 @@ notmuch_client_srcs =   \

 notmuch_client_modules = $(notmuch_client_srcs:.c=.o)
 notmuch: $(notmuch_client_modules) lib/notmuch.a
-   $(CXX) $^ $(LDFLAGS) -o $@
+   $(call quiet,CXX) $^ $(LDFLAGS) -o $@

 notmuch.1.gz: notmuch.1
-   gzip --stdout notmuch.1 > notmuch.1.gz
+   $(call quiet,GZIP) --stdout $^ > $@

 install: all notmuch.1.gz
for d in $(DESTDIR)$(prefix)/bin/ $(DESTDIR)$(prefix)/share/man/man1 \
diff --git a/lib/Makefile.local b/lib/Makefile.local
index 79f7b0b..a7562c9 100644
--- a/lib/Makefile.local
+++ b/lib/Makefile.local
@@ -18,7 +18,7 @@ libnotmuch_cxx_srcs = \

 libnotmuch_modules = $(libnotmuch_c_srcs:.c=.o) $(libnotmuch_cxx_srcs:.cc=.o)
 $(dir)/notmuch.a: $(libnotmuch_modules)
-   $(AR) rcs $@ $^
+   $(call quiet,AR) rcs $@ $^

 SRCS  := $(SRCS) $(libnotmuch_c_srcs) $(libnotmuch_cxx_srcs)
 CLEAN := $(CLEAN) $(libnotmuch_modules) $(dir)/notmuch.a
-- 
1.6.5.3



[notmuch] [PATCH] Permit opening the notmuch database in read-only mode.

2009-11-21 Thread Chris Wilson
We only rarely need to actually open the database for writing, but we
always create a Xapian::WritableDatabase. This has the effect of
preventing searches and like whilst updating the index.

Signed-off-by: Chris Wilson 
Acked-by: Carl Worth 
[ickle: Updated to add WRITABLE mode to notmuch-new]
---
 lib/database-private.h |3 ++-
 lib/database.cc|   31 ---
 lib/message.cc |   15 +--
 lib/notmuch-private.h  |1 +
 lib/notmuch.h  |   13 +++--
 notmuch-dump.c |3 ++-
 notmuch-new.c  |4 +++-
 notmuch-reply.c|3 ++-
 notmuch-restore.c  |3 ++-
 notmuch-search.c   |3 ++-
 notmuch-show.c |3 ++-
 notmuch-tag.c  |3 ++-
 12 files changed, 66 insertions(+), 19 deletions(-)

diff --git a/lib/database-private.h b/lib/database-private.h
index 76e26ce..79c7916 100644
--- a/lib/database-private.h
+++ b/lib/database-private.h
@@ -27,7 +27,8 @@

 struct _notmuch_database {
 char *path;
-Xapian::WritableDatabase *xapian_db;
+notmuch_database_mode_t mode;
+Xapian::Database *xapian_db;
 Xapian::QueryParser *query_parser;
 Xapian::TermGenerator *term_gen;
 };
diff --git a/lib/database.cc b/lib/database.cc
index 207246c..fb38664 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -172,6 +172,8 @@ notmuch_status_to_string (notmuch_status_t status)
return "No error occurred";
 case NOTMUCH_STATUS_OUT_OF_MEMORY:
return "Out of memory";
+case NOTMUCH_STATUS_READONLY_DATABASE:
+   return "The database is read-only";
 case NOTMUCH_STATUS_XAPIAN_EXCEPTION:
return "A Xapian exception occurred";
 case NOTMUCH_STATUS_FILE_ERROR:
@@ -438,7 +440,8 @@ notmuch_database_create (const char *path)
goto DONE;
 }

-notmuch = notmuch_database_open (path);
+notmuch = notmuch_database_open (path,
+NOTMUCH_DATABASE_MODE_WRITABLE);

   DONE:
 if (notmuch_path)
@@ -448,7 +451,8 @@ notmuch_database_create (const char *path)
 }

 notmuch_database_t *
-notmuch_database_open (const char *path)
+notmuch_database_open (const char *path,
+  notmuch_database_mode_t mode)
 {
 notmuch_database_t *notmuch = NULL;
 char *notmuch_path = NULL, *xapian_path = NULL;
@@ -481,9 +485,14 @@ notmuch_database_open (const char *path)
 if (notmuch->path[strlen (notmuch->path) - 1] == '/')
notmuch->path[strlen (notmuch->path) - 1] = '\0';

+notmuch->mode = mode;
 try {
-   notmuch->xapian_db = new Xapian::WritableDatabase (xapian_path,
-  
Xapian::DB_CREATE_OR_OPEN);
+   if (mode == NOTMUCH_DATABASE_MODE_WRITABLE) {
+   notmuch->xapian_db = new Xapian::WritableDatabase (xapian_path,
+  
Xapian::DB_CREATE_OR_OPEN);
+   } else {
+   notmuch->xapian_db = new Xapian::Database (xapian_path);
+   }
notmuch->query_parser = new Xapian::QueryParser;
notmuch->term_gen = new Xapian::TermGenerator;
notmuch->term_gen->set_stemmer (Xapian::Stem ("english"));
@@ -521,7 +530,8 @@ notmuch_database_open (const char *path)
 void
 notmuch_database_close (notmuch_database_t *notmuch)
 {
-notmuch->xapian_db->flush ();
+if (notmuch->mode == NOTMUCH_DATABASE_MODE_WRITABLE)
+   (static_cast  (notmuch->xapian_db))->flush 
();

 delete notmuch->term_gen;
 delete notmuch->query_parser;
@@ -567,11 +577,18 @@ notmuch_database_set_timestamp (notmuch_database_t 
*notmuch,
const char *key, time_t timestamp)
 {
 Xapian::Document doc;
+Xapian::WritableDatabase *db;
 unsigned int doc_id;
 notmuch_private_status_t status;
 notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;
 char *db_key = NULL;

+if (notmuch->mode == NOTMUCH_DATABASE_MODE_READONLY) {
+   fprintf (stderr, "Attempted to update a read-only database.\n");
+   return NOTMUCH_STATUS_READONLY_DATABASE;
+}
+
+db = static_cast  (notmuch->xapian_db);
 db_key = timestamp_db_key (key);

 try {
@@ -586,9 +603,9 @@ notmuch_database_set_timestamp (notmuch_database_t *notmuch,
doc.add_term (term);
talloc_free (term);

-   notmuch->xapian_db->add_document (doc);
+   db->add_document (doc);
} else {
-   notmuch->xapian_db->replace_document (doc_id, doc);
+   db->replace_document (doc_id, doc);
}

 } catch (Xapian::Error ) {
diff --git a/lib/message.cc b/lib/message.cc
index e0b8a8e..7ba06c9 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -168,9 +168,15 @@ _notmuch_message_create_for_message_id (notmuch_database_t 
*notmuch,
 {
 notmuch_message

[notmuch] [PATCH] Permit opening the notmuch database in read-only mode.

2009-11-21 Thread Chris Wilson
We only rarely need to actually open the database for writing, but we
always create a Xapian::WritableDatabase. This has the effect of
preventing searches and like whilst updating the index.

Signed-off-by: Chris Wilson 
Acked-by: Carl Worth 
---
 lib/database-private.h |3 ++-
 lib/database.cc|   31 ---
 lib/message.cc |   15 +--
 lib/notmuch-private.h  |1 +
 lib/notmuch.h  |   13 +++--
 notmuch-dump.c |3 ++-
 notmuch-new.c  |4 +++-
 notmuch-reply.c|3 ++-
 notmuch-restore.c  |3 ++-
 notmuch-search.c   |3 ++-
 notmuch-show.c |3 ++-
 notmuch-tag.c  |3 ++-
 12 files changed, 66 insertions(+), 19 deletions(-)

diff --git a/lib/database-private.h b/lib/database-private.h
index 76e26ce..79c7916 100644
--- a/lib/database-private.h
+++ b/lib/database-private.h
@@ -27,7 +27,8 @@

 struct _notmuch_database {
 char *path;
-Xapian::WritableDatabase *xapian_db;
+notmuch_database_mode_t mode;
+Xapian::Database *xapian_db;
 Xapian::QueryParser *query_parser;
 Xapian::TermGenerator *term_gen;
 };
diff --git a/lib/database.cc b/lib/database.cc
index 207246c..fb38664 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -172,6 +172,8 @@ notmuch_status_to_string (notmuch_status_t status)
return "No error occurred";
 case NOTMUCH_STATUS_OUT_OF_MEMORY:
return "Out of memory";
+case NOTMUCH_STATUS_READONLY_DATABASE:
+   return "The database is read-only";
 case NOTMUCH_STATUS_XAPIAN_EXCEPTION:
return "A Xapian exception occurred";
 case NOTMUCH_STATUS_FILE_ERROR:
@@ -438,7 +440,8 @@ notmuch_database_create (const char *path)
goto DONE;
 }

-notmuch = notmuch_database_open (path);
+notmuch = notmuch_database_open (path,
+NOTMUCH_DATABASE_MODE_WRITABLE);

   DONE:
 if (notmuch_path)
@@ -448,7 +451,8 @@ notmuch_database_create (const char *path)
 }

 notmuch_database_t *
-notmuch_database_open (const char *path)
+notmuch_database_open (const char *path,
+  notmuch_database_mode_t mode)
 {
 notmuch_database_t *notmuch = NULL;
 char *notmuch_path = NULL, *xapian_path = NULL;
@@ -481,9 +485,14 @@ notmuch_database_open (const char *path)
 if (notmuch->path[strlen (notmuch->path) - 1] == '/')
notmuch->path[strlen (notmuch->path) - 1] = '\0';

+notmuch->mode = mode;
 try {
-   notmuch->xapian_db = new Xapian::WritableDatabase (xapian_path,
-  
Xapian::DB_CREATE_OR_OPEN);
+   if (mode == NOTMUCH_DATABASE_MODE_WRITABLE) {
+   notmuch->xapian_db = new Xapian::WritableDatabase (xapian_path,
+  
Xapian::DB_CREATE_OR_OPEN);
+   } else {
+   notmuch->xapian_db = new Xapian::Database (xapian_path);
+   }
notmuch->query_parser = new Xapian::QueryParser;
notmuch->term_gen = new Xapian::TermGenerator;
notmuch->term_gen->set_stemmer (Xapian::Stem ("english"));
@@ -521,7 +530,8 @@ notmuch_database_open (const char *path)
 void
 notmuch_database_close (notmuch_database_t *notmuch)
 {
-notmuch->xapian_db->flush ();
+if (notmuch->mode == NOTMUCH_DATABASE_MODE_WRITABLE)
+   (static_cast  (notmuch->xapian_db))->flush 
();

 delete notmuch->term_gen;
 delete notmuch->query_parser;
@@ -567,11 +577,18 @@ notmuch_database_set_timestamp (notmuch_database_t 
*notmuch,
const char *key, time_t timestamp)
 {
 Xapian::Document doc;
+Xapian::WritableDatabase *db;
 unsigned int doc_id;
 notmuch_private_status_t status;
 notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;
 char *db_key = NULL;

+if (notmuch->mode == NOTMUCH_DATABASE_MODE_READONLY) {
+   fprintf (stderr, "Attempted to update a read-only database.\n");
+   return NOTMUCH_STATUS_READONLY_DATABASE;
+}
+
+db = static_cast  (notmuch->xapian_db);
 db_key = timestamp_db_key (key);

 try {
@@ -586,9 +603,9 @@ notmuch_database_set_timestamp (notmuch_database_t *notmuch,
doc.add_term (term);
talloc_free (term);

-   notmuch->xapian_db->add_document (doc);
+   db->add_document (doc);
} else {
-   notmuch->xapian_db->replace_document (doc_id, doc);
+   db->replace_document (doc_id, doc);
}

 } catch (Xapian::Error ) {
diff --git a/lib/message.cc b/lib/message.cc
index e0b8a8e..7ba06c9 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -168,9 +168,15 @@ _notmuch_message_create_for_message_id (notmuch_database_t 
*notmuch,
 {
 notmuch_message_t *message;
 Xapian::Document doc;
+Xapian::Writ

[notmuch] [PATCH] Makefile: Magic silent rules.

2009-11-21 Thread Chris Wilson
Use the facilities of GNU make to create a magic function that will
on the first invocation print a description of how to enable verbose
compile lines and then print the quiet rule.

Signed-off-by: Chris Wilson 
Signed-off-by: Carl Worth 
Cc: Mikhail Gusarov 
---
 Makefile   |   22 +++---
 Makefile.local |4 ++--
 lib/Makefile.local |2 +-
 3 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile
index 3fedcf1..77e70ed 100644
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,10 @@
 WARN_FLAGS=-Wall -Wextra -Wmissing-declarations -Wwrite-strings -Wswitch-enum
 CFLAGS=-O2

+# Additional programs that are used during the compilation process.
+EMACS ?= emacs
+GZIP ?= gzip
+
 # Additional flags that we will append to whatever the user set.
 # These aren't intended for the user to manipulate.
 extra_cflags := $(shell pkg-config --cflags glib-2.0 gmime-2.4 talloc)
@@ -31,14 +35,26 @@ include lib/Makefile.local
 # And get user settings from the output of configure
 include Makefile.config

+# The user has not set any verbosity, default to quiet mode and inform the
+# user how to enable verbose compiles.
+ifeq ($(V),)
+quiet_DOC := "Use \"$(MAKE) V=1\" to see the verbose compile lines.\n"
+quiet = @echo $(quiet_DOC)$(eval quiet_DOC:=)"  $1 $@"; $($1)
+endif
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @echo "  $1$@"; $($1)
+endif
+# Otherwise, print the full command line.
+
 %.o: %.cc $(all_deps)
-   $(CXX) -c $(CXXFLAGS) $< -o $@
+   $(call quiet,CXX) -c $(CXXFLAGS) $< -o $@

 %.o: %.c $(all_deps)
-   $(CC) -c $(CFLAGS) $< -o $@
+   $(call quiet,CC) -c $(CFLAGS) $< -o $@

 %.elc: %.el
-   emacs -batch -f batch-byte-compile $<
+   $(call quiet,EMACS) -batch -f batch-byte-compile $<

 .deps/%.d: %.c $(all_deps)
@set -e; rm -f $@; mkdir -p $$(dirname $@) ; \
diff --git a/Makefile.local b/Makefile.local
index 3c99624..5fd5d4f 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -20,10 +20,10 @@ notmuch_client_srcs =   \

 notmuch_client_modules = $(notmuch_client_srcs:.c=.o)
 notmuch: $(notmuch_client_modules) lib/notmuch.a
-   $(CXX) $^ $(LDFLAGS) -o $@
+   $(call quiet,CXX) $^ $(LDFLAGS) -o $@

 notmuch.1.gz: notmuch.1
-   gzip --stdout notmuch.1 > notmuch.1.gz
+   $(call quiet,GZIP) --stdout $^ > $@

 install: all notmuch.1.gz
for d in $(DESTDIR)$(prefix)/bin/ $(DESTDIR)$(prefix)/share/man/man1 \
diff --git a/lib/Makefile.local b/lib/Makefile.local
index 79f7b0b..a7562c9 100644
--- a/lib/Makefile.local
+++ b/lib/Makefile.local
@@ -18,7 +18,7 @@ libnotmuch_cxx_srcs = \

 libnotmuch_modules = $(libnotmuch_c_srcs:.c=.o) $(libnotmuch_cxx_srcs:.cc=.o)
 $(dir)/notmuch.a: $(libnotmuch_modules)
-   $(AR) rcs $@ $^
+   $(call quiet,AR) rcs $@ $^

 SRCS  := $(SRCS) $(libnotmuch_c_srcs) $(libnotmuch_cxx_srcs)
 CLEAN := $(CLEAN) $(libnotmuch_modules) $(dir)/notmuch.a
-- 
1.6.5.3



[notmuch] [PATCH] Makefile: Magic silent rules.

2009-11-21 Thread Chris Wilson
Use the facilities of GNU make to create a magic function that will
on the first invocation print a description of how to enable verbose
compile lines and then print the quiet rule.

Signed-off-by: Chris Wilson 
Signed-off-by: Carl Worth 
Cc: Mikhail Gusarov 
---
 Makefile   |   18 +++---
 Makefile.local |2 +-
 lib/Makefile.local |2 +-
 3 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/Makefile b/Makefile
index 0411cbb..96fcdd5 100644
--- a/Makefile
+++ b/Makefile
@@ -28,14 +28,26 @@ include lib/Makefile.local
 # And get user settings from the output of configure
 include Makefile.config

+# The user has not set any verbosity, default to quiet mode and inform the
+# user how to enable verbose compiles.
+ifeq ($(V),)
+quiet_DOC := "Use \"$(MAKE) V=1\" to see the verbose compile lines.\n"
+quiet = @echo $(quiet_DOC)$(eval quiet_DOC:=)"  $1 $@";
+endif
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @echo "  $1$@";
+endif
+# Otherwise, print the full command line.
+
 %.o: %.cc
-   $(CXX) -c $(CFLAGS) $(CXXFLAGS) $< -o $@
+   $(call quiet,CXX) $(CXX) -c $(CFLAGS) $(CXXFLAGS) $< -o $@

 %.o: %.c
-   $(CC) -c $(CFLAGS) $< -o $@
+   $(call quiet,CC) $(CC) -c $(CFLAGS) $< -o $@

 %.elc: %.el
-   emacs -batch -f batch-byte-compile $<
+   $(call quiet,EMACS) emacs -batch -f batch-byte-compile $<

 .deps/%.d: %.c
@set -e; rm -f $@; mkdir -p $$(dirname $@) ; \
diff --git a/Makefile.local b/Makefile.local
index ecd4ceb..115de0e 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -20,7 +20,7 @@ notmuch_client_srcs = \

 notmuch_client_modules = $(notmuch_client_srcs:.c=.o)
 notmuch: $(notmuch_client_modules) lib/notmuch.a
-   $(CXX) $^ $(LDFLAGS) -o $@
+   $(call quiet,CXX) $(CXX) $^ $(LDFLAGS) -o $@

 notmuch.1.gz: notmuch.1
gzip --stdout notmuch.1 > notmuch.1.gz
diff --git a/lib/Makefile.local b/lib/Makefile.local
index 79f7b0b..f635da7 100644
--- a/lib/Makefile.local
+++ b/lib/Makefile.local
@@ -18,7 +18,7 @@ libnotmuch_cxx_srcs = \

 libnotmuch_modules = $(libnotmuch_c_srcs:.c=.o) $(libnotmuch_cxx_srcs:.cc=.o)
 $(dir)/notmuch.a: $(libnotmuch_modules)
-   $(AR) rcs $@ $^
+   $(call quiet,AR) $(AR) rcs $@ $^

 SRCS  := $(SRCS) $(libnotmuch_c_srcs) $(libnotmuch_cxx_srcs)
 CLEAN := $(CLEAN) $(libnotmuch_modules) $(dir)/notmuch.a
-- 
1.6.5.3



[notmuch] Recommended Coding Style?

2009-11-20 Thread Chris Wilson
Excerpts from Jan Janak's message of Fri Nov 20 15:08:31 + 2009:
> Is there any recommended coding style for the C/C++ code in notmuch?

My prediction is that Carl will go with something close to what he wrote
for Cairo:

  http://cgit.freedesktop.org/cairo/tree/CODING_STYLE

He may or may not change to a more kernel style, but he definitely will
not mandate 3-space indents. ;-)
-ickle
-- 
Chris Wilson, Intel Open Source Technology Centre


[notmuch] [PATCH 2/2] reply: Pointer mismatch.

2009-11-18 Thread Chris Wilson
Apparently typeof (size_t) != unsigned int on my x86-64.
---
 notmuch-reply.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index 4a4a782..344b6e3 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -78,7 +78,7 @@ address_is_users (const char *address, notmuch_config_t 
*config)
 {
 const char *primary;
 char **other;
-unsigned int i, other_len;
+size_t i, other_len;

 primary = notmuch_config_get_user_primary_email (config);
 if (strcmp (primary, address) == 0)
-- 
1.6.5.2



[notmuch] [PATCH 1/2] Makefile: evaluate pkg-config once

2009-11-18 Thread Chris Wilson
Currently the same `pkg-config ...` is executed for every target, so
just store the results in a variable.
---
 Makefile |9 +
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/Makefile b/Makefile
index 96aaa73..023b2ec 100644
--- a/Makefile
+++ b/Makefile
@@ -4,15 +4,16 @@ CFLAGS=-O2

 # Additional flags that we will append to whatever the user set.
 # These aren't intended for the user to manipulate.
-extra_cflags = `pkg-config --cflags glib-2.0 gmime-2.4 talloc`
-extra_cxxflags = `xapian-config --cxxflags`
+extra_cflags := $(shell pkg-config --cflags glib-2.0 gmime-2.4 talloc)
+extra_cxxflags := $(shell xapian-config --cxxflags)

 # Now smash together user's values with our extra values
 override CFLAGS += $(WARN_FLAGS) $(extra_cflags)
 override CXXFLAGS += $(WARN_FLAGS) $(extra_cflags) $(extra_cxxflags)

-override LDFLAGS += `pkg-config --libs glib-2.0 gmime-2.4 talloc` \
-   `xapian-config --libs`
+override LDFLAGS += \
+   $(shell pkg-config --libs glib-2.0 gmime-2.4 talloc) \
+   $(shell xapian-config --libs)

 # Include our local Makefile.local first so that its first target is default
 include Makefile.local
-- 
1.6.5.2