[notmuch] [PATCH] notmuch: Respect maildir message flags

Tim Stoakes notmuch at stoakes.net
Tue Feb 9 19:13:39 PST 2010


Michiel Buddingh'(michiel at michielbuddingh.net)@061209-20:55:
>
...
> A new patch is attached.  Apologies for the rather verbose Maildir
> handling logic, but I couldn't find a way to minimize the calls to
> is_maildir that was both neat and readable.


Hi notmuch-ers,

My apologies for dredging up an old thread. I don't want to restart the
religious war over whether notmuch should respect Maildir flags -
suffice to say that *I* want that, and the patch posted by Michiel
seemed to be the best way to make that happen.

Since it no longer applies cleanly, I've ported it forward to
79d3f9773c58d6fd7113871362687d8cfc0b1a59, to save someone else the
trouble. It works for me, but that's all the testing I've done.

Tim

-- 
Tim Stoakes



---
 notmuch-new.c |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 85 insertions(+), 1 deletions(-)

diff --git a/notmuch-new.c b/notmuch-new.c
index f25c71f..3264653 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -39,6 +39,7 @@ typedef struct {
     int total_files;
     int processed_files;
     int added_messages;
+    int tag_maildir;
     struct timeval tv_start;
 
     _filename_list_t *removed_files;
@@ -169,6 +170,60 @@ _entries_resemble_maildir (struct dirent **entries, int count)
     return 0;
 }
 
+/* Tag new mail according to its Maildir attribute flags.
+ *
+ * Test if the mail file's filename contains any of the
+ * standard Maildir attributes, and translate these to
+ * the corresponding standard notmuch tags.
+ *
+ * If the message is not marked as 'seen', or if no
+ * flags are present, tag as 'inbox, unread'.
+ */
+static void
+derive_tags_from_maildir_flags (notmuch_message_t *message,
+				const char * path)
+{
+    int seen = FALSE;
+    int end_of_flags = FALSE;
+    size_t l = strlen(path);
+
+    /* Non-experimental message flags start with this */
+    char * i = strstr(path, ":2,");
+    i = (i) ? i : strstr(path, "!2,"); /* This format is used on VFAT */
+    if (i != NULL) {
+	i += 3;
+	for (; i < (path + l) && !end_of_flags; i++) {
+	    switch (*i) {
+	    case 'F' :
+		notmuch_message_add_tag (message, "flagged");
+		break;
+	    case 'R': /* replied */
+		notmuch_message_add_tag (message, "answered");
+		break;
+	    case 'D':
+		notmuch_message_add_tag (message, "draft");
+		break;
+	    case 'S': /* seen */
+		seen = TRUE;
+		break;
+	    case 'T': /* trashed */
+		notmuch_message_add_tag (message, "deleted");
+		break;
+	    case 'P': /* passed */
+		notmuch_message_add_tag (message, "forwarded");
+		break;
+	    default:
+		end_of_flags = TRUE;
+		break;
+	    }
+	}
+    }
+
+    if (i == NULL || !seen) {
+	tag_inbox_and_unread (message);
+    }
+}
+
 /* Examine 'path' recursively as follows:
  *
  *   o Ask the filesystem for the mtime of 'path' (fs_mtime)
@@ -222,6 +277,7 @@ add_files_recursive (notmuch_database_t *notmuch,
     notmuch_filenames_t *db_subdirs = NULL;
     struct stat st;
     notmuch_bool_t is_maildir, new_directory;
+    int maildir_detected = -1;
 
     if (stat (path, &st)) {
 	fprintf (stderr, "Error reading directory %s: %s\n",
@@ -301,6 +357,28 @@ add_files_recursive (notmuch_database_t *notmuch,
 	    continue;
 	}
 
+	/* If this directory is a Maildir folder, we need to
+	 * ignore any subdirectories marked tmp/, and scan for
+	 * Maildir attributes on messages contained in the sub-
+	 * directories 'new' and 'cur'. */
+	if (maildir_detected != 0 &&
+	    entry->d_type == DT_DIR &&
+	    ((strcmp (entry->d_name, "tmp") == 0) ||
+	     (strcmp (entry->d_name, "new") == 0) ||
+	     (strcmp (entry->d_name, "cur") == 0))) {
+
+    if (maildir_detected == -1) {
+      maildir_detected = _entries_resemble_maildir(fs_entries, num_fs_entries);
+    }
+    if (maildir_detected == 1) {
+      if (strcmp (entry->d_name, "tmp") == 0) {
+        continue;
+      } else {
+        state->tag_maildir = TRUE;
+      }
+    }
+  }
+
 	next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name);
 	status = add_files_recursive (notmuch, next, state);
 	if (status && ret == NOTMUCH_STATUS_SUCCESS)
@@ -412,7 +490,12 @@ add_files_recursive (notmuch_database_t *notmuch,
 	/* success */
 	case NOTMUCH_STATUS_SUCCESS:
 	    state->added_messages++;
-	    tag_inbox_and_unread (message);
+			if (state->tag_maildir) {
+			    derive_tags_from_maildir_flags (message,
+							    entry->d_name);
+			} else {
+			    tag_inbox_and_unread (message);
+			}
 	    break;
 	/* Non-fatal issues (go on to next file) */
 	case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:
@@ -482,6 +565,7 @@ add_files_recursive (notmuch_database_t *notmuch,
 	status = notmuch_directory_set_mtime (directory, fs_mtime);
 	if (status && ret == NOTMUCH_STATUS_SUCCESS)
 	    ret = status;
+	    state->tag_maildir = FALSE;
     }
 
   DONE:
-- 
1.6.6.1



More information about the notmuch mailing list