[PATCH] notmuch new: Support for conversion of spool subdirectories into tags

classic Classic list List threaded Threaded
3 messages Options
Jan Janak-2 Jan Janak-2
Reply | Threaded
Open this post in threaded view
|

[PATCH] notmuch new: Support for conversion of spool subdirectories into tags

This patch makes it possible to convert subdirectory names inside the
spool directory into message tags. Messages stored in subdirectory
"foo" will be marked with tag "foo". Message duplicates found in several
subdirectories will be given one tag per subdirectory.

This feature can be used to synchronize notmuch's tags with with gmail
tags, for example. Gmail IMAP servers convert tags to IMAP
subdirectories and those subdirectories can be converted back to tags
in notmuch.

The patch modifies notmuch_database_add_message function to return a
pointer to the message even if a message duplicate was found in the
database. This is needed if we want to add a tag for each subdirectory
in which a message duplicate was found.

In addition to that, it makes the pointer to notmuch_config_t global
(previously it was a local variable in notmuch_new_command). The
configuration data structure is used by the function which converts
subdirectory names to tags.

Finally, there is a new function called subdir_to_tag. The function
extracts the name of the subdirectory inside the spool from the full
path of the message (also removing Maildir's cur,dir,and tmp
subdirectories) and adds it as a new tag to the message.

