X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=lib%2Fopen.cc;h=8a835e986d5dd78661eba0a53e793b288550b083;hp=c2cb281865e7beccbe9a3046c8f911855820a436;hb=HEAD;hpb=1e7d33961e626488b09b56c8543e8edf00648670 diff --git a/lib/open.cc b/lib/open.cc index c2cb2818..463e38bf 100644 --- a/lib/open.cc +++ b/lib/open.cc @@ -3,6 +3,7 @@ #include "database-private.h" #include "parse-time-vrp.h" +#include "lastmod-fp.h" #include "path-util.h" #if HAVE_XAPIAN_DB_RETRY_LOCK @@ -186,36 +187,35 @@ _db_dir_exists (const char *database_path, char **message) } static notmuch_status_t -_choose_database_path (void *ctx, +_choose_database_path (notmuch_database_t *notmuch, const char *profile, GKeyFile *key_file, const char **database_path, - bool *split, char **message) { + notmuch_status_t status; + if (! *database_path) { *database_path = getenv ("NOTMUCH_DATABASE"); } if (! *database_path && key_file) { - char *path = g_key_file_get_value (key_file, "database", "path", NULL); + char *path = g_key_file_get_string (key_file, "database", "path", NULL); if (path) { if (path[0] == '/') - *database_path = talloc_strdup (ctx, path); + *database_path = talloc_strdup (notmuch, path); else - *database_path = talloc_asprintf (ctx, "%s/%s", getenv ("HOME"), path); + *database_path = talloc_asprintf (notmuch, "%s/%s", getenv ("HOME"), path); g_free (path); } } if (! *database_path) { - notmuch_status_t status; - - *database_path = _xdg_dir (ctx, "XDG_DATA_HOME", ".local/share", profile); + *database_path = _xdg_dir (notmuch, "XDG_DATA_HOME", ".local/share", profile); status = _db_dir_exists (*database_path, message); if (status) { *database_path = NULL; } else { - *split = true; + notmuch->params |= NOTMUCH_PARAM_SPLIT; } } @@ -224,9 +224,7 @@ _choose_database_path (void *ctx, } if (! *database_path) { - notmuch_status_t status; - - *database_path = talloc_asprintf (ctx, "%s/mail", getenv ("HOME")); + *database_path = talloc_asprintf (notmuch, "%s/mail", getenv ("HOME")); status = _db_dir_exists (*database_path, message); if (status) { *database_path = NULL; @@ -242,6 +240,71 @@ _choose_database_path (void *ctx, *message = strdup ("Error: Database path must be absolute.\n"); return NOTMUCH_STATUS_PATH_ERROR; } + + status = _db_dir_exists (*database_path, message); + if (status) { + IGNORE_RESULT (asprintf (message, + "Error: database path '%s' does not exist or is not a directory.\n", + *database_path)); + return NOTMUCH_STATUS_NO_DATABASE; + } + + if (*message) { + free (*message); + *message = NULL; + } + + return NOTMUCH_STATUS_SUCCESS; +} + +static notmuch_status_t +_mkdir (const char *path, char **message) +{ + if (g_mkdir_with_parents (path, 0755)) { + IGNORE_RESULT (asprintf (message, "Error: Cannot create directory %s: %s.\n", + path, strerror (errno))); + return NOTMUCH_STATUS_FILE_ERROR; + } + return NOTMUCH_STATUS_SUCCESS; +} + +static notmuch_status_t +_create_database_path (notmuch_database_t *notmuch, + const char *profile, + GKeyFile *key_file, + const char **database_path, + char **message) +{ + notmuch_status_t status; + + if (! *database_path) { + *database_path = getenv ("NOTMUCH_DATABASE"); + } + + if (! *database_path && key_file) { + char *path = g_key_file_get_string (key_file, "database", "path", NULL); + if (path) { + if (path[0] == '/') + *database_path = talloc_strdup (notmuch, path); + else + *database_path = talloc_asprintf (notmuch, "%s/%s", getenv ("HOME"), path); + g_free (path); + } + } + + if (! *database_path) { + *database_path = _xdg_dir (notmuch, "XDG_DATA_HOME", ".local/share", profile); + notmuch->params |= NOTMUCH_PARAM_SPLIT; + } + + if (*database_path[0] != '/') { + *message = strdup ("Error: Database path must be absolute.\n"); + return NOTMUCH_STATUS_PATH_ERROR; + } + + if ((status = _mkdir (*database_path, message))) + return status; + return NOTMUCH_STATUS_SUCCESS; } @@ -262,6 +325,8 @@ _alloc_notmuch (const char *database_path, const char *config_path, const char * notmuch->transaction_count = 0; notmuch->transaction_threshold = 0; notmuch->view = 1; + notmuch->index_as_text = NULL; + notmuch->index_as_text_length = 0; notmuch->params = NOTMUCH_PARAM_NONE; if (database_path) @@ -369,6 +434,53 @@ _load_database_state (notmuch_database_t *notmuch) notmuch, notmuch->xapian_db->get_uuid ().c_str ()); } +/* XXX This should really be done lazily, but the error reporting path in the indexing code + * would need to be redone to report any errors. + */ +notmuch_status_t +_ensure_index_as_text (notmuch_database_t *notmuch, char **message) +{ + int nregex = 0; + regex_t *regexv = NULL; + + if (notmuch->index_as_text) + return NOTMUCH_STATUS_SUCCESS; + + for (notmuch_config_values_t *list = notmuch_config_get_values (notmuch, + NOTMUCH_CONFIG_INDEX_AS_TEXT); + notmuch_config_values_valid (list); + notmuch_config_values_move_to_next (list)) { + regex_t *new_regex; + int rerr; + const char *str = notmuch_config_values_get (list); + size_t len = strlen (str); + + /* str must be non-empty, because n_c_get_values skips empty + * strings */ + assert (len > 0); + + regexv = talloc_realloc (notmuch, regexv, regex_t, nregex + 1); + new_regex = ®exv[nregex]; + + rerr = regcomp (new_regex, str, REG_EXTENDED | REG_NOSUB); + if (rerr) { + size_t error_size = regerror (rerr, new_regex, NULL, 0); + char *error = (char *) talloc_size (str, error_size); + + regerror (rerr, new_regex, error, error_size); + IGNORE_RESULT (asprintf (message, "Error in index.as_text: %s: %s\n", error, str)); + + return NOTMUCH_STATUS_ILLEGAL_ARGUMENT; + } + nregex++; + } + + notmuch->index_as_text = regexv; + notmuch->index_as_text_length = nregex; + + return NOTMUCH_STATUS_SUCCESS; +} + static notmuch_status_t _finish_open (notmuch_database_t *notmuch, const char *profile, @@ -432,8 +544,7 @@ _finish_open (notmuch_database_t *notmuch, notmuch->value_range_processor = new Xapian::NumberRangeProcessor (NOTMUCH_VALUE_TIMESTAMP); notmuch->date_range_processor = new ParseTimeRangeProcessor (NOTMUCH_VALUE_TIMESTAMP, "date:"); - notmuch->last_mod_range_processor = new Xapian::NumberRangeProcessor (NOTMUCH_VALUE_LAST_MOD, - "lastmod:"); + notmuch->last_mod_range_processor = new LastModRangeProcessor (notmuch, "lastmod:"); notmuch->query_parser->set_default_op (Xapian::Query::OP_AND); notmuch->query_parser->set_database (*notmuch->xapian_db); notmuch->stemmer = new Xapian::Stem ("english"); @@ -449,7 +560,7 @@ _finish_open (notmuch_database_t *notmuch, goto DONE; if (key_file) - status = _notmuch_config_load_from_file (notmuch, key_file); + status = _notmuch_config_load_from_file (notmuch, key_file, &message); if (status) goto DONE; @@ -474,6 +585,10 @@ _finish_open (notmuch_database_t *notmuch, if (status) goto DONE; + status = _ensure_index_as_text (notmuch, &message); + if (status) + goto DONE; + autocommit_str = notmuch_config_get (notmuch, NOTMUCH_CONFIG_AUTOCOMMIT); if (unlikely (! autocommit_str)) { INTERNAL_ERROR ("missing configuration for autocommit"); @@ -510,11 +625,9 @@ notmuch_database_open_with_config (const char *database_path, char **status_string) { notmuch_status_t status = NOTMUCH_STATUS_SUCCESS; - void *local = talloc_new (NULL); notmuch_database_t *notmuch = NULL; char *message = NULL; GKeyFile *key_file = NULL; - bool split = false; _notmuch_init (); @@ -530,8 +643,8 @@ notmuch_database_open_with_config (const char *database_path, goto DONE; } - if ((status = _choose_database_path (local, profile, key_file, - &database_path, &split, + if ((status = _choose_database_path (notmuch, profile, key_file, + &database_path, &message))) goto DONE; @@ -549,8 +662,6 @@ notmuch_database_open_with_config (const char *database_path, status = _finish_open (notmuch, profile, mode, key_file, &message); DONE: - talloc_free (local); - if (key_file) g_key_file_free (key_file); @@ -612,9 +723,6 @@ notmuch_database_create_with_config (const char *database_path, const char *notmuch_path = NULL; char *message = NULL; GKeyFile *key_file = NULL; - void *local = talloc_new (NULL); - int err; - bool split = false; _notmuch_init (); @@ -630,48 +738,45 @@ notmuch_database_create_with_config (const char *database_path, goto DONE; } - if ((status = _choose_database_path (local, profile, key_file, - &database_path, &split, &message))) - goto DONE; - - status = _db_dir_exists (database_path, &message); - if (status) + status = _choose_database_path (notmuch, profile, key_file, + &database_path, &message); + switch (status) { + case NOTMUCH_STATUS_SUCCESS: + break; + case NOTMUCH_STATUS_NO_DATABASE: + if ((status = _create_database_path (notmuch, profile, key_file, + &database_path, &message))) + goto DONE; + break; + default: goto DONE; + } _set_database_path (notmuch, database_path); - if (key_file && ! split) { + if (key_file && ! (notmuch->params & NOTMUCH_PARAM_SPLIT)) { char *mail_root = notmuch_canonicalize_file_name ( - g_key_file_get_value (key_file, "database", "mail_root", NULL)); + g_key_file_get_string (key_file, "database", "mail_root", NULL)); char *db_path = notmuch_canonicalize_file_name (database_path); - split = (mail_root && (0 != strcmp (mail_root, db_path))); + if (mail_root && (0 != strcmp (mail_root, db_path))) + notmuch->params |= NOTMUCH_PARAM_SPLIT; free (mail_root); free (db_path); } - if (split) { + if (notmuch->params & NOTMUCH_PARAM_SPLIT) { notmuch_path = database_path; } else { - if (! (notmuch_path = talloc_asprintf (local, "%s/%s", database_path, ".notmuch"))) { + if (! (notmuch_path = talloc_asprintf (notmuch, "%s/%s", database_path, ".notmuch"))) { status = NOTMUCH_STATUS_OUT_OF_MEMORY; goto DONE; } - err = mkdir (notmuch_path, 0755); - if (err) { - if (errno == EEXIST) { - status = NOTMUCH_STATUS_DATABASE_EXISTS; - talloc_free (notmuch); - notmuch = NULL; - } else { - IGNORE_RESULT (asprintf (&message, "Error: Cannot create directory %s: %s.\n", - notmuch_path, strerror (errno))); - status = NOTMUCH_STATUS_FILE_ERROR; - } + status = _mkdir (notmuch_path, &message); + if (status) goto DONE; - } } if (! (notmuch->xapian_path = talloc_asprintf (notmuch, "%s/%s", notmuch_path, "xapian"))) { @@ -711,8 +816,6 @@ notmuch_database_create_with_config (const char *database_path, } DONE: - talloc_free (local); - if (key_file) g_key_file_free (key_file); @@ -812,11 +915,9 @@ notmuch_database_load_config (const char *database_path, char **status_string) { notmuch_status_t status = NOTMUCH_STATUS_SUCCESS, warning = NOTMUCH_STATUS_SUCCESS; - void *local = talloc_new (NULL); notmuch_database_t *notmuch = NULL; char *message = NULL; GKeyFile *key_file = NULL; - bool split = false; _notmuch_init (); @@ -838,8 +939,8 @@ notmuch_database_load_config (const char *database_path, goto DONE; } - status = _choose_database_path (local, profile, key_file, - &database_path, &split, &message); + status = _choose_database_path (notmuch, profile, key_file, + &database_path, &message); switch (status) { case NOTMUCH_STATUS_NO_DATABASE: case NOTMUCH_STATUS_SUCCESS: @@ -865,7 +966,7 @@ notmuch_database_load_config (const char *database_path, } if (key_file) { - status = _notmuch_config_load_from_file (notmuch, key_file); + status = _notmuch_config_load_from_file (notmuch, key_file, &message); if (status) goto DONE; } @@ -874,8 +975,6 @@ notmuch_database_load_config (const char *database_path, goto DONE; DONE: - talloc_free (local); - if (status_string) *status_string = message;