X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=notmuch.h;h=f4e59ab2ca47f47df30c81fba7323f3605b0033f;hp=a6f3f5d4342ea198293a2bb8f0ce36194c77f383;hb=fbf55bfe2fdcdf3773ba37a9921875530e94c7b3;hpb=a360670c03475b1489ea5e2327cc3037cc8dff0b diff --git a/notmuch.h b/notmuch.h index a6f3f5d4..f4e59ab2 100644 --- a/notmuch.h +++ b/notmuch.h @@ -75,6 +75,11 @@ typedef int notmuch_bool_t; * NOTMUCH_STATUS_TAG_TOO_LONG: A tag value is too long (exceeds * NOTMUCH_TAG_MAX) * + * NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: The notmuch_message_thaw + * function has been called more times than notmuch_message_freeze. + * + * And finally: + * * NOTMUCH_STATUS_LAST_STATUS: Not an actual status value. Just a way * to find out how many valid status values there are. */ @@ -87,6 +92,7 @@ typedef enum _notmuch_status { NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID, NOTMUCH_STATUS_NULL_POINTER, NOTMUCH_STATUS_TAG_TOO_LONG, + NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW, NOTMUCH_STATUS_LAST_STATUS } notmuch_status_t; @@ -102,7 +108,9 @@ notmuch_status_to_string (notmuch_status_t status); * notmuch_ functions below. */ typedef struct _notmuch_database notmuch_database_t; typedef struct _notmuch_query notmuch_query_t; -typedef struct _notmuch_results notmuch_results_t; +typedef struct _notmuch_thread_results notmuch_thread_results_t; +typedef struct _notmuch_thread notmuch_thread_t; +typedef struct _notmuch_message_results notmuch_message_results_t; typedef struct _notmuch_message notmuch_message_t; typedef struct _notmuch_tags notmuch_tags_t; @@ -244,6 +252,12 @@ notmuch_database_get_timestamp (notmuch_database_t *database, * reference the filename, and will not copy the entire contents of * the file. * + * If 'message' is not NULL, then, on successful return '*message' + * will be initialized to a message object that can be used for things + * such as adding tags to the just-added message. The user should call + * notmuch_message_destroy when done with the message. On any failure + * '*message' will be set to NULL. + * * Return value: * * NOTMUCH_STATUS_SUCCESS: Message successfully added to database. @@ -261,7 +275,8 @@ notmuch_database_get_timestamp (notmuch_database_t *database, */ notmuch_status_t notmuch_database_add_message (notmuch_database_t *database, - const char *filename); + const char *filename, + notmuch_message_t **message); /* Find a message with the given messsage_id. * @@ -313,22 +328,63 @@ typedef enum { void notmuch_query_set_sort (notmuch_query_t *query, notmuch_sort_t sort); -/* Execute a query, returning a notmuch_results_t object which can be - * used to iterate over the results. The results object is owned by - * the query and as such, will only be valid until notmuch_query_destroy. +/* Execute a query for threads, returning a notmuch_thread_results_t + * object which can be used to iterate over the results. The results + * object is owned by the query and as such, will only be valid until + * notmuch_query_destroy. + * + * Typical usage might be: + * + * notmuch_query_t *query; + * notmuch_thread_results_t *results; + * notmuch_thread_t *thread; + * + * query = notmuch_query_create (database, query_string); + * + * for (results = notmuch_query_search_threads (query); + * notmuch_thread_results_has_more (results); + * notmuch_thread_results_advance (results)) + * { + * thread = notmuch_thread_results_get (results); + * .... + * notmuch_thread_destroy (thread); + * } + * + * notmuch_query_destroy (query); + * + * Note: If you are finished with a thread before its containing + * query, you can call notmuch_thread_destroy to clean up some memory + * sooner (as in the above example). Otherwise, if your thread objects + * are long-lived, then you don't need to call notmuch_thread_destroy + * and all the memory will still be reclaimed when the query is + * destroyed. + * + * Note that there's no explicit destructor needed for the + * notmuch_thread_results_t object. (For consistency, we do provide a + * notmuch_thread_results_destroy function, but there's no good reason + * to call it if the query is about to be destroyed). + */ +notmuch_thread_results_t * +notmuch_query_search_threads (notmuch_query_t *query); + +/* Execute a query for messages, returning a notmuch_message_results_t + * object which can be used to iterate over the results. The results + * object is owned by the query and as such, will only be valid until + * notmuch_query_destroy. * * Typical usage might be: * * notmuch_query_t *query; - * notmuch_results_t *results; + * notmuch_message_results_t *results; + * notmuch_message_t *message; * * query = notmuch_query_create (database, query_string); * - * for (results = notmuch_query_search (query); - * notmuch_results_has_more (results); - * notmuch_result_advance (results)) + * for (results = notmuch_query_search_messages (query); + * notmuch_message_results_has_more (results); + * notmuch_message_results_advance (results)) * { - * message = notmuch_results_get (results); + * message = notmuch_message_results_get (results); * .... * notmuch_message_destroy (message); * } @@ -343,64 +399,181 @@ notmuch_query_set_sort (notmuch_query_t *query, notmuch_sort_t sort); * when the query is destroyed. * * Note that there's no explicit destructor needed for the - * notmuch_results_t object. (For consistency, we do provide a - * notmuch_results_destroy function, but there's no good reason to - * call it if the query is about to be destroyed). + * notmuch_message_results_t object. (For consistency, we do provide a + * notmuch_message_results_destroy function, but there's no good + * reason to call it if the query is about to be destroyed). */ -notmuch_results_t * -notmuch_query_search (notmuch_query_t *query); +notmuch_message_results_t * +notmuch_query_search_messages (notmuch_query_t *query); /* Destroy a notmuch_query_t along with any associated resources. * - * This will in turn destroy any notmuch_results_t objects generated - * by this query, (and in turn any notmuch_message_t objects generated - * from those results, etc.). + * This will in turn destroy any notmuch_thread_results_t and + * notmuch_message_results_t objects generated by this query, (and in + * turn any notmuch_thrad_t and notmuch_message_t objects generated + * from those results, etc.), if such objects haven't already been + * destroyed. */ void notmuch_query_destroy (notmuch_query_t *query); -/* Does the given notmuch_results_t object contain any more results. +/* Does the given notmuch_thread_results_t object contain any more + * results. * - * When this function returns TRUE, notmuch_results_get will return a - * valid object. Whereas when this function returns FALSE, - * notmuch_results_get will return NULL. + * When this function returns TRUE, notmuch_thread_results_get will + * return a valid object. Whereas when this function returns FALSE, + * notmuch_thread_results_get will return NULL. * - * See the documentation of notmuch_query_search for example code - * showing how to iterate over a notmuch_results_t object. + * See the documentation of notmuch_query_search_threads for example + * code showing how to iterate over a notmuch_thread_results_t object. */ notmuch_bool_t -notmuch_results_has_more (notmuch_results_t *results); +notmuch_thread_results_has_more (notmuch_thread_results_t *results); + +/* Get the current result from 'results' as a notmuch_thread_t. + * + * Note: The returned thread belongs to 'results' and has a lifetime + * identical to it (and the query to which it belongs). + * + * See the documentation of notmuch_query_search_threads for example + * code showing how to iterate over a notmuch_thread_results_t object. + * + * If an out-of-memory situation occurs, this function will return + * NULL. + */ +notmuch_thread_t * +notmuch_thread_results_get (notmuch_thread_results_t *results); + +/* Advance the 'results' iterator to the next result. + * + * See the documentation of notmuch_query_search_threads for example + * code showing how to iterate over a notmuch_thread_results_t object. + */ +void +notmuch_thread_results_advance (notmuch_thread_results_t *results); + +/* Destroy a notmuch_thread_results_t object. + * + * It's not strictly necessary to call this function. All memory from + * the notmuch_thread_results_t object will be reclaimed when the + * containg query object is destroyed. + */ +void +notmuch_thread_results_destroy (notmuch_thread_results_t *results); + +/* Get the thread ID of 'thread'. + * + * The returned string belongs to 'thread' and as such, should not be + * modified by the caller and will only be valid for as long as the + * thread is valid, (which is until notmuch_thread_destroy or until + * the query from which it derived is destroyed). + */ +const char * +notmuch_thread_get_thread_id (notmuch_thread_t *thread); + +/* Get the subject of 'thread' + * + * The subject is taken from the first message (according to the query + * order---see notmuch_query_set_sort) in the query results that + * belongs to this thread. + * + * The returned string belongs to 'thread' and as such, should not be + * modified by the caller and will only be valid for as long as the + * thread is valid, (which is until notmuch_thread_destroy or until + * the query from which it derived is destroyed). + */ +const char * +notmuch_thread_get_subject (notmuch_thread_t *thread); + +/* Get the tags for 'thread', returning a notmuch_tags_t object which + * can be used to iterate over all tags. + * + * Note: In the Notmuch database, tags are stored on individual + * messages, not on threads. So the tags returned here will be all + * tags of the messages which matched the search and which belong to + * this thread. + * + * The tags object is owned by the thread and as such, will only be + * valid for as long as the thread is valid, (for example, until + * notmuch_thread_destroy or until the query from which it derived is + * destroyed). + * + * Typical usage might be: + * + * notmuch_thread_t *thread; + * notmuch_tags_t *tags; + * const char *tag; + * + * thread = notmuch_thread_results_get (thread_results); + * + * for (tags = notmuch_thread_get_tags (thread); + * notmuch_tags_has_more (tags); + * notmuch_result_advance (tags)) + * { + * tag = notmuch_tags_get (tags); + * .... + * } + * + * notmuch_thread_destroy (thread); + * + * Note that there's no explicit destructor needed for the + * notmuch_tags_t object. (For consistency, we do provide a + * notmuch_tags_destroy function, but there's no good reason to call + * it if the message is about to be destroyed). + */ +notmuch_tags_t * +notmuch_thread_get_tags (notmuch_thread_t *thread); + +/* Destroy a notmuch_thread_t object. */ +void +notmuch_thread_destroy (notmuch_thread_t *thread); + +/* Does the given notmuch_message_results_t object contain any more + * results. + * + * When this function returns TRUE, notmuch_message_results_get will + * return a valid object. Whereas when this function returns FALSE, + * notmuch_message_results_get will return NULL. + * + * See the documentation of notmuch_query_search_messages for example + * code showing how to iterate over a notmuch_message_results_t + * object. + */ +notmuch_bool_t +notmuch_message_results_has_more (notmuch_message_results_t *results); /* Get the current result from 'results' as a notmuch_message_t. * * Note: The returned message belongs to 'results' and has a lifetime * identical to it (and the query to which it belongs). * - * See the documentation of notmuch_query_search for example code - * showing how to iterate over a notmuch_results_t object. + * See the documentation of notmuch_query_search_messages for example + * code showing how to iterate over a notmuch_message_results_t + * object. * * If an out-of-memory situation occurs, this function will return * NULL. */ notmuch_message_t * -notmuch_results_get (notmuch_results_t *results); +notmuch_message_results_get (notmuch_message_results_t *results); /* Advance the 'results' iterator to the next result. * - * See the documentation of notmuch_query_search for example code - * showing how to iterate over a notmuch_results_t object. + * See the documentation of notmuch_query_search_messages for example + * code showing how to iterate over a notmuch_message_results_t + * object. */ void -notmuch_results_advance (notmuch_results_t *results); +notmuch_message_results_advance (notmuch_message_results_t *results); -/* Destroy a notmuch_results_t object. +/* Destroy a notmuch_message_results_t object. * * It's not strictly necessary to call this function. All memory from - * the notmuch_results_t object will be reclaimed when the containg - * query object is destroyed. + * the notmuch_message_results_t object will be reclaimed when the + * containg query object is destroyed. */ void -notmuch_results_destroy (notmuch_results_t *results); +notmuch_message_results_destroy (notmuch_message_results_t *results); /* Get the message ID of 'message'. * @@ -416,7 +589,6 @@ notmuch_results_destroy (notmuch_results_t *results); const char * notmuch_message_get_message_id (notmuch_message_t *message); - /* Get the thread ID of 'message'. * * The returned string belongs to 'message' and as such, should not be @@ -485,8 +657,8 @@ notmuch_message_get_tags (notmuch_message_t *message); * * NOTMUCH_STATUS_NULL_POINTER: The 'tag' argument is NULL * - * NOTMUCH_STATUS_TAG_TOO_LONG: The length of 'tag' is longer than - * too long (exceeds NOTMUCH_TAG_MAX) + * NOTMUCH_STATUS_TAG_TOO_LONG: The length of 'tag' is too long + * (exceeds NOTMUCH_TAG_MAX) */ notmuch_status_t notmuch_message_add_tag (notmuch_message_t *message, const char *tag); @@ -495,16 +667,83 @@ notmuch_message_add_tag (notmuch_message_t *message, const char *tag); * * Return value: * - * NOTMUCH_STATUS_SUCCESS: Tag successfully added to message + * NOTMUCH_STATUS_SUCCESS: Tag successfully removed from message * * NOTMUCH_STATUS_NULL_POINTER: The 'tag' argument is NULL * - * NOTMUCH_STATUS_TAG_TOO_LONG: The length of 'tag' is longer than - * too long (exceeds NOTMUCH_TAG_MAX) + * NOTMUCH_STATUS_TAG_TOO_LONG: The length of 'tag' is too long + * (exceeds NOTMUCH_TAG_MAX) */ notmuch_status_t notmuch_message_remove_tag (notmuch_message_t *message, const char *tag); +/* Remove all tags from the given message. + * + * See notmuch_message_freeze for an example showing how to safely + * replace tag values. + */ +void +notmuch_message_remove_all_tags (notmuch_message_t *message); + +/* Freeze the current state of 'message' within the database. + * + * This means that changes to the message state, (via + * notmuch_message_add_tag, notmuch_message_remove_tag, and + * notmuch_message_remove_all_tags), will not be committed to the + * database until the message is thawed with notmuch_message_thaw. + * + * Multiple calls to freeze/thaw are valid and these calls with + * "stack". That is there must be as many calls to thaw as to freeze + * before a message is actually thawed. + * + * The ability to do freeze/thaw allows for safe transactions to + * change tag values. For example, explicitly setting a message to + * have a given set of tags might look like this: + * + * notmuch_message_freeze (message); + * + * notmuch_message_remove_all_tags (message); + * + * for (i = 0; i < NUM_TAGS; i++) + * notmuch_message_add_tag (message, tags[i]); + * + * notmuch_message_thaw (message); + * + * With freeze/thaw used like this, the message in the database is + * guaranteed to have either the full set of original tag value, or + * the full set of new tag values, but nothing in between. + * + * Imagine the example above without freeze/thaw and the operation + * somehow getting interrupted. This could result in the message being + * left with no tags if the interruption happened after + * notmuch_message_remove_all_tags but before notmuch_message_add_tag. + */ +void +notmuch_message_freeze (notmuch_message_t *message); + +/* Thaw the current 'message', synchronizing any changes that may have + * occurred while 'message' was frozen into the notmuch database. + * + * See notmuch_message_freeze for an example of how to use this + * function to safely provide tag changes. + * + * Multiple calls to freeze/thaw are valid and these calls with + * "stack". That is there must be as many calls to thaw as to freeze + * before a message is actually thawed. + * + * Return value: + * + * NOTMUCH_STATUS_SUCCESS: Message successfully thawed, (or at least + * its frozen count has successfully been reduced by 1). + * + * NOTMUCH_STATUS_UNBALANCE_FREEZE_THAW: An attempt was made to thaw + * an unfrozen message. That is, there have been an unbalanced + * number of calls to notmuch_message_freeze and + * notmuch_message_thaw. + */ +notmuch_status_t +notmuch_message_thaw (notmuch_message_t *message); + /* Destroy a notmuch_message_t object. * * It can be useful to call this function in the case of a single