Signed-off-by: Jan Janak <[hidden email]>
---
 lib/database.cc |    3 +-
 notmuch-new.c   |   74 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 74 insertions(+), 3 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 3c8d626..f7799d2 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -949,7 +949,8 @@ notmuch_database_add_message (notmuch_database_t *notmuch,
 
   DONE:
     if (message) {
- if (ret == NOTMUCH_STATUS_SUCCESS && message_ret)
+ if ((ret == NOTMUCH_STATUS_SUCCESS ||
+ ret == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) && message_ret)
     *message_ret = message;
  else
     notmuch_message_destroy (message);
diff --git a/notmuch-new.c b/notmuch-new.c
index 83a05ba..d94ce16 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -19,6 +19,9 @@
  */
 
 #include "notmuch-client.h"
+#include <libgen.h>
+
+static notmuch_config_t *config = 0;
 
 static volatile sig_atomic_t do_add_files_print_progress = 0;
 
@@ -45,6 +48,69 @@ tag_inbox_and_unread (notmuch_message_t *message)
     notmuch_message_add_tag (message, "unread");
 }
 
+/*
+ * Extracts the sub-directory from the filename and adds it as a new tag to
+ * the message. The filename must begin with the database directory configured
+ * in the configuration file. This prefix is then removed. If the remaining
+ * sub-directory ends with one of the Maildir special directories (/tmp, /new,
+ * /cur) then they are removed as well. If there is anything left then the
+ * function adds it as a new tag to the message.
+ *
+ * The function does nothing if it cannot extract a sub-directory from
+ * filename.
+ */
+static void
+subdir_to_tag (char* filename, notmuch_message_t *message)
+{
+ const char* db_path;
+ char *msg_dir, *tmp;
+ int db_path_len, msg_dir_len;
+
+ if (config == NULL) return;
+    db_path = notmuch_config_get_database_path (config);
+ if (db_path == NULL) return;
+ db_path_len = strlen(db_path);
+
+ /* Make a copy of the string as dirname may need to modify it. */
+ tmp = talloc_strdup(message, filename);
+ msg_dir = dirname(tmp);
+ msg_dir_len = strlen(msg_dir);
+
+ /* If msg_dir starts with db_path, remove it, including the / which delimits
+ * it from the rest of the directory name. */
+ if (db_path_len < msg_dir_len &&
+ !strncmp(db_path, msg_dir, db_path_len)) {
+ msg_dir += db_path_len + 1;
+ msg_dir_len -= db_path_len + 1;
+ } else {
+ /* If we get here, either the message filename is not inside the
+ * database directory configured in the configuration file, or it is a
+ * file in the root directory of the database. Either way we just skip
+ * it because we do not know how to convert it to a meaningful
+ * subdirectory string that we could add as tag. */
+ goto out;
+ }
+
+ /* Special conditioning for Maildirs. If the remainder of the directory
+ * name ends with /new, /cur, or /tmp then remove it. */
+ if ((msg_dir_len >= 4) &&
+ (!strncmp(msg_dir + msg_dir_len - 4, "/new", 4) ||
+ !strncmp(msg_dir + msg_dir_len - 4, "/cur", 4) ||
+ !strncmp(msg_dir + msg_dir_len - 4, "/tmp", 4))) {
+ msg_dir[msg_dir_len - 4] = '\0';
+ }
+
+ /* If, after all the modifications, we still have a subdirectory, add it
+ * as tag. */
+ if (strlen(msg_dir)) {
+ notmuch_message_add_tag (message, msg_dir);
+ }
+
+out:
+ talloc_free(tmp);
+}
+
+
 static void
 add_files_print_progress (add_files_state_t *state)
 {
@@ -186,10 +252,15 @@ add_files_recursive (notmuch_database_t *notmuch,
     case NOTMUCH_STATUS_SUCCESS:
  state->added_messages++;
  tag_inbox_and_unread (message);
+ subdir_to_tag(next, message);
  break;
     /* Non-fatal issues (go on to next file) */
     case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:
-        /* Stay silent on this one. */
+        /* Stay silent on this one. The message already exists in the
+ * database, that means we may have found a duplicate in
+ * another directory. If that's the case then we add another
+ * tag to the message with the sub-directory. */
+ subdir_to_tag(next, message);
  break;
     case NOTMUCH_STATUS_FILE_NOT_EMAIL:
  fprintf (stderr, "Note: Ignoring non-mail file: %s\n",
@@ -386,7 +457,6 @@ int
 notmuch_new_command (void *ctx,
      unused (int argc), unused (char *argv[]))
 {
-    notmuch_config_t *config;
     notmuch_database_t *notmuch;
     add_files_state_t add_files_state;
     double elapsed;
--
1.6.3.3


Carl Worth-2 Carl Worth-2
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] notmuch new: Support for conversion of spool subdirectories into tags

On Wed, 18 Nov 2009 05:57:03 +0100, Jan Janak <[hidden email]> wrote:
> This patch makes it possible to convert subdirectory names inside the
> spool directory into message tags. Messages stored in subdirectory
> "foo" will be marked with tag "foo". Message duplicates found in several
> subdirectories will be given one tag per subdirectory.

Hi Jan,

I just pushed out a patch from Aneesh for similar functionality, but
with a simpler implementation.

One thing that patch loses is the addition of multiple tags when a
message appears in multiple directories. Would you like to code up that
feature on top of the current code?

-Carl

Jan Janak-2 Jan Janak-2
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] notmuch new: Support for conversion of spool subdirectories into tags

On Sat, Nov 21, 2009 at 7:44 PM, Carl Worth <[hidden email]> wrote:

> On Wed, 18 Nov 2009 05:57:03 +0100, Jan Janak <[hidden email]> wrote:
>> This patch makes it possible to convert subdirectory names inside the
>> spool directory into message tags. Messages stored in subdirectory
>> "foo" will be marked with tag "foo". Message duplicates found in several
>> subdirectories will be given one tag per subdirectory.
>
> Hi Jan,
>
> I just pushed out a patch from Aneesh for similar functionality, but
> with a simpler implementation.
>
> One thing that patch loses is the addition of multiple tags when a
> message appears in multiple directories. Would you like to code up that
> feature on top of the current code?

Looking at the commit log history, I noticed that you reverted the
commit, so I guess this question is no more relevant.

By the way, although I provided a similar patch some time ago, I agree
that it is better not to have this hard-wired in 'notmuch-new'. It
helped me with the initial import, but since then I have been trying
to get it working with a script run after 'notmuch-new'.

   -- Jan