diff options
| author | David Bremner <david@tethera.net> | 2016-06-28 16:48:30 +0200 |
|---|---|---|
| committer | David Bremner <david@tethera.net> | 2016-06-28 16:48:30 +0200 |
| commit | 7fe91ddc4f47170724d455e84d5d262410d569f2 (patch) | |
| tree | 4ba841df17c181ab6a785d408c4e5f8316bda9c1 /lib | |
| parent | 148ceed198f98524db8482e212804c5a510d696b (diff) | |
| parent | ea5caecec5c50833a6f5a422e217a71eee6324af (diff) | |
Merge tag 'debian/0.22-1' into jessie-backports
notmuch Debian 0.22-1 upload (same as 0.22)
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/database.cc | 22 | ||||
| -rw-r--r-- | lib/index.cc | 3 | ||||
| -rw-r--r-- | lib/message.cc | 115 | ||||
| -rw-r--r-- | lib/notmuch-private.h | 17 | ||||
| -rw-r--r-- | lib/notmuch.h | 11 | ||||
| -rw-r--r-- | lib/query.cc | 18 |
6 files changed, 162 insertions, 24 deletions
diff --git a/lib/database.cc b/lib/database.cc index 5e86955d..c8c5e261 100644 --- a/lib/database.cc +++ b/lib/database.cc @@ -1635,6 +1635,9 @@ notmuch_database_begin_atomic (notmuch_database_t *notmuch) notmuch->atomic_nesting > 0) goto DONE; + if (notmuch_database_needs_upgrade(notmuch)) + return NOTMUCH_STATUS_UPGRADE_REQUIRED; + try { (static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db))->begin_transaction (false); } catch (const Xapian::Error &error) { @@ -1758,18 +1761,11 @@ _notmuch_database_split_path (void *ctx, slash = path + strlen (path) - 1; /* First, skip trailing slashes. */ - while (slash != path) { - if (*slash != '/') - break; - + while (slash != path && *slash == '/') --slash; - } /* Then, find a slash. */ - while (slash != path) { - if (*slash == '/') - break; - + while (slash != path && *slash != '/') { if (basename) *basename = slash; @@ -1777,12 +1773,8 @@ _notmuch_database_split_path (void *ctx, } /* Finally, skip multiple slashes. */ - while (slash != path) { - if (*slash != '/') - break; - + while (slash != path && *(slash - 1) == '/') --slash; - } if (slash == path) { if (directory) @@ -1791,7 +1783,7 @@ _notmuch_database_split_path (void *ctx, *basename = path; } else { if (directory) - *directory = talloc_strndup (ctx, path, slash - path + 1); + *directory = talloc_strndup (ctx, path, slash - path); } return NOTMUCH_STATUS_SUCCESS; diff --git a/lib/index.cc b/lib/index.cc index e81aa819..f166aefd 100644 --- a/lib/index.cc +++ b/lib/index.cc @@ -377,7 +377,8 @@ _index_mime_part (notmuch_message_t *message, disposition = g_mime_object_get_content_disposition (part); if (disposition && - strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0) + strcasecmp (g_mime_content_disposition_get_disposition (disposition), + GMIME_DISPOSITION_ATTACHMENT) == 0) { const char *filename = g_mime_part_get_filename (GMIME_PART (part)); diff --git a/lib/message.cc b/lib/message.cc index 26b5e76e..68393055 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -728,7 +728,7 @@ _notmuch_message_add_filename (notmuch_message_t *message, * Note: This function does not remove a document from the database, * even if the specified filename is the only filename for this * message. For that functionality, see - * _notmuch_database_remove_message. */ + * notmuch_database_remove_message. */ notmuch_status_t _notmuch_message_remove_filename (notmuch_message_t *message, const char *filename) @@ -1037,20 +1037,90 @@ _notmuch_message_sync (notmuch_message_t *message) message->modified = FALSE; } -/* Delete a message document from the database. */ +/* Delete a message document from the database, leaving a ghost + * message in its place */ notmuch_status_t _notmuch_message_delete (notmuch_message_t *message) { notmuch_status_t status; Xapian::WritableDatabase *db; + const char *mid, *tid, *query_string; + notmuch_message_t *ghost; + notmuch_private_status_t private_status; + notmuch_database_t *notmuch; + notmuch_query_t *query; + unsigned int count = 0; + notmuch_bool_t is_ghost; + + mid = notmuch_message_get_message_id (message); + tid = notmuch_message_get_thread_id (message); + notmuch = message->notmuch; status = _notmuch_database_ensure_writable (message->notmuch); if (status) return status; - db = static_cast <Xapian::WritableDatabase *> (message->notmuch->xapian_db); + db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db); db->delete_document (message->doc_id); - return NOTMUCH_STATUS_SUCCESS; + + /* if this was a ghost to begin with, we are done */ + private_status = _notmuch_message_has_term (message, "type", "ghost", &is_ghost); + if (private_status) + return COERCE_STATUS (private_status, + "Error trying to determine whether message was a ghost"); + if (is_ghost) + return NOTMUCH_STATUS_SUCCESS; + + query_string = talloc_asprintf (message, "thread:%s", tid); + query = notmuch_query_create (notmuch, query_string); + if (query == NULL) + return NOTMUCH_STATUS_OUT_OF_MEMORY; + status = notmuch_query_count_messages_st (query, &count); + if (status) { + notmuch_query_destroy (query); + return status; + } + + if (count > 0) { + /* reintroduce a ghost in its place because there are still + * other active messages in this thread: */ + ghost = _notmuch_message_create_for_message_id (notmuch, mid, &private_status); + if (private_status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) { + private_status = _notmuch_message_initialize_ghost (ghost, tid); + if (! private_status) + _notmuch_message_sync (ghost); + } else if (private_status == NOTMUCH_PRIVATE_STATUS_SUCCESS) { + /* this is deeply weird, and we should not have gotten + into this state. is there a better error message to + return here? */ + status = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID; + } + + notmuch_message_destroy (ghost); + status = COERCE_STATUS (private_status, "Error converting to ghost message"); + } else { + /* the thread is empty; drop all ghost messages from it */ + notmuch_messages_t *messages; + status = _notmuch_query_search_documents (query, + "ghost", + &messages); + if (status == NOTMUCH_STATUS_SUCCESS) { + notmuch_status_t last_error = NOTMUCH_STATUS_SUCCESS; + while (notmuch_messages_valid (messages)) { + message = notmuch_messages_get (messages); + status = _notmuch_message_delete (message); + if (status) /* we'll report the last failure we see; + * if there is more than one failure, we + * forget about previous ones */ + last_error = status; + notmuch_message_destroy (message); + notmuch_messages_move_to_next (messages); + } + status = last_error; + } + } + notmuch_query_destroy (query); + return status; } /* Transform a blank message into a ghost message. The caller must @@ -1180,7 +1250,7 @@ _notmuch_message_remove_term (notmuch_message_t *message, message->doc.remove_term (term); message->modified = TRUE; } catch (const Xapian::InvalidArgumentError) { - /* We'll let the philosopher's try to wrestle with the + /* We'll let the philosophers try to wrestle with the * question of whether failing to remove that which was not * there in the first place is failure. For us, we'll silently * consider it all good. */ @@ -1193,6 +1263,41 @@ _notmuch_message_remove_term (notmuch_message_t *message, return NOTMUCH_PRIVATE_STATUS_SUCCESS; } +notmuch_private_status_t +_notmuch_message_has_term (notmuch_message_t *message, + const char *prefix_name, + const char *value, + notmuch_bool_t *result) +{ + char *term; + notmuch_bool_t out = FALSE; + notmuch_private_status_t status = NOTMUCH_PRIVATE_STATUS_SUCCESS; + + if (value == NULL) + return NOTMUCH_PRIVATE_STATUS_NULL_POINTER; + + term = talloc_asprintf (message, "%s%s", + _find_prefix (prefix_name), value); + + if (strlen (term) > NOTMUCH_TERM_MAX) + return NOTMUCH_PRIVATE_STATUS_TERM_TOO_LONG; + + try { + /* Look for the exact term */ + Xapian::TermIterator i = message->doc.termlist_begin (); + i.skip_to (term); + if (i != message->doc.termlist_end () && + !strcmp ((*i).c_str (), term)) + out = TRUE; + } catch (Xapian::Error &error) { + status = NOTMUCH_PRIVATE_STATUS_XAPIAN_EXCEPTION; + } + talloc_free (term); + + *result = out; + return status; +} + notmuch_status_t notmuch_message_add_tag (notmuch_message_t *message, const char *tag) { diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index 5dd4770e..92807975 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -280,6 +280,12 @@ _notmuch_message_remove_term (notmuch_message_t *message, const char *value); notmuch_private_status_t +_notmuch_message_has_term (notmuch_message_t *message, + const char *prefix_name, + const char *value, + notmuch_bool_t *result); + +notmuch_private_status_t _notmuch_message_gen_terms (notmuch_message_t *message, const char *prefix_name, const char *text); @@ -477,6 +483,17 @@ void _notmuch_doc_id_set_remove (notmuch_doc_id_set_t *doc_ids, unsigned int doc_id); +/* querying xapian documents by type (e.g. "mail" or "ghost"): */ +notmuch_status_t +_notmuch_query_search_documents (notmuch_query_t *query, + const char *type, + notmuch_messages_t **out); + +notmuch_status_t +_notmuch_query_count_documents (notmuch_query_t *query, + const char *type, + unsigned *count_out); + /* message.cc */ void diff --git a/lib/notmuch.h b/lib/notmuch.h index 85b56bf1..cb46fc05 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -59,8 +59,17 @@ NOTMUCH_BEGIN_DECLS #define LIBNOTMUCH_MINOR_VERSION 3 #define LIBNOTMUCH_MICRO_VERSION 0 + +#if defined (__clang_major__) && __clang_major__ >= 3 \ + || defined (__GNUC__) && __GNUC__ >= 5 \ + || defined (__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 5 #define NOTMUCH_DEPRECATED(major,minor) \ __attribute__ ((deprecated ("function deprecated as of libnotmuch " #major "." #minor))) +#else +#define NOTMUCH_DEPRECATED(major,minor) __attribute__ ((deprecated)) +#endif + + #endif /* __DOXYGEN__ */ /** @@ -1752,7 +1761,7 @@ notmuch_filenames_t * notmuch_directory_get_child_files (notmuch_directory_t *directory); /** - * Get a notmuch_filenams_t iterator listing all the filenames of + * Get a notmuch_filenames_t iterator listing all the filenames of * sub-directories in the database within the given directory. * * The returned filenames will be the basename-entries only (not diff --git a/lib/query.cc b/lib/query.cc index e627bfc2..77a7926b 100644 --- a/lib/query.cc +++ b/lib/query.cc @@ -187,6 +187,14 @@ notmuch_status_t notmuch_query_search_messages_st (notmuch_query_t *query, notmuch_messages_t **out) { + return _notmuch_query_search_documents (query, "mail", out); +} + +notmuch_status_t +_notmuch_query_search_documents (notmuch_query_t *query, + const char *type, + notmuch_messages_t **out) +{ notmuch_database_t *notmuch = query->notmuch; const char *query_string = query->query_string; notmuch_mset_messages_t *messages; @@ -208,7 +216,7 @@ notmuch_query_search_messages_st (notmuch_query_t *query, Xapian::Enquire enquire (*notmuch->xapian_db); Xapian::Query mail_query (talloc_asprintf (query, "%s%s", _find_prefix ("type"), - "mail")); + type)); Xapian::Query string_query, final_query, exclude_query; Xapian::MSet mset; Xapian::MSetIterator iterator; @@ -554,6 +562,12 @@ notmuch_query_count_messages (notmuch_query_t *query) notmuch_status_t notmuch_query_count_messages_st (notmuch_query_t *query, unsigned *count_out) { + return _notmuch_query_count_documents (query, "mail", count_out); +} + +notmuch_status_t +_notmuch_query_count_documents (notmuch_query_t *query, const char *type, unsigned *count_out) +{ notmuch_database_t *notmuch = query->notmuch; const char *query_string = query->query_string; Xapian::doccount count = 0; @@ -562,7 +576,7 @@ notmuch_query_count_messages_st (notmuch_query_t *query, unsigned *count_out) Xapian::Enquire enquire (*notmuch->xapian_db); Xapian::Query mail_query (talloc_asprintf (query, "%s%s", _find_prefix ("type"), - "mail")); + type)); Xapian::Query string_query, final_query, exclude_query; Xapian::MSet mset; unsigned int flags = (Xapian::QueryParser::FLAG_BOOLEAN | |
