]> git.notmuchmail.org Git - notmuch/blobdiff - notmuch.c
add_message: Add an optional parameter for getting the just-added message.
[notmuch] / notmuch.c
index ef93ded9b3a848297e1d72c960801eb528a48500..f620f58dfe8aadcbcbfe0bd2186996c9fbf626c6 100644 (file)
--- a/notmuch.c
+++ b/notmuch.c
@@ -41,8 +41,6 @@
 
 #include <talloc.h>
 
-#include <glib.h> /* g_strdup_printf */
-
 #define unused(x) x __attribute__ ((unused))
 
 /* There's no point in continuing when we've detected that we've done
@@ -69,6 +67,8 @@ typedef struct command {
     const char *usage;
 } command_t;
 
+typedef void (*add_files_callback_t) (notmuch_message_t *message);
+
 typedef struct {
     int ignore_read_only_directories;
     int saw_read_only_directory;
@@ -77,6 +77,8 @@ typedef struct {
     int processed_files;
     int added_messages;
     struct timeval tv_start;
+
+    add_files_callback_t callback;
 } add_files_state_t;
 
 static void
@@ -178,6 +180,7 @@ add_files_recursive (notmuch_database_t *notmuch,
     char *next = NULL;
     time_t path_mtime, path_dbtime;
     notmuch_status_t status, ret = NOTMUCH_STATUS_SUCCESS;
+    notmuch_message_t *message, **closure;
 
     /* If we're told to, we bail out on encountering a read-only
      * directory, (with this being a clear clue from the user to
@@ -236,7 +239,7 @@ add_files_recursive (notmuch_database_t *notmuch,
            continue;
        }
 
-       next = g_strdup_printf ("%s/%s", path, entry->d_name);
+       next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name);
 
        if (stat (next, st)) {
            fprintf (stderr, "Error reading %s: %s\n",
@@ -251,11 +254,19 @@ add_files_recursive (notmuch_database_t *notmuch,
            if (st->st_mtime > path_dbtime) {
                state->processed_files++;
 
-               status = notmuch_database_add_message (notmuch, next);
+               if (state->callback)
+                   closure = &message;
+               else
+                   closure = NULL;
+
+               status = notmuch_database_add_message (notmuch, next, closure);
                switch (status) {
                    /* success */
                    case NOTMUCH_STATUS_SUCCESS:
                        state->added_messages++;
+                       if (state->callback)
+                           (state->callback) (message);
+                       notmuch_message_destroy (message);
                        break;
                    /* Non-fatal issues (go on to next file) */
                    case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:
@@ -267,10 +278,16 @@ add_files_recursive (notmuch_database_t *notmuch,
                        break;
                    /* Fatal issues. Don't process anymore. */
                    case NOTMUCH_STATUS_XAPIAN_EXCEPTION:
-                       fprintf (stderr, "A Xapian error was encountered. Halting processing.\n");
+                   case NOTMUCH_STATUS_OUT_OF_MEMORY:
+                       fprintf (stderr, "Error: %s. Halting processing.\n",
+                                notmuch_status_to_string (status));
                        ret = status;
                        goto DONE;
                    default:
+                   case NOTMUCH_STATUS_FILE_ERROR:
+                   case NOTMUCH_STATUS_NULL_POINTER:
+                   case NOTMUCH_STATUS_TAG_TOO_LONG:
+                   case NOTMUCH_STATUS_LAST_STATUS:
                        INTERNAL_ERROR ("add_message returned unexpected value: %d",  status);
                        goto DONE;
                }
@@ -283,7 +300,7 @@ add_files_recursive (notmuch_database_t *notmuch,
                ret = status;
        }
 
-       free (next);
+       talloc_free (next);
        next = NULL;
     }
 
