X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=lib%2Fnotmuch.h;h=3633bedde20acafc064b62a52f319dcdde153111;hp=4295cbd09e0d626409869ed548b80c17fe2e000d;hb=af6b4b29f97b1f457bb7220491bf37536e1b9d7a;hpb=5a98880add247cca406cc99bf826398915ee6039 diff --git a/lib/notmuch.h b/lib/notmuch.h index 4295cbd0..3633bedd 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -81,6 +81,9 @@ typedef int notmuch_bool_t; * NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: The notmuch_message_thaw * function has been called more times than notmuch_message_freeze. * + * NOTMUCH_STATUS_UNBALANCED_ATOMIC: notmuch_database_end_atomic has + * been called more times than notmuch_database_begin_atomic. + * * And finally: * * NOTMUCH_STATUS_LAST_STATUS: Not an actual status value. Just a way @@ -97,13 +100,14 @@ typedef enum _notmuch_status { NOTMUCH_STATUS_NULL_POINTER, NOTMUCH_STATUS_TAG_TOO_LONG, NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW, + NOTMUCH_STATUS_UNBALANCED_ATOMIC, NOTMUCH_STATUS_LAST_STATUS } notmuch_status_t; /* Get a string representation of a notmuch_status_t value. * - * The result is readonly. + * The result is read-only. */ const char * notmuch_status_to_string (notmuch_status_t status); @@ -129,27 +133,38 @@ typedef struct _notmuch_filenames notmuch_filenames_t; * * After a successful call to notmuch_database_create, the returned * database will be open so the caller should call - * notmuch_database_close when finished with it. + * notmuch_database_destroy when finished with it. * * The database will not yet have any data in it * (notmuch_database_create itself is a very cheap function). Messages * contained within 'path' can be added to the database by calling * notmuch_database_add_message. * - * In case of any failure, this function returns NULL, (after printing - * an error message on stderr). + * In case of any failure, this function returns an error status and + * sets *database to NULL (after printing an error message on stderr). + * + * Return value: + * + * NOTMUCH_STATUS_SUCCESS: Successfully created the database. + * + * NOTMUCH_STATUS_NULL_POINTER: The given 'path' argument is NULL. + * + * NOTMUCH_STATUS_OUT_OF_MEMORY: Out of memory. + * + * NOTMUCH_STATUS_FILE_ERROR: An error occurred trying to create the + * database file (such as permission denied, or file not found, + * etc.), or the database already exists. + * + * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred. */ -notmuch_database_t * -notmuch_database_create (const char *path); +notmuch_status_t +notmuch_database_create (const char *path, notmuch_database_t **database); typedef enum { NOTMUCH_DATABASE_MODE_READ_ONLY = 0, NOTMUCH_DATABASE_MODE_READ_WRITE } notmuch_database_mode_t; -/* XXX: I think I'd like this to take an extra argument of - * notmuch_status_t* for returning a status value on failure. */ - /* Open an existing notmuch database located at 'path'. * * The database should have been created at some time in the past, @@ -161,21 +176,50 @@ typedef enum { * An existing notmuch database can be identified by the presence of a * directory named ".notmuch" below 'path'. * - * The caller should call notmuch_database_close when finished with + * The caller should call notmuch_database_destroy when finished with * this database. * - * In case of any failure, this function returns NULL, (after printing - * an error message on stderr). + * In case of any failure, this function returns an error status and + * sets *database to NULL (after printing an error message on stderr). + * + * Return value: + * + * NOTMUCH_STATUS_SUCCESS: Successfully opened the database. + * + * NOTMUCH_STATUS_NULL_POINTER: The given 'path' argument is NULL. + * + * NOTMUCH_STATUS_OUT_OF_MEMORY: Out of memory. + * + * NOTMUCH_STATUS_FILE_ERROR: An error occurred trying to open the + * database file (such as permission denied, or file not found, + * etc.), or the database version is unknown. + * + * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred. */ -notmuch_database_t * +notmuch_status_t notmuch_database_open (const char *path, - notmuch_database_mode_t mode); + notmuch_database_mode_t mode, + notmuch_database_t **database); -/* Close the given notmuch database, freeing all associated - * resources. See notmuch_database_open. */ +/* Close the given notmuch database. + * + * After notmuch_database_close has been called, calls to other + * functions on objects derived from this database may either behave + * as if the database had not been closed (e.g., if the required data + * has been cached) or may fail with a + * NOTMUCH_STATUS_XAPIAN_EXCEPTION. + * + * notmuch_database_close can be called multiple times. Later calls + * have no effect. + */ void notmuch_database_close (notmuch_database_t *database); +/* Destroy the notmuch database, closing it if necessary and freeing +* all associated resources. */ +void +notmuch_database_destroy (notmuch_database_t *database); + /* Return the database path of the given database. * * The return value is a string owned by notmuch so should not be @@ -214,21 +258,69 @@ notmuch_database_upgrade (notmuch_database_t *database, double progress), void *closure); +/* Begin an atomic database operation. + * + * Any modifications performed between a successful begin and a + * notmuch_database_end_atomic will be applied to the database + * atomically. Note that, unlike a typical database transaction, this + * only ensures atomicity, not durability; neither begin nor end + * necessarily flush modifications to disk. + * + * Atomic sections may be nested. begin_atomic and end_atomic must + * always be called in pairs. + * + * Return value: + * + * NOTMUCH_STATUS_SUCCESS: Successfully entered atomic section. + * + * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred; + * atomic section not entered. + */ +notmuch_status_t +notmuch_database_begin_atomic (notmuch_database_t *notmuch); + +/* Indicate the end of an atomic database operation. + * + * Return value: + * + * NOTMUCH_STATUS_SUCCESS: Successfully completed atomic section. + * + * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred; + * atomic section not ended. + * + * NOTMUCH_STATUS_UNBALANCED_ATOMIC: The database is not currently in + * an atomic section. + */ +notmuch_status_t +notmuch_database_end_atomic (notmuch_database_t *notmuch); + /* Retrieve a directory object from the database for 'path'. * * Here, 'path' should be a path relative to the path of 'database' * (see notmuch_database_get_path), or else should be an absolute path * with initial components that match the path of 'database'. * - * Can return NULL if a Xapian exception occurs. + * If this directory object does not exist in the database, this + * returns NOTMUCH_STATUS_SUCCESS and sets *directory to NULL. + * + * Return value: + * + * NOTMUCH_STATUS_SUCCESS: Successfully retrieved directory. + * + * NOTMUCH_STATUS_NULL_POINTER: The given 'directory' argument is NULL. + * + * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred; + * directory not retrieved. */ -notmuch_directory_t * +notmuch_status_t notmuch_database_get_directory (notmuch_database_t *database, - const char *path); + const char *path, + notmuch_directory_t **directory); -/* Add a new message to the given notmuch database. +/* Add a new message to the given notmuch database or associate an + * additional filename with an existing message. * - * Here,'filename' should be a path relative to the path of + * Here, 'filename' should be a path relative to the path of * 'database' (see notmuch_database_get_path), or else should be an * absolute filename with initial components that match the path of * 'database'. @@ -238,6 +330,10 @@ notmuch_database_get_directory (notmuch_database_t *database, * notmuch database will reference the filename, and will not copy the * entire contents of the file. * + * If another message with the same message ID already exists in the + * database, rather than creating a new message, this adds 'filename' + * to the list of the filenames for the existing message. + * * If 'message' is not NULL, then, on successful return * (NOTMUCH_STATUS_SUCCESS or NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) '*message' * will be initialized to a message object that can be used for things @@ -255,7 +351,7 @@ notmuch_database_get_directory (notmuch_database_t *database, * NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID: Message has the same message * ID as another message already in the database. The new * filename was successfully added to the message in the database - * (if not already present). + * (if not already present) and the existing message is returned. * * NOTMUCH_STATUS_FILE_ERROR: an error occurred trying to open the * file, (such as permission denied, or file not found, @@ -272,14 +368,14 @@ notmuch_database_add_message (notmuch_database_t *database, const char *filename, notmuch_message_t **message); -/* Remove a message from the given notmuch database. +/* Remove a message filename from the given notmuch database. If the + * message has no more filenames, remove the message. * - * Note that only this particular filename association is removed from - * the database. If the same message (as determined by the message ID) - * is still available via other filenames, then the message will - * persist in the database for those filenames. When the last filename - * is removed for a particular message, the database content for that - * message will be entirely removed. + * If the same message (as determined by the message ID) is still + * available via other filenames, then the message will persist in the + * database for those filenames. When the last filename is removed for + * a particular message, the database content for that message will be + * entirely removed. * * Return value: * @@ -302,19 +398,57 @@ notmuch_database_remove_message (notmuch_database_t *database, /* Find a message with the given message_id. * - * If the database contains a message with the given message_id, then - * a new notmuch_message_t object is returned. The caller should call - * notmuch_message_destroy when done with the message. + * If a message with the given message_id is found then, on successful return + * (NOTMUCH_STATUS_SUCCESS) '*message' will be initialized to a message + * object. The caller should call notmuch_message_destroy when done with the + * message. + * + * On any failure or when the message is not found, this function initializes + * '*message' to NULL. This means, when NOTMUCH_STATUS_SUCCESS is returned, the + * caller is supposed to check '*message' for NULL to find out whether the + * message with the given message_id was found. + * + * Return value: + * + * NOTMUCH_STATUS_SUCCESS: Successful return, check '*message'. + * + * NOTMUCH_STATUS_NULL_POINTER: The given 'message' argument is NULL * - * This function returns NULL in the following situations: + * NOTMUCH_STATUS_OUT_OF_MEMORY: Out of memory, creating message object * - * * No message is found with the given message_id - * * An out-of-memory situation occurs - * * A Xapian exception occurs + * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred */ -notmuch_message_t * +notmuch_status_t notmuch_database_find_message (notmuch_database_t *database, - const char *message_id); + const char *message_id, + notmuch_message_t **message); + +/* Find a message with the given filename. + * + * If the database contains a message with the given filename then, on + * successful return (NOTMUCH_STATUS_SUCCESS) '*message' will be initialized to + * a message object. The caller should call notmuch_message_destroy when done + * with the message. + * + * On any failure or when the message is not found, this function initializes + * '*message' to NULL. This means, when NOTMUCH_STATUS_SUCCESS is returned, the + * caller is supposed to check '*message' for NULL to find out whether the + * message with the given filename is found. + * + * Return value: + * + * NOTMUCH_STATUS_SUCCESS: Successful return, check '*message' + * + * NOTMUCH_STATUS_NULL_POINTER: The given 'message' argument is NULL + * + * NOTMUCH_STATUS_OUT_OF_MEMORY: Out of memory, creating the message object + * + * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred + */ +notmuch_status_t +notmuch_database_find_message_by_filename (notmuch_database_t *notmuch, + const char *filename, + notmuch_message_t **message); /* Return a list of all tags found in the database. * @@ -366,6 +500,26 @@ typedef enum { const char * notmuch_query_get_query_string (notmuch_query_t *query); +/* Specify whether to omit excluded results or simply flag them. By + * default, this is set to TRUE. + * + * If this is TRUE, notmuch_query_search_messages will omit excluded + * messages from the results. notmuch_query_search_threads will omit + * threads that match only in excluded messages, but will include all + * messages in threads that match in at least one non-excluded + * message. + * + * The performance difference when calling + * notmuch_query_search_messages should be relatively small (and both + * should be very fast). However, in some cases, + * notmuch_query_search_threads is very much faster when omitting + * excluded messages as it does not need to construct the threads that + * only match in excluded messages. + */ + +void +notmuch_query_set_omit_excluded (notmuch_query_t *query, notmuch_bool_t omit_excluded); + /* Specify the sorting desired for this query. */ void notmuch_query_set_sort (notmuch_query_t *query, notmuch_sort_t sort); @@ -374,6 +528,12 @@ notmuch_query_set_sort (notmuch_query_t *query, notmuch_sort_t sort); notmuch_sort_t notmuch_query_get_sort (notmuch_query_t *query); +/* Add a tag that will be excluded from the query results by default. + * This exclusion will be overridden if this tag appears explicitly in + * the query. */ +void +notmuch_query_add_tag_exclude (notmuch_query_t *query, const char *tag); + /* Execute a query for threads, returning a notmuch_threads_t object * which can be used to iterate over the results. The returned threads * object is owned by the query and as such, will only be valid until @@ -510,7 +670,7 @@ notmuch_threads_move_to_next (notmuch_threads_t *threads); * * It's not strictly necessary to call this function. All memory from * the notmuch_threads_t object will be reclaimed when the - * containg query object is destroyed. + * containing query object is destroyed. */ void notmuch_threads_destroy (notmuch_threads_t *threads); @@ -526,6 +686,20 @@ notmuch_threads_destroy (notmuch_threads_t *threads); unsigned notmuch_query_count_messages (notmuch_query_t *query); +/* Return the number of threads matching a search. + * + * This function performs a search and returns the number of unique thread IDs + * in the matching messages. This is the same as number of threads matching a + * search. + * + * Note that this is a significantly heavier operation than + * notmuch_query_count_messages(). + * + * If an error occurs, this function may return 0. + */ +unsigned +notmuch_query_count_threads (notmuch_query_t *query); + /* Get the thread ID of 'thread'. * * The returned string belongs to 'thread' and as such, should not be @@ -562,8 +736,10 @@ notmuch_thread_get_toplevel_messages (notmuch_thread_t *thread); /* Get the number of messages in 'thread' that matched the search. * * This count includes only the messages in this thread that were - * matched by the search from which the thread was created. Contrast - * with notmuch_thread_get_total_messages() . + * matched by the search from which the thread was created and were + * not excluded by any exclude tags passed in with the query (see + * notmuch_query_add_tag_exclude). Contrast with + * notmuch_thread_get_total_messages() . */ int notmuch_thread_get_matched_messages (notmuch_thread_t *thread); @@ -792,7 +968,8 @@ notmuch_message_get_filenames (notmuch_message_t *message); /* Message flags */ typedef enum _notmuch_message_flag { - NOTMUCH_MESSAGE_FLAG_MATCH + NOTMUCH_MESSAGE_FLAG_MATCH, + NOTMUCH_MESSAGE_FLAG_EXCLUDED } notmuch_message_flag_t; /* Get a value of a flag for the email corresponding to 'message'. */ @@ -926,11 +1103,8 @@ notmuch_message_remove_all_tags (notmuch_message_t *message); * For each flag that is not present, the opposite action (add/remove) * is performed for the corresponding tags. * - * The only filenames examined for flags are filenames which appear to - * be within a maildir directory, (the file must be in a directory - * named "new" or "cur" and there must be a neighboring directory - * named respectively "cur" or "new"). The flags are identified as - * trailing components of the filename after a sequence of ":2,". + * Flags are identified as trailing components of the filename after a + * sequence of ":2,". * * If there are multiple filenames associated with this message, the * flag is considered present if it appears in one or more @@ -950,10 +1124,11 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message); * * Specifically, for each filename corresponding to this message: * - * If the filename is not in a maildir directory, do nothing. - * (A maildir directory is determined as a directory named "new" or - * "cur" with a neighboring directory named respectively "cur" or - * "new".) + * If the filename is not in a maildir directory, do nothing. (A + * maildir directory is determined as a directory named "new" or + * "cur".) Similarly, if the filename has invalid maildir info, + * (repeated or outof-ASCII-order flag characters after ":2,"), then + * do nothing. * * If the filename is in a maildir directory, rename the file so that * its filename ends with the sequence ":2," followed by zero or more @@ -965,8 +1140,8 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message); * 'R' iff the message has the "replied" tag * 'S' iff the message does not have the "unread" tag * - * Any existing flags unmentioned in the list above are left - * unaffected by the rename. + * Any existing flags unmentioned in the list above will be preserved + * in the renaming. * * Also, if this filename is in a directory named "new", rename it to * be within the neighboring directory named "cur".