]> git.notmuchmail.org Git - notmuch/blobdiff - database.cc
notmuch dump: Fix the sorting of results.
[notmuch] / database.cc
index 70f80f9fccf257ebf7d27cf7d1b154afc1e02f70..31afe7cc147afdc3098e8599eb57337b7c7b785d 100644 (file)
  * Author: Carl Worth <cworth@cworth.org>
  */
 
-#include "notmuch-private.h"
+#include "database-private.h"
 
 #include <iostream>
 
 #include <xapian.h>
 
-#include <glib.h> /* g_strdup_printf, g_free, GHashTable */
+#include <glib.h> /* g_strdup_printf, g_free, GPtrArray, GHashTable */
 
 using namespace std;
 
-struct _notmuch_database {
-    char *path;
-    Xapian::WritableDatabase *xapian_db;
-    Xapian::TermGenerator *term_gen;
-};
-
 #define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr[0]))
 
 /* Xapian complains if we provide a term longer than this. */
@@ -73,15 +67,6 @@ prefix_t BOOLEAN_PREFIX[] = {
     { "ref", "R" }
 };
 
-/* Similarly, these value numbers are also chosen to be sup
- * compatible. */
-
-typedef enum {
-    NOTMUCH_VALUE_MESSAGE_ID = 0,
-    NOTMUCH_VALUE_THREAD = 1,
-    NOTMUCH_VALUE_DATE = 2
-} notmuch_value_t;
-
 static const char *
 find_prefix (const char *name)
 {
@@ -379,24 +364,38 @@ parse_references (GPtrArray *array,
     }
 }
 
+char *
+notmuch_database_default_path (void)
+{
+    if (getenv ("NOTMUCH_BASE"))
+       return strdup (getenv ("NOTMUCH_BASE"));
+
+    return g_strdup_printf ("%s/mail", getenv ("HOME"));
+}
+
 notmuch_database_t *
 notmuch_database_create (const char *path)
 {
-    char *notmuch_path;
+    notmuch_database_t *notmuch = NULL;
+    char *notmuch_path = NULL;
     struct stat st;
     int err;
+    char *local_path = NULL;
+
+    if (path == NULL)
+       path = local_path = notmuch_database_default_path ();
 
     err = stat (path, &st);
     if (err) {
        fprintf (stderr, "Error: Cannot create database at %s: %s.\n",
                 path, strerror (errno));
-       return NULL;
+       goto DONE;
     }
 
     if (! S_ISDIR (st.st_mode)) {
        fprintf (stderr, "Error: Cannot create database at %s: Not a directory.\n",
                 path);
-       return NULL;
+       goto DONE;
     }
 
     notmuch_path = g_strdup_printf ("%s/%s", path, ".notmuch");
@@ -406,35 +405,42 @@ notmuch_database_create (const char *path)
     if (err) {
        fprintf (stderr, "Error: Cannot create directory %s: %s.\n",
                 notmuch_path, strerror (errno));
-       free (notmuch_path);
-       return NULL;
+       goto DONE;
     }
 
-    free (notmuch_path);
+    notmuch = notmuch_database_open (path);
+
+  DONE:
+    if (notmuch_path)
+       free (notmuch_path);
+    if (local_path)
+       free (local_path);
 
-    return notmuch_database_open (path);
+    return notmuch;
 }
 
 notmuch_database_t *
 notmuch_database_open (const char *path)
 {
-    notmuch_database_t *notmuch;
-    char *notmuch_path, *xapian_path;
+    notmuch_database_t *notmuch = NULL;
+    char *notmuch_path = NULL, *xapian_path = NULL;
     struct stat st;
     int err;
+    char *local_path = NULL;
+
+    if (path == NULL)
+       path = local_path = notmuch_database_default_path ();
 
     notmuch_path = g_strdup_printf ("%s/%s", path, ".notmuch");
 
     err = stat (notmuch_path, &st);
     if (err) {
-       fprintf (stderr, "Error: Cannot stat %s: %s\n",
-                notmuch_path, strerror (err));
-       free (notmuch_path);
-       return NULL;
+       fprintf (stderr, "Error opening database at %s: %s\n",
+                notmuch_path, strerror (errno));
+       goto DONE;
     }
 
     xapian_path = g_strdup_printf ("%s/%s", notmuch_path, "xapian");
-    free (notmuch_path);
 
     /* C++ is so nasty in requiring these casts. I'm almost tempted to
      * write a C wrapper for Xapian... */
@@ -444,12 +450,21 @@ notmuch_database_open (const char *path)
     try {
        notmuch->xapian_db = new Xapian::WritableDatabase (xapian_path,
                                                           Xapian::DB_CREATE_OR_OPEN);
+       notmuch->query_parser = new Xapian::QueryParser;
+       notmuch->query_parser->set_default_op (Xapian::Query::OP_AND);
+       notmuch->query_parser->set_database (*notmuch->xapian_db);
     } catch (const Xapian::Error &error) {
        fprintf (stderr, "A Xapian exception occurred: %s\n",
                 error.get_msg().c_str());
     }
     
-    free (xapian_path);
+  DONE:
+    if (local_path)
+       free (local_path);
+    if (notmuch_path)
+       free (notmuch_path);
+    if (xapian_path)
+       free (xapian_path);
 
     return notmuch;
 }