@@ -293,7 +310,7 @@ add_files_recursive (notmuch_database_t *notmuch,
 
   DONE:
     if (next)
-       free (next);
+       talloc_free (next);
     if (entry)
        free (entry);
     if (dir)
@@ -336,7 +353,7 @@ static void
 count_files (const char *path, int *count)
 {
     DIR *dir;
-    struct dirent *entry, *e;
+    struct dirent *e, *entry = NULL;
     int entry_length;
     int err;
     char *next;
@@ -347,7 +364,7 @@ count_files (const char *path, int *count)
     if (dir == NULL) {
        fprintf (stderr, "Warning: failed to open directory %s: %s\n",
                 path, strerror (errno));
-       return;
+       goto DONE;
     }
 
     entry_length = offsetof (struct dirent, d_name) +
@@ -360,7 +377,7 @@ count_files (const char *path, int *count)
            fprintf (stderr, "Error reading directory: %s\n",
                     strerror (errno));
            free (entry);
-           return;
+           goto DONE;
        }
 
        if (e == NULL)
@@ -378,7 +395,12 @@ count_files (const char *path, int *count)
            continue;
        }
 
-       next = g_strdup_printf ("%s/%s", path, entry->d_name);
+       if (asprintf (&next, "%s/%s", path, entry->d_name) == -1) {
+           next = NULL;
+           fprintf (stderr, "Error descending from %s to %s: Out of memory\n",
+                    path, entry->d_name);
+           continue;
+       }
 
        stat (next, &st);
 
@@ -395,7 +417,9 @@ count_files (const char *path, int *count)
        free (next);
     }
 
-    free (entry);
+  DONE:
+    if (entry)
+       free (entry);
 
     closedir (dir);
 }
@@ -484,6 +508,7 @@ setup_command (unused (int argc), unused (char *argv[]))
     add_files_state.total_files = count;
     add_files_state.processed_files = 0;
     add_files_state.added_messages = 0;
+    add_files_state.callback = NULL;
     gettimeofday (&add_files_state.tv_start, NULL);
 
     ret = add_files (notmuch, mail_directory, &add_files_state);
@@ -526,6 +551,13 @@ setup_command (unused (int argc), unused (char *argv[]))
     return ret;
 }
 
+static void
+tag_inbox_and_unread (notmuch_message_t *message)
+{
+    notmuch_message_add_tag (message, "inbox");
+    notmuch_message_add_tag (message, "unread");
+}
+
 static int
 new_command (unused (int argc), unused (char *argv[]))
 {
@@ -549,6 +581,7 @@ new_command (unused (int argc), unused (char *argv[]))
     add_files_state.total_files = 0;
     add_files_state.processed_files = 0;
     add_files_state.added_messages = 0;
+    add_files_state.callback = tag_inbox_and_unread;
     gettimeofday (&add_files_state.tv_start, NULL);
 
     ret = add_files (notmuch, mail_directory, &add_files_state);
@@ -602,8 +635,8 @@ search_command (int argc, char *argv[])
     void *local = talloc_new (NULL);
     notmuch_database_t *notmuch = NULL;
     notmuch_query_t *query;
-    notmuch_results_t *results;
-    notmuch_message_t *message;
+    notmuch_thread_results_t *results;
+    notmuch_thread_t *thread;
     notmuch_tags_t *tags;
     char *query_str;
     int i;
@@ -632,30 +665,31 @@ search_command (int argc, char *argv[])
        goto DONE;
     }
 
