X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=database.cc;h=31afe7cc147afdc3098e8599eb57337b7c7b785d;hp=efc3876205b79de6469373533988af12ca6f354e;hb=65baa4f4e7fc401e5af742b491a3bc0784f2cdf7;hpb=45f0d7bcab72ff6b8375804d3e518f961bd9a96f diff --git a/database.cc b/database.cc index efc38762..31afe7cc 100644 --- a/database.cc +++ b/database.cc @@ -18,22 +18,16 @@ * Author: Carl Worth */ -#include "notmuch-private.h" +#include "database-private.h" #include #include -#include /* g_strdup_printf, g_free, GHashTable */ +#include /* 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); - return notmuch_database_open (path); + DONE: + if (notmuch_path) + free (notmuch_path); + if (local_path) + free (local_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,42 +490,45 @@ 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; const char *refs, *in_reply_to, *date, *header; + const char *from, *to, *subject; char *message_id; time_t time_value; unsigned int i; - message = notmuch_message_open (filename); + message = notmuch_message_file_open (filename); - notmuch_message_restrict_headers (message, - "references", - "in-reply-to", - "message-id", - "date", - (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 @@ -547,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) { @@ -559,22 +577,36 @@ 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)); - db->add_document (doc); + 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_file_close (message); + return NOTMUCH_STATUS_FILE_NOT_EMAIL; + } else { + db->add_document (doc); + } } catch (const Xapian::Error &error) { fprintf (stderr, "A Xapian exception occurred: %s.\n", error.get_msg().c_str()); return NOTMUCH_STATUS_XAPIAN_EXCEPTION; } - notmuch_message_close (message); + notmuch_message_file_close (message); return NOTMUCH_STATUS_SUCCESS; }