@@ -457,6 +472,7 @@ notmuch_database_open (const char *path)
 void
 notmuch_database_close (notmuch_database_t *notmuch)
 {
+    delete notmuch->query_parser;
     delete notmuch->xapian_db;
     free (notmuch->path);
     free (notmuch);
@@ -474,7 +490,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch,
 {
     Xapian::WritableDatabase *db = notmuch->xapian_db;
     Xapian::Document doc;
-    notmuch_message_t *message;
+    notmuch_message_file_t *message;
 
     GPtrArray *parents, *thread_ids;
 
@@ -485,34 +501,34 @@ notmuch_database_add_message (notmuch_database_t *notmuch,
     time_t time_value;
     unsigned int i;
 
-    message = notmuch_message_open (filename);
+    message = notmuch_message_file_open (filename);
 
-    notmuch_message_restrict_headers (message,
-                                     "date",
-                                     "from",
-                                     "in-reply-to",
-                                     "message-id",
-                                     "references",
-                                     "subject",
-                                     (char *) NULL);
+    notmuch_message_file_restrict_headers (message,
+                                          "date",
+                                          "from",
+                                          "in-reply-to",
+                                          "message-id",
+                                          "references",
+                                          "subject",
+                                          (char *) NULL);
 
     try {
-       doc = Xapian::Document ();
-
        doc.set_data (filename);
 
+       add_term (doc, "type", "mail");
+
        parents = g_ptr_array_new ();
 
-       refs = notmuch_message_get_header (message, "references");
+       refs = notmuch_message_file_get_header (message, "references");
        parse_references (parents, refs);
 
-       in_reply_to = notmuch_message_get_header (message, "in-reply-to");
+       in_reply_to = notmuch_message_file_get_header (message, "in-reply-to");
        parse_references (parents, in_reply_to);
 
        for (i = 0; i < parents->len; i++)
            add_term (doc, "ref", (char *) g_ptr_array_index (parents, i));
 
-       header = notmuch_message_get_header (message, "message-id");
+       header = notmuch_message_file_get_header (message, "message-id");
        if (header) {
            message_id = parse_message_id (header, NULL);
            /* So the header value isn't RFC-compliant, but it's
@@ -550,7 +566,6 @@ notmuch_database_add_message (notmuch_database_t *notmuch,
 
                free (id);
            }
-           g_ptr_array_free (thread_ids, TRUE);
            doc.add_value (NOTMUCH_VALUE_THREAD, thread_id->str);
            g_string_free (thread_id, TRUE);
        } else if (message_id) {
@@ -562,23 +577,25 @@ notmuch_database_add_message (notmuch_database_t *notmuch,
            doc.add_value (NOTMUCH_VALUE_THREAD, thread_id.str);
        }
 
+       g_ptr_array_free (thread_ids, TRUE);
+
        free (message_id);
 
-       date = notmuch_message_get_header (message, "date");
+       date = notmuch_message_file_get_header (message, "date");
        time_value = notmuch_parse_date (date, NULL);
 
        doc.add_value (NOTMUCH_VALUE_DATE,
                       Xapian::sortable_serialise (time_value));
 
-       from = notmuch_message_get_header (message, "from");
-       subject = notmuch_message_get_header (message, "subject");
-       to = notmuch_message_get_header (message, "to");
+       from = notmuch_message_file_get_header (message, "from");
+       subject = notmuch_message_file_get_header (message, "subject");
+       to = notmuch_message_file_get_header (message, "to");
 
        if (from == NULL &&
            subject == NULL &&
            to == NULL)
        {
-           notmuch_message_close (message);
+           notmuch_message_file_close (message);
            return NOTMUCH_STATUS_FILE_NOT_EMAIL;
        } else {
            db->add_document (doc);
@@ -589,7 +606,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch,
        return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
     }
 
-    notmuch_message_close (message);
+    notmuch_message_file_close (message);
 
     return NOTMUCH_STATUS_SUCCESS;
 }