diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/database.cc | 40 | ||||
-rw-r--r-- | lib/directory.cc | 41 | ||||
-rw-r--r-- | lib/message.cc | 11 | ||||
-rw-r--r-- | lib/notmuch-private.h | 13 | ||||
-rw-r--r-- | lib/notmuch.h | 10 |
5 files changed, 80 insertions, 35 deletions
diff --git a/lib/database.cc b/lib/database.cc index f8c4a7d1..761dc1a2 100644 --- a/lib/database.cc +++ b/lib/database.cc @@ -956,7 +956,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch, document.get_value (NOTMUCH_VALUE_TIMESTAMP)); directory = _notmuch_directory_create (notmuch, term.c_str() + 10, - &status); + NOTMUCH_FIND_CREATE, &status); notmuch_directory_set_mtime (directory, mtime); notmuch_directory_destroy (directory); } @@ -1197,9 +1197,17 @@ _notmuch_database_split_path (void *ctx, return NOTMUCH_STATUS_SUCCESS; } +/* Find the document ID of the specified directory. + * + * If (flags & NOTMUCH_FIND_CREATE), a new directory document will be + * created if one does not exist for 'path'. Otherwise, if the + * directory document does not exist, this sets *directory_id to + * ((unsigned int)-1) and returns NOTMUCH_STATUS_SUCCESS. + */ notmuch_status_t _notmuch_database_find_directory_id (notmuch_database_t *notmuch, const char *path, + notmuch_find_flags_t flags, unsigned int *directory_id) { notmuch_directory_t *directory; @@ -1210,8 +1218,8 @@ _notmuch_database_find_directory_id (notmuch_database_t *notmuch, return NOTMUCH_STATUS_SUCCESS; } - directory = _notmuch_directory_create (notmuch, path, &status); - if (status) { + directory = _notmuch_directory_create (notmuch, path, flags, &status); + if (status || !directory) { *directory_id = -1; return status; } @@ -1240,13 +1248,16 @@ _notmuch_database_get_directory_path (void *ctx, * database path), return a new string (with 'ctx' as the talloc * owner) suitable for use as a direntry term value. * - * The necessary directory documents will be created in the database - * as needed. + * If (flags & NOTMUCH_FIND_CREATE), the necessary directory documents + * will be created in the database as needed. Otherwise, if the + * necessary directory documents do not exist, this sets + * *direntry to NULL and returns NOTMUCH_STATUS_SUCCESS. */ notmuch_status_t _notmuch_database_filename_to_direntry (void *ctx, notmuch_database_t *notmuch, const char *filename, + notmuch_find_flags_t flags, char **direntry) { const char *relative, *directory, *basename; @@ -1260,10 +1271,12 @@ _notmuch_database_filename_to_direntry (void *ctx, if (status) return status; - status = _notmuch_database_find_directory_id (notmuch, directory, + status = _notmuch_database_find_directory_id (notmuch, directory, flags, &directory_id); - if (status) + if (status || directory_id == (unsigned int)-1) { + *direntry = NULL; return status; + } *direntry = talloc_asprintf (ctx, "%u:%s", directory_id, basename); @@ -1315,12 +1328,9 @@ notmuch_database_get_directory (notmuch_database_t *notmuch, return NOTMUCH_STATUS_NULL_POINTER; *directory = NULL; - /* XXX Handle read-only databases properly */ - if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY) - return NOTMUCH_STATUS_READ_ONLY_DATABASE; - try { - *directory = _notmuch_directory_create (notmuch, path, &status); + *directory = _notmuch_directory_create (notmuch, path, + NOTMUCH_FIND_LOOKUP, &status); } catch (const Xapian::Error &error) { fprintf (stderr, "A Xapian exception occurred getting directory: %s.\n", error.get_msg().c_str()); @@ -1884,9 +1894,9 @@ notmuch_database_find_message_by_filename (notmuch_database_t *notmuch, local = talloc_new (notmuch); try { - status = _notmuch_database_filename_to_direntry (local, notmuch, - filename, &direntry); - if (status) + status = _notmuch_database_filename_to_direntry ( + local, notmuch, filename, NOTMUCH_FIND_LOOKUP, &direntry); + if (status || !direntry) goto DONE; term = talloc_asprintf (local, "%s%s", prefix, direntry); diff --git a/lib/directory.cc b/lib/directory.cc index 70e1693e..6a3ffed7 100644 --- a/lib/directory.cc +++ b/lib/directory.cc @@ -82,28 +82,41 @@ find_directory_document (notmuch_database_t *notmuch, return NOTMUCH_PRIVATE_STATUS_SUCCESS; } +/* Find or create a directory document. + * + * 'path' should be a path relative to the path of 'database', or else + * should be an absolute path with initial components that match the + * path of 'database'. + * + * If (flags & NOTMUCH_FIND_CREATE), then the directory document will + * be created if it does not exist. Otherwise, if the directory + * document does not exist, *status_ret is set to + * NOTMUCH_STATUS_SUCCESS and this returns NULL. + */ notmuch_directory_t * _notmuch_directory_create (notmuch_database_t *notmuch, const char *path, + notmuch_find_flags_t flags, notmuch_status_t *status_ret) { Xapian::WritableDatabase *db; notmuch_directory_t *directory; notmuch_private_status_t private_status; const char *db_path; + notmuch_bool_t create = (flags & NOTMUCH_FIND_CREATE); *status_ret = NOTMUCH_STATUS_SUCCESS; path = _notmuch_database_relative_path (notmuch, path); - if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY) + if (create && notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY) INTERNAL_ERROR ("Failure to ensure database is writable"); - db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db); - directory = talloc (notmuch, notmuch_directory_t); - if (unlikely (directory == NULL)) + if (unlikely (directory == NULL)) { + *status_ret = NOTMUCH_STATUS_OUT_OF_MEMORY; return NULL; + } directory->notmuch = notmuch; @@ -122,6 +135,13 @@ _notmuch_directory_create (notmuch_database_t *notmuch, directory->document_id = directory->doc.get_docid (); if (private_status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) { + if (!create) { + notmuch_directory_destroy (directory); + directory = NULL; + *status_ret = NOTMUCH_STATUS_SUCCESS; + goto DONE; + } + void *local = talloc_new (directory); const char *parent, *basename; Xapian::docid parent_id; @@ -133,7 +153,13 @@ _notmuch_directory_create (notmuch_database_t *notmuch, _notmuch_database_split_path (local, path, &parent, &basename); - _notmuch_database_find_directory_id (notmuch, parent, &parent_id); + *status_ret = _notmuch_database_find_directory_id ( + notmuch, parent, NOTMUCH_FIND_CREATE, &parent_id); + if (*status_ret) { + notmuch_directory_destroy (directory); + directory = NULL; + goto DONE; + } if (basename) { term = talloc_asprintf (local, "%s%u:%s", @@ -145,6 +171,8 @@ _notmuch_directory_create (notmuch_database_t *notmuch, directory->doc.add_value (NOTMUCH_VALUE_TIMESTAMP, Xapian::sortable_serialise (0)); + db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db); + directory->document_id = _notmuch_database_generate_doc_id (notmuch); db->replace_document (directory->document_id, directory->doc); talloc_free (local); @@ -158,10 +186,11 @@ _notmuch_directory_create (notmuch_database_t *notmuch, error.get_msg().c_str()); notmuch->exception_reported = TRUE; notmuch_directory_destroy (directory); + directory = NULL; *status_ret = NOTMUCH_STATUS_XAPIAN_EXCEPTION; - return NULL; } + DONE: if (db_path != path) free ((char *) db_path); diff --git a/lib/message.cc b/lib/message.cc index 00754254..67875065 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -495,9 +495,8 @@ _notmuch_message_add_filename (notmuch_message_t *message, if (status) return status; - status = _notmuch_database_filename_to_direntry (local, - message->notmuch, - filename, &direntry); + status = _notmuch_database_filename_to_direntry ( + local, message->notmuch, filename, NOTMUCH_FIND_CREATE, &direntry); if (status) return status; @@ -541,9 +540,9 @@ _notmuch_message_remove_filename (notmuch_message_t *message, notmuch_status_t status; Xapian::TermIterator i, last; - status = _notmuch_database_filename_to_direntry (local, message->notmuch, - filename, &direntry); - if (status) + status = _notmuch_database_filename_to_direntry ( + local, message->notmuch, filename, NOTMUCH_FIND_LOOKUP, &direntry); + if (status || !direntry) return status; /* Unlink this file from its parent directory. */ diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index 3886e0ca..bfb41116 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -146,6 +146,16 @@ typedef enum _notmuch_private_status { : \ (notmuch_status_t) private_status) +/* Flags shared by various lookup functions. */ +typedef enum _notmuch_find_flags { + /* Lookup without creating any documents. This is the default + * behavior. */ + NOTMUCH_FIND_LOOKUP = 0, + /* If set, create the necessary document (or documents) if they + * are missing. Requires a read/write database. */ + NOTMUCH_FIND_CREATE = 1<<0, +} notmuch_find_flags_t; + typedef struct _notmuch_doc_id_set notmuch_doc_id_set_t; typedef struct _notmuch_string_list notmuch_string_list_t; @@ -188,6 +198,7 @@ _notmuch_database_find_unique_doc_id (notmuch_database_t *notmuch, notmuch_status_t _notmuch_database_find_directory_id (notmuch_database_t *database, const char *path, + notmuch_find_flags_t flags, unsigned int *directory_id); const char * @@ -199,6 +210,7 @@ notmuch_status_t _notmuch_database_filename_to_direntry (void *ctx, notmuch_database_t *notmuch, const char *filename, + notmuch_find_flags_t flags, char **direntry); /* directory.cc */ @@ -206,6 +218,7 @@ _notmuch_database_filename_to_direntry (void *ctx, notmuch_directory_t * _notmuch_directory_create (notmuch_database_t *notmuch, const char *path, + notmuch_find_flags_t flags, notmuch_status_t *status_ret); unsigned int diff --git a/lib/notmuch.h b/lib/notmuch.h index bbb17e4a..3633bedd 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -300,10 +300,8 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch); * (see notmuch_database_get_path), or else should be an absolute path * with initial components that match the path of 'database'. * - * Note: Currently this will create the directory object if it doesn't - * exist. In the future, when a directory object does not exist this - * will return NOTMUCH_STATUS_SUCCESS and set *directory to NULL. - * Callers should be prepared for this. + * If this directory object does not exist in the database, this + * returns NOTMUCH_STATUS_SUCCESS and sets *directory to NULL. * * Return value: * @@ -313,10 +311,6 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch); * * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred; * directory not retrieved. - * - * NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only - * mode so the directory cannot be created (this case will be - * removed in the future). */ notmuch_status_t notmuch_database_get_directory (notmuch_database_t *database, |