-    for (results = notmuch_query_search (query);
-        notmuch_results_has_more (results);
-        notmuch_results_advance (results))
+    for (results = notmuch_query_search_threads (query);
+        notmuch_thread_results_has_more (results);
+        notmuch_thread_results_advance (results))
     {
        int first = 1;
-       message = notmuch_results_get (results);
 
-       printf ("%s (", notmuch_message_get_message_id (message));
+       thread = notmuch_thread_results_get (results);
 
-       for (tags = notmuch_message_get_tags (message);
+       printf ("%s %s",
+               notmuch_thread_get_thread_id (thread),
+               notmuch_thread_get_subject (thread));
+
+       printf (" (");
+       for (tags = notmuch_thread_get_tags (thread);
             notmuch_tags_has_more (tags);
             notmuch_tags_advance (tags))
        {
            if (! first)
                printf (" ");
-
            printf ("%s", notmuch_tags_get (tags));
-
            first = 0;
        }
-
        printf (")\n");
 
-       notmuch_message_destroy (message);
+       notmuch_thread_destroy (thread);
     }
 
     notmuch_query_destroy (query);
@@ -678,10 +712,10 @@ show_command (unused (int argc), unused (char *argv[]))
 static int
 dump_command (int argc, char *argv[])
 {
-    FILE *output;
+    FILE *output = NULL;
     notmuch_database_t *notmuch = NULL;
     notmuch_query_t *query;
-    notmuch_results_t *results;
+    notmuch_message_results_t *results;
     notmuch_message_t *message;
     notmuch_tags_t *tags;
     int ret = 0;
@@ -713,12 +747,12 @@ dump_command (int argc, char *argv[])
 
     notmuch_query_set_sort (query, NOTMUCH_SORT_MESSAGE_ID);
 
-    for (results = notmuch_query_search (query);
-        notmuch_results_has_more (results);
-        notmuch_results_advance (results))
+    for (results = notmuch_query_search_messages (query);
+        notmuch_message_results_has_more (results);
+        notmuch_message_results_advance (results))
     {
        int first = 1;
-       message = notmuch_results_get (results);
+       message = notmuch_message_results_get (results);
 
        fprintf (output,
                 "%s (", notmuch_message_get_message_id (message));
@@ -745,7 +779,7 @@ dump_command (int argc, char *argv[])
   DONE:
     if (notmuch)
        notmuch_database_close (notmuch);
-    if (output != stdout)
+    if (output && output != stdout)
        fclose (output);
 
     return ret;
@@ -754,7 +788,7 @@ dump_command (int argc, char *argv[])
 static int
 restore_command (int argc, char *argv[])
 {
-    FILE *input;
+    FILE *input = NULL;
     notmuch_database_t *notmuch = NULL;
     char *line = NULL;
     size_t line_size;
@@ -855,6 +889,8 @@ restore_command (int argc, char *argv[])
        free (line);
     if (notmuch)
        notmuch_database_close (notmuch);
+    if (input && input != stdin)
+       fclose (input);
 
     return ret;
 }
@@ -866,10 +902,13 @@ command_t commands[] = {
       "\t\tthe setup command has not previously been completed." },
     { "new", new_command,
       "Find and import any new messages.\n\n"
-      "\t\tScans all sub-directories of the database, adding new files\n"
-      "\t\tthat are found. Note: \"notmuch new\" will skip any\n"
-      "\t\tread-only directories, so you can use that to mark\n"
-      "\t\tdirectories that will not receive any new mail."},
+      "\t\tScans all sub-directories of the database, adding new messages\n"
+      "\t\tthat are found. Each new message will be tagges as both\n"
+      "\t\t\"inbox\" and \"unread\".\n"
+      "\n"
+      "\t\tNote: \"notmuch new\" will skip any read-only directories,\n"
+      "\t\tso you can use that to mark tdirectories that will not\n"
+      "\t\treceive any new mail (and make \"notmuch new\" faster)." },
     { "search", search_command,
       "<search-term> [...]\n\n"
       "\t\tSearch for threads matching the given search terms.\n"
@@ -932,11 +971,11 @@ main (int argc, char *argv[])
        strcmp (argv[1], "--help") == 0)
     {
        fprintf (stderr, "The notmuch mail system.\n\n");
+       usage ();
+       return 0;
     } else {
        fprintf (stderr, "Error: Unknown command '%s'\n\n", argv[1]);
+       usage ();
+       return 1;
     }
-    usage ();
-    exit (1);
-
-    return 0;
 }