]> git.notmuchmail.org Git - notmuch/blobdiff - database.cc
Move find_prefix function from database.cc to message.cc
[notmuch] / database.cc
index 528ae1154b48d9b4428c214355700e96f5123564..b73b806ee8ea79c8a34e9d57aa18d592f943d5fd 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. */
-#define NOTMUCH_MAX_TERM 245
-
-/* These prefix values are specifically chosen to be compatible
- * with sup, (http://sup.rubyforge.org), written by
- * William Morgan <wmorgan-sup@masanjin.net>, and released
- * under the GNU GPL v2.
- */
-
-typedef struct {
-    const char *name;
-    const char *prefix;
-} prefix_t;
-
-prefix_t NORMAL_PREFIX[] = {
-    { "subject", "S" },
-    { "body", "B" },
-    { "from_name", "FN" },
-    { "to_name", "TN" },
-    { "name", "N" },
-    { "attachment", "A" }
-};
-
-prefix_t BOOLEAN_PREFIX[] = {
-    { "type", "K" },
-    { "from_email", "FE" },
-    { "to_email", "TE" },
-    { "email", "E" },
-    { "date", "D" },
-    { "label", "L" },
-    { "source_id", "I" },
-    { "attachment_extension", "O" },
-    { "msgid", "Q" },
-    { "thread", "H" },
-    { "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)
-{
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_SIZE (NORMAL_PREFIX); i++)
-       if (strcmp (name, NORMAL_PREFIX[i].name) == 0)
-           return NORMAL_PREFIX[i].prefix;
-
-    for (i = 0; i < ARRAY_SIZE (BOOLEAN_PREFIX); i++)
-       if (strcmp (name, BOOLEAN_PREFIX[i].name) == 0)
-           return BOOLEAN_PREFIX[i].prefix;
-
-    return "";
-}
-
 /* "128 bits of thread-id ought to be enough for anybody" */
 #define NOTMUCH_THREAD_ID_BITS  128
 #define NOTMUCH_THREAD_ID_DIGITS (NOTMUCH_THREAD_ID_BITS / 4)
@@ -145,7 +75,7 @@ add_term (Xapian::Document doc,
     if (value == NULL)
        return;
 
-    prefix = find_prefix (prefix_name);
+    prefix = _find_prefix (prefix_name);
 
     term = g_strdup_printf ("%s%s", prefix, value);
 
@@ -165,7 +95,7 @@ find_messages_by_term (Xapian::Database *db,
     Xapian::PostingIterator i;
     char *term;
 
-    term = g_strdup_printf ("%s%s", find_prefix (prefix_name), value);
+    term = g_strdup_printf ("%s%s", _find_prefix (prefix_name), value);
 
     *begin = db->postlist_begin (term);
 
@@ -320,6 +250,7 @@ static char *
 parse_message_id (const char *message_id, const char **next)
 {
     const char *s, *end;
+    char *result;
 
     if (message_id == NULL)
        return NULL;
@@ -354,10 +285,23 @@ parse_message_id (const char *message_id, const char **next)
 
     if (end > s && *end == '>')
        end--;
-    if (end > s)
-       return strndup (s, end - s + 1);
-    else
+    if (end <= s)
        return NULL;
+
+    result = strndup (s, end - s + 1);
+
+    /* Finally, collapse any whitespace that is within the message-id
+     * itself. */
+    {
+       char *r;
+       int len;
+
+       for (r = result, len = strlen (r); *r; r++, len--)
+           if (*r == ' ' || *r == '\t')
+               memmove (r, r+1, len);
+    }
+
+    return result;
 }
 
 /* Parse a References header value, putting a copy of each referenced
@@ -450,21 +394,22 @@ notmuch_database_open (const char *path)
 
     err = stat (notmuch_path, &st);
     if (err) {
-       fprintf (stderr, "Error: Cannot stat %s: %s\n",
-                notmuch_path, strerror (err));
+       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");
 
-    /* C++ is so nasty in requiring these casts. I'm almost tempted to
-     * write a C wrapper for Xapian... */
-    notmuch = (notmuch_database_t *) xmalloc (sizeof (notmuch_database_t));
-    notmuch->path = xstrdup (path);
+    notmuch = talloc (NULL, notmuch_database_t);
+    notmuch->path = talloc_strdup (notmuch, 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());
@@ -484,9 +429,9 @@ 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);
+    talloc_free (notmuch);
 }
 
 const char *
@@ -501,7 +446,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;
 
@@ -512,34 +457,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
@@ -577,7 +522,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) {
@@ -589,23 +533,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);
@@ -616,7 +562,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;
 }