mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-25 04:18:08 +01:00
lib: add "verbose" versions of notmuch_database_{open,create}
The compatibility wrapper ensures that clients calling notmuch_database_open will receive consistent output for now. The changes to notmuch-{new,search} and test/symbol-test are just to make the test suite pass. The use of IGNORE_RESULT is justified by two things. 1) I don't know what else to do. 2) asprintf guarantees the output string is NULL if an error occurs, so at least we are not passing garbage back.
This commit is contained in:
parent
83298fa0f8
commit
84d3b15d25
5 changed files with 137 additions and 33 deletions
102
lib/database.cc
102
lib/database.cc
|
@ -607,30 +607,51 @@ parse_references (void *ctx,
|
||||||
|
|
||||||
notmuch_status_t
|
notmuch_status_t
|
||||||
notmuch_database_create (const char *path, notmuch_database_t **database)
|
notmuch_database_create (const char *path, notmuch_database_t **database)
|
||||||
|
{
|
||||||
|
char *status_string = NULL;
|
||||||
|
notmuch_status_t status;
|
||||||
|
|
||||||
|
status = notmuch_database_create_verbose (path, database,
|
||||||
|
&status_string);
|
||||||
|
|
||||||
|
if (status_string) {
|
||||||
|
fputs (status_string, stderr);
|
||||||
|
free (status_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
notmuch_status_t
|
||||||
|
notmuch_database_create_verbose (const char *path,
|
||||||
|
notmuch_database_t **database,
|
||||||
|
char **status_string)
|
||||||
{
|
{
|
||||||
notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
|
notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
|
||||||
notmuch_database_t *notmuch = NULL;
|
notmuch_database_t *notmuch = NULL;
|
||||||
char *notmuch_path = NULL;
|
char *notmuch_path = NULL;
|
||||||
|
char *message = NULL;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (path == NULL) {
|
if (path == NULL) {
|
||||||
fprintf (stderr, "Error: Cannot create a database for a NULL path.\n");
|
message = strdup ("Error: Cannot create a database for a NULL path.\n");
|
||||||
status = NOTMUCH_STATUS_NULL_POINTER;
|
status = NOTMUCH_STATUS_NULL_POINTER;
|
||||||
goto DONE;
|
goto DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = stat (path, &st);
|
err = stat (path, &st);
|
||||||
if (err) {
|
if (err) {
|
||||||
fprintf (stderr, "Error: Cannot create database at %s: %s.\n",
|
IGNORE_RESULT (asprintf (&message, "Error: Cannot create database at %s: %s.\n",
|
||||||
path, strerror (errno));
|
path, strerror (errno)));
|
||||||
status = NOTMUCH_STATUS_FILE_ERROR;
|
status = NOTMUCH_STATUS_FILE_ERROR;
|
||||||
goto DONE;
|
goto DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! S_ISDIR (st.st_mode)) {
|
if (! S_ISDIR (st.st_mode)) {
|
||||||
fprintf (stderr, "Error: Cannot create database at %s: Not a directory.\n",
|
IGNORE_RESULT (asprintf (&message, "Error: Cannot create database at %s: "
|
||||||
path);
|
"Not a directory.\n",
|
||||||
|
path));
|
||||||
status = NOTMUCH_STATUS_FILE_ERROR;
|
status = NOTMUCH_STATUS_FILE_ERROR;
|
||||||
goto DONE;
|
goto DONE;
|
||||||
}
|
}
|
||||||
|
@ -640,15 +661,15 @@ notmuch_database_create (const char *path, notmuch_database_t **database)
|
||||||
err = mkdir (notmuch_path, 0755);
|
err = mkdir (notmuch_path, 0755);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
fprintf (stderr, "Error: Cannot create directory %s: %s.\n",
|
IGNORE_RESULT (asprintf (&message, "Error: Cannot create directory %s: %s.\n",
|
||||||
notmuch_path, strerror (errno));
|
notmuch_path, strerror (errno)));
|
||||||
status = NOTMUCH_STATUS_FILE_ERROR;
|
status = NOTMUCH_STATUS_FILE_ERROR;
|
||||||
goto DONE;
|
goto DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = notmuch_database_open (path,
|
status = notmuch_database_open_verbose (path,
|
||||||
NOTMUCH_DATABASE_MODE_READ_WRITE,
|
NOTMUCH_DATABASE_MODE_READ_WRITE,
|
||||||
¬much);
|
¬much, &message);
|
||||||
if (status)
|
if (status)
|
||||||
goto DONE;
|
goto DONE;
|
||||||
|
|
||||||
|
@ -667,6 +688,12 @@ notmuch_database_create (const char *path, notmuch_database_t **database)
|
||||||
if (notmuch_path)
|
if (notmuch_path)
|
||||||
talloc_free (notmuch_path);
|
talloc_free (notmuch_path);
|
||||||
|
|
||||||
|
if (message) {
|
||||||
|
if (status_string)
|
||||||
|
*status_string = message;
|
||||||
|
else
|
||||||
|
free (message);
|
||||||
|
}
|
||||||
if (database)
|
if (database)
|
||||||
*database = notmuch;
|
*database = notmuch;
|
||||||
else
|
else
|
||||||
|
@ -766,38 +793,59 @@ notmuch_status_t
|
||||||
notmuch_database_open (const char *path,
|
notmuch_database_open (const char *path,
|
||||||
notmuch_database_mode_t mode,
|
notmuch_database_mode_t mode,
|
||||||
notmuch_database_t **database)
|
notmuch_database_t **database)
|
||||||
|
{
|
||||||
|
char *status_string = NULL;
|
||||||
|
notmuch_status_t status;
|
||||||
|
|
||||||
|
status = notmuch_database_open_verbose (path, mode, database,
|
||||||
|
&status_string);
|
||||||
|
|
||||||
|
if (status_string) {
|
||||||
|
fputs (status_string, stderr);
|
||||||
|
free (status_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
notmuch_status_t
|
||||||
|
notmuch_database_open_verbose (const char *path,
|
||||||
|
notmuch_database_mode_t mode,
|
||||||
|
notmuch_database_t **database,
|
||||||
|
char **status_string)
|
||||||
{
|
{
|
||||||
notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
|
notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
|
||||||
void *local = talloc_new (NULL);
|
void *local = talloc_new (NULL);
|
||||||
notmuch_database_t *notmuch = NULL;
|
notmuch_database_t *notmuch = NULL;
|
||||||
char *notmuch_path, *xapian_path, *incompat_features;
|
char *notmuch_path, *xapian_path, *incompat_features;
|
||||||
|
char *message = NULL;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int err;
|
int err;
|
||||||
unsigned int i, version;
|
unsigned int i, version;
|
||||||
static int initialized = 0;
|
static int initialized = 0;
|
||||||
|
|
||||||
if (path == NULL) {
|
if (path == NULL) {
|
||||||
fprintf (stderr, "Error: Cannot open a database for a NULL path.\n");
|
message = strdup ("Error: Cannot open a database for a NULL path.\n");
|
||||||
status = NOTMUCH_STATUS_NULL_POINTER;
|
status = NOTMUCH_STATUS_NULL_POINTER;
|
||||||
goto DONE;
|
goto DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! (notmuch_path = talloc_asprintf (local, "%s/%s", path, ".notmuch"))) {
|
if (! (notmuch_path = talloc_asprintf (local, "%s/%s", path, ".notmuch"))) {
|
||||||
fprintf (stderr, "Out of memory\n");
|
message = strdup ("Out of memory\n");
|
||||||
status = NOTMUCH_STATUS_OUT_OF_MEMORY;
|
status = NOTMUCH_STATUS_OUT_OF_MEMORY;
|
||||||
goto DONE;
|
goto DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = stat (notmuch_path, &st);
|
err = stat (notmuch_path, &st);
|
||||||
if (err) {
|
if (err) {
|
||||||
fprintf (stderr, "Error opening database at %s: %s\n",
|
IGNORE_RESULT (asprintf (&message, "Error opening database at %s: %s\n",
|
||||||
notmuch_path, strerror (errno));
|
notmuch_path, strerror (errno)));
|
||||||
status = NOTMUCH_STATUS_FILE_ERROR;
|
status = NOTMUCH_STATUS_FILE_ERROR;
|
||||||
goto DONE;
|
goto DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! (xapian_path = talloc_asprintf (local, "%s/%s", notmuch_path, "xapian"))) {
|
if (! (xapian_path = talloc_asprintf (local, "%s/%s", notmuch_path, "xapian"))) {
|
||||||
fprintf (stderr, "Out of memory\n");
|
message = strdup ("Out of memory\n");
|
||||||
status = NOTMUCH_STATUS_OUT_OF_MEMORY;
|
status = NOTMUCH_STATUS_OUT_OF_MEMORY;
|
||||||
goto DONE;
|
goto DONE;
|
||||||
}
|
}
|
||||||
|
@ -837,11 +885,11 @@ notmuch_database_open (const char *path,
|
||||||
* means a dramatically incompatible change. */
|
* means a dramatically incompatible change. */
|
||||||
version = notmuch_database_get_version (notmuch);
|
version = notmuch_database_get_version (notmuch);
|
||||||
if (version > NOTMUCH_DATABASE_VERSION) {
|
if (version > NOTMUCH_DATABASE_VERSION) {
|
||||||
fprintf (stderr,
|
IGNORE_RESULT (asprintf (&message,
|
||||||
"Error: Notmuch database at %s\n"
|
"Error: Notmuch database at %s\n"
|
||||||
" has a newer database format version (%u) than supported by this\n"
|
" has a newer database format version (%u) than supported by this\n"
|
||||||
" version of notmuch (%u).\n",
|
" version of notmuch (%u).\n",
|
||||||
notmuch_path, version, NOTMUCH_DATABASE_VERSION);
|
notmuch_path, version, NOTMUCH_DATABASE_VERSION));
|
||||||
notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;
|
notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;
|
||||||
notmuch_database_destroy (notmuch);
|
notmuch_database_destroy (notmuch);
|
||||||
notmuch = NULL;
|
notmuch = NULL;
|
||||||
|
@ -856,11 +904,11 @@ notmuch_database_open (const char *path,
|
||||||
version, mode == NOTMUCH_DATABASE_MODE_READ_WRITE ? 'w' : 'r',
|
version, mode == NOTMUCH_DATABASE_MODE_READ_WRITE ? 'w' : 'r',
|
||||||
&incompat_features);
|
&incompat_features);
|
||||||
if (incompat_features) {
|
if (incompat_features) {
|
||||||
fprintf (stderr,
|
IGNORE_RESULT (asprintf (&message,
|
||||||
"Error: Notmuch database at %s\n"
|
"Error: Notmuch database at %s\n"
|
||||||
" requires features (%s)\n"
|
" requires features (%s)\n"
|
||||||
" not supported by this version of notmuch.\n",
|
" not supported by this version of notmuch.\n",
|
||||||
notmuch_path, incompat_features);
|
notmuch_path, incompat_features));
|
||||||
notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;
|
notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;
|
||||||
notmuch_database_destroy (notmuch);
|
notmuch_database_destroy (notmuch);
|
||||||
notmuch = NULL;
|
notmuch = NULL;
|
||||||
|
@ -906,8 +954,8 @@ notmuch_database_open (const char *path,
|
||||||
notmuch->query_parser->add_prefix (prefix->name, prefix->prefix);
|
notmuch->query_parser->add_prefix (prefix->name, prefix->prefix);
|
||||||
}
|
}
|
||||||
} catch (const Xapian::Error &error) {
|
} catch (const Xapian::Error &error) {
|
||||||
fprintf (stderr, "A Xapian exception occurred opening database: %s\n",
|
IGNORE_RESULT (asprintf (&message, "A Xapian exception occurred opening database: %s\n",
|
||||||
error.get_msg().c_str());
|
error.get_msg().c_str()));
|
||||||
notmuch_database_destroy (notmuch);
|
notmuch_database_destroy (notmuch);
|
||||||
notmuch = NULL;
|
notmuch = NULL;
|
||||||
status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
|
status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
|
||||||
|
@ -916,6 +964,13 @@ notmuch_database_open (const char *path,
|
||||||
DONE:
|
DONE:
|
||||||
talloc_free (local);
|
talloc_free (local);
|
||||||
|
|
||||||
|
if (message) {
|
||||||
|
if (status_string)
|
||||||
|
*status_string = message;
|
||||||
|
else
|
||||||
|
free (message);
|
||||||
|
}
|
||||||
|
|
||||||
if (database)
|
if (database)
|
||||||
*database = notmuch;
|
*database = notmuch;
|
||||||
else
|
else
|
||||||
|
@ -1039,13 +1094,18 @@ notmuch_database_compact (const char *path,
|
||||||
notmuch_database_t *notmuch = NULL;
|
notmuch_database_t *notmuch = NULL;
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
notmuch_bool_t keep_backup;
|
notmuch_bool_t keep_backup;
|
||||||
|
char *message = NULL;
|
||||||
|
|
||||||
local = talloc_new (NULL);
|
local = talloc_new (NULL);
|
||||||
if (! local)
|
if (! local)
|
||||||
return NOTMUCH_STATUS_OUT_OF_MEMORY;
|
return NOTMUCH_STATUS_OUT_OF_MEMORY;
|
||||||
|
|
||||||
ret = notmuch_database_open (path, NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much);
|
ret = notmuch_database_open_verbose (path,
|
||||||
|
NOTMUCH_DATABASE_MODE_READ_WRITE,
|
||||||
|
¬much,
|
||||||
|
&message);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
if (status_cb) status_cb (message, closure);
|
||||||
goto DONE;
|
goto DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -229,6 +229,16 @@ typedef struct _notmuch_filenames notmuch_filenames_t;
|
||||||
notmuch_status_t
|
notmuch_status_t
|
||||||
notmuch_database_create (const char *path, notmuch_database_t **database);
|
notmuch_database_create (const char *path, notmuch_database_t **database);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like notmuch_database_create, except optionally return an error
|
||||||
|
* message. This message is allocated by malloc and should be freed by
|
||||||
|
* the caller.
|
||||||
|
*/
|
||||||
|
notmuch_status_t
|
||||||
|
notmuch_database_create_verbose (const char *path,
|
||||||
|
notmuch_database_t **database,
|
||||||
|
char **error_message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database open mode for notmuch_database_open.
|
* Database open mode for notmuch_database_open.
|
||||||
*/
|
*/
|
||||||
|
@ -279,6 +289,17 @@ notmuch_status_t
|
||||||
notmuch_database_open (const char *path,
|
notmuch_database_open (const char *path,
|
||||||
notmuch_database_mode_t mode,
|
notmuch_database_mode_t mode,
|
||||||
notmuch_database_t **database);
|
notmuch_database_t **database);
|
||||||
|
/**
|
||||||
|
* Like notmuch_database_open, except optionally return an error
|
||||||
|
* message. This message is allocated by malloc and should be freed by
|
||||||
|
* the caller.
|
||||||
|
*/
|
||||||
|
|
||||||
|
notmuch_status_t
|
||||||
|
notmuch_database_open_verbose (const char *path,
|
||||||
|
notmuch_database_mode_t mode,
|
||||||
|
notmuch_database_t **database,
|
||||||
|
char **error_message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commit changes and close the given notmuch database.
|
* Commit changes and close the given notmuch database.
|
||||||
|
|
|
@ -985,9 +985,16 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
add_files_state.total_files = count;
|
add_files_state.total_files = count;
|
||||||
} else {
|
} else {
|
||||||
if (notmuch_database_open (db_path, NOTMUCH_DATABASE_MODE_READ_WRITE,
|
char *status_string = NULL;
|
||||||
¬much))
|
if (notmuch_database_open_verbose (db_path, NOTMUCH_DATABASE_MODE_READ_WRITE,
|
||||||
|
¬much, &status_string)) {
|
||||||
|
if (status_string) {
|
||||||
|
fputs (status_string, stderr);
|
||||||
|
free (status_string);
|
||||||
|
}
|
||||||
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
if (notmuch_database_needs_upgrade (notmuch)) {
|
if (notmuch_database_needs_upgrade (notmuch)) {
|
||||||
time_t now = time (NULL);
|
time_t now = time (NULL);
|
||||||
|
|
|
@ -545,6 +545,7 @@ _notmuch_search_prepare (search_context_t *ctx, notmuch_config_t *config, int ar
|
||||||
{
|
{
|
||||||
char *query_str;
|
char *query_str;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
char *status_string = NULL;
|
||||||
|
|
||||||
switch (ctx->format_sel) {
|
switch (ctx->format_sel) {
|
||||||
case NOTMUCH_FORMAT_TEXT:
|
case NOTMUCH_FORMAT_TEXT:
|
||||||
|
@ -570,9 +571,17 @@ _notmuch_search_prepare (search_context_t *ctx, notmuch_config_t *config, int ar
|
||||||
|
|
||||||
notmuch_exit_if_unsupported_format ();
|
notmuch_exit_if_unsupported_format ();
|
||||||
|
|
||||||
if (notmuch_database_open (notmuch_config_get_database_path (config),
|
if (notmuch_database_open_verbose (
|
||||||
NOTMUCH_DATABASE_MODE_READ_ONLY, &ctx->notmuch))
|
notmuch_config_get_database_path (config),
|
||||||
|
NOTMUCH_DATABASE_MODE_READ_ONLY, &ctx->notmuch, &status_string)) {
|
||||||
|
|
||||||
|
if (status_string) {
|
||||||
|
fputs (status_string, stderr);
|
||||||
|
free (status_string);
|
||||||
|
}
|
||||||
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
query_str = query_string_from_args (ctx->notmuch, argc, argv);
|
query_str = query_string_from_args (ctx->notmuch, argc, argv);
|
||||||
if (query_str == NULL) {
|
if (query_str == NULL) {
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <xapian.h>
|
#include <xapian.h>
|
||||||
#include <notmuch.h>
|
#include <notmuch.h>
|
||||||
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
notmuch_database_t *notmuch;
|
notmuch_database_t *notmuch;
|
||||||
notmuch_database_open("fakedb", NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much);
|
char *message = NULL;
|
||||||
|
|
||||||
|
if (notmuch_database_open_verbose ("fakedb", NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much, &message))
|
||||||
|
if (message) {
|
||||||
|
fputs (message, stderr);
|
||||||
|
free (message);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
(void) new Xapian::WritableDatabase("./nonexistant", Xapian::DB_OPEN);
|
(void) new Xapian::WritableDatabase("./nonexistant", Xapian::DB_OPEN);
|
||||||
|
|
Loading…
Reference in a new issue