Support flexible database location

classic Classic list List threaded Threaded
24 messages Options
12
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

Support flexible database location

This series obsoletes and includes the series at [1]. It adds support
for configuring a seperate location for the mail files and the xapian
database. XDG compliant locations for the database are supported.

The notmuch-config and notmuch-setup commands still needed to be
updated to handle the new configuration possibilities.

[1]: id:[hidden email]


_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 01/23] lib: publish API for notmuch_database_reopen

Include the (currently unused) mode argument which will specify which
mode to re-open the database in. Functionality and docs to be
finalized in a followup commit.
---
 lib/database.cc       | 3 ++-
 lib/message.cc        | 3 ++-
 lib/notmuch-private.h | 3 ---
 lib/notmuch.h         | 7 +++++++
 4 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index f96ba7c0..89865599 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -516,7 +516,8 @@ notmuch_database_close (notmuch_database_t *notmuch)
 }
 
 notmuch_status_t
-_notmuch_database_reopen (notmuch_database_t *notmuch)
+notmuch_database_reopen (notmuch_database_t *notmuch,
+ unused(notmuch_database_mode_t mode))
 {
     if (_notmuch_database_mode (notmuch) != NOTMUCH_DATABASE_MODE_READ_ONLY)
  return NOTMUCH_STATUS_UNSUPPORTED_OPERATION;
diff --git a/lib/message.cc b/lib/message.cc
index fca99082..1bea90f0 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -455,7 +455,8 @@ _notmuch_message_ensure_metadata (notmuch_message_t *message, void *field)
     /* all the way without an exception */
     break;
  } catch (const Xapian::DatabaseModifiedError &error) {
-    notmuch_status_t status = _notmuch_database_reopen (message->notmuch);
+    notmuch_status_t status = notmuch_database_reopen (message->notmuch,
+       NOTMUCH_DATABASE_MODE_READ_ONLY);
     if (status != NOTMUCH_STATUS_SUCCESS)
  INTERNAL_ERROR ("unhandled error from notmuch_database_reopen: %s\n",
  notmuch_status_to_string (status));
diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index 2fbf7ab9..731757cc 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -206,9 +206,6 @@ _notmuch_message_id_compressed (void *ctx, const char *message_id);
 notmuch_status_t
 _notmuch_database_ensure_writable (notmuch_database_t *notmuch);
 
-notmuch_status_t
-_notmuch_database_reopen (notmuch_database_t *notmuch);
-
 void
 _notmuch_database_log (notmuch_database_t *notmuch,
        const char *format, ...);
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 5a5d99c0..0c13f607 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -879,6 +879,13 @@ notmuch_database_find_message_by_filename (notmuch_database_t *notmuch,
 notmuch_tags_t *
 notmuch_database_get_all_tags (notmuch_database_t *db);
 
+/**
+ * Reopen an open notmuch database.
+ *
+ */
+notmuch_status_t
+notmuch_database_reopen (notmuch_database_t *db, notmuch_database_mode_t mode);
+
 /**
  * Create a new query for 'database'.
  *
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 02/23] lib: save path of xapian database in notmuch struct.

In reply to this post by David Bremner-2
This will allow re-opening in a different mode (read/write
vs. read-only) with current Xapian API.
---
 lib/database-private.h |  4 ++++
 lib/open.cc            | 19 ++++++++++---------
 2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/lib/database-private.h b/lib/database-private.h
index d83cf0d0..d936b216 100644
--- a/lib/database-private.h
+++ b/lib/database-private.h
@@ -189,8 +189,12 @@ operator& (notmuch_field_flag_t a, notmuch_field_flag_t b)
 struct _notmuch_database {
     bool exception_reported;
 
+    /* Path to database parent directory and or/mail root */
     char *path;
 
+    /* Path to actual database */
+    const char *xapian_path;
+
     int atomic_nesting;
     /* true if changes have been made in this atomic section */
     bool atomic_dirty;
diff --git a/lib/open.cc b/lib/open.cc
index b4637ec5..2576424e 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -193,7 +193,7 @@ notmuch_database_open_with_config (const char *database_path,
     notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
     void *local = talloc_new (NULL);
     notmuch_database_t *notmuch = NULL;
-    char *notmuch_path, *xapian_path, *incompat_features;
+    char *notmuch_path, *incompat_features;
     char *message = NULL;
     struct stat st;
     int err;
@@ -218,12 +218,6 @@ notmuch_database_open_with_config (const char *database_path,
  goto DONE;
     }
 
-    if (! (xapian_path = talloc_asprintf (local, "%s/%s", notmuch_path, "xapian"))) {
- message = strdup ("Out of memory\n");
- status = NOTMUCH_STATUS_OUT_OF_MEMORY;
- goto DONE;
-    }
-
     /* Initialize the GLib type system and threads */
 #if ! GLIB_CHECK_VERSION (2, 35, 1)
     g_type_init ();
@@ -245,16 +239,23 @@ notmuch_database_open_with_config (const char *database_path,
     notmuch->writable_xapian_db = NULL;
     notmuch->atomic_nesting = 0;
     notmuch->view = 1;
+
+    if (! (notmuch->xapian_path = talloc_asprintf (notmuch, "%s/%s", notmuch_path, "xapian"))) {
+ message = strdup ("Out of memory\n");
+ status = NOTMUCH_STATUS_OUT_OF_MEMORY;
+ goto DONE;
+    }
+
     try {
  std::string last_thread_id;
  std::string last_mod;
 
  if (mode == NOTMUCH_DATABASE_MODE_READ_WRITE) {
-    notmuch->writable_xapian_db = new Xapian::WritableDatabase (xapian_path,
+    notmuch->writable_xapian_db = new Xapian::WritableDatabase (notmuch->xapian_path,
  DB_ACTION);
     notmuch->xapian_db = notmuch->writable_xapian_db;
  } else {
-    notmuch->xapian_db = new Xapian::Database (xapian_path);
+    notmuch->xapian_db = new Xapian::Database (notmuch->xapian_path);
  }
 
  /* Check version.  As of database version 3, we represent
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 03/23] lib: support reopening databases for write access.

In reply to this post by David Bremner-2
In the future xapian will apparently support this more conveniently
for the cases other than READ_ONLY => READ_ONLY
---
 lib/database.cc     |  23 --------
 lib/open.cc         |  40 ++++++++++++++
 test/T595-reopen.sh | 125 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 165 insertions(+), 23 deletions(-)
 create mode 100755 test/T595-reopen.sh

diff --git a/lib/database.cc b/lib/database.cc
index 89865599..b231a619 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -515,29 +515,6 @@ notmuch_database_close (notmuch_database_t *notmuch)
     return status;
 }
 
-notmuch_status_t
-notmuch_database_reopen (notmuch_database_t *notmuch,
- unused(notmuch_database_mode_t mode))
-{
-    if (_notmuch_database_mode (notmuch) != NOTMUCH_DATABASE_MODE_READ_ONLY)
- return NOTMUCH_STATUS_UNSUPPORTED_OPERATION;
-
-    try {
- notmuch->xapian_db->reopen ();
-    } catch (const Xapian::Error &error) {
- if (! notmuch->exception_reported) {
-    _notmuch_database_log (notmuch, "Error: A Xapian exception reopening database: %s\n",
-   error.get_msg ().c_str ());
-    notmuch->exception_reported = true;
- }
- return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
-    }
-
-    notmuch->view++;
-
-    return NOTMUCH_STATUS_SUCCESS;
-}
-
 static int
 unlink_cb (const char *path,
    unused (const struct stat *sb),
diff --git a/lib/open.cc b/lib/open.cc
index 2576424e..a927472e 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -495,3 +495,43 @@ notmuch_database_create_with_config (const char *database_path,
  talloc_free (notmuch);
     return status;
 }
+
+notmuch_status_t
+notmuch_database_reopen (notmuch_database_t *notmuch,
+ notmuch_database_mode_t new_mode)
+{
+    notmuch_database_mode_t cur_mode = _notmuch_database_mode (notmuch);
+    try {
+ if (cur_mode == new_mode &&
+    new_mode == NOTMUCH_DATABASE_MODE_READ_ONLY) {
+    notmuch->xapian_db->reopen ();
+ } else {
+    notmuch->xapian_db->close ();
+
+    delete notmuch->xapian_db;
+    notmuch->xapian_db = NULL;
+    /* no need to free the same object twice */
+    notmuch->writable_xapian_db = NULL;
+
+    if (new_mode == NOTMUCH_DATABASE_MODE_READ_WRITE) {
+ notmuch->writable_xapian_db = new Xapian::WritableDatabase (notmuch->xapian_path,
+    DB_ACTION);
+ notmuch->xapian_db = notmuch->writable_xapian_db;
+    } else {
+ notmuch->xapian_db = new Xapian::Database (notmuch->xapian_path,
+   DB_ACTION);
+    }
+ }
+    } catch (const Xapian::Error &error) {
+ if (! notmuch->exception_reported) {
+    _notmuch_database_log (notmuch, "Error: A Xapian exception reopening database: %s\n",
+   error.get_msg ().c_str ());
+    notmuch->exception_reported = true;
+ }
+ return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+    }
+
+    notmuch->view++;
+    return NOTMUCH_STATUS_SUCCESS;
+}
+
diff --git a/test/T595-reopen.sh b/test/T595-reopen.sh
new file mode 100755
index 00000000..7375e2ac
--- /dev/null
+++ b/test/T595-reopen.sh
@@ -0,0 +1,125 @@
+#!/usr/bin/env bash
+test_description="library reopen API"
+
+. $(dirname "$0")/test-lib.sh || exit 1
+
+add_email_corpus
+
+cat <<EOF > c_head
+#include <string.h>
+#include <stdlib.h>
+#include <notmuch-test.h>
+
+int main (int argc, char** argv)
+{
+   notmuch_database_t *db;
+   char *val;
+   notmuch_status_t stat;
+   notmuch_database_mode_t mode = NOTMUCH_DATABASE_MODE_READ_ONLY;
+
+   char *msg = NULL;
+
+   for (int i = 1; i < argc; i++)
+      if (strcmp (argv[i], "%NULL%") == 0) argv[i] = NULL;
+
+   if (argv[2] && (argv[2][0] == 'w' || argv[2][0] == 'W'))
+     mode = NOTMUCH_DATABASE_MODE_READ_WRITE;
+
+   stat = notmuch_database_open_with_config (argv[1],
+     mode,
+     argv[3],
+     argv[4],
+     &db,
+     &msg);
+   if (stat != NOTMUCH_STATUS_SUCCESS) {
+     fprintf (stderr, "error opening database: %d %s\n", stat, msg ? msg : "");
+     exit (1);
+   }
+EOF
+
+cat <<EOF > c_tail
+   EXPECT0(notmuch_database_destroy(db));
+}
+EOF
+
+# The sequence of tests is important here
+
+test_begin_subtest "notmuch_database_reopen (read=>write)"
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} read ${NOTMUCH_CONFIG}
+{
+   EXPECT0(notmuch_database_reopen (db, NOTMUCH_DATABASE_MODE_READ_WRITE));
+   EXPECT0(notmuch_database_set_config (db, "test.key1", "testvalue1"));
+   EXPECT0(notmuch_database_set_config (db, "test.key2", "testvalue2"));
+   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
+   printf("test.key1 = %s\n", val);
+   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
+   printf("test.key2 = %s\n", val);
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+test.key1 = testvalue1
+test.key2 = testvalue2
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "notmuch_database_reopen (read=>read)"
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} read ${NOTMUCH_CONFIG}
+{
+   EXPECT0(notmuch_database_reopen (db, NOTMUCH_DATABASE_MODE_READ_ONLY));
+   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
+   printf("test.key1 = %s\n", val);
+   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
+   printf("test.key2 = %s\n", val);
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+test.key1 = testvalue1
+test.key2 = testvalue2
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "notmuch_database_reopen (write=>read)"
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} write ${NOTMUCH_CONFIG}
+{
+   EXPECT0(notmuch_database_reopen (db, NOTMUCH_DATABASE_MODE_READ_ONLY));
+   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
+   printf("test.key1 = %s\n", val);
+   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
+   printf("test.key2 = %s\n", val);
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+test.key1 = testvalue1
+test.key2 = testvalue2
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "notmuch_database_reopen (write=>write)"
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} write ${NOTMUCH_CONFIG}
+{
+   EXPECT0(notmuch_database_reopen (db, NOTMUCH_DATABASE_MODE_READ_WRITE));
+   EXPECT0(notmuch_database_set_config (db, "test.key3", "testvalue3"));
+   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
+   printf("test.key1 = %s\n", val);
+   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
+   printf("test.key2 = %s\n", val);
+   EXPECT0(notmuch_database_get_config (db, "test.key3", &val));
+   printf("test.key3 = %s\n", val);
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+test.key1 = testvalue1
+test.key2 = testvalue2
+test.key3 = testvalue3
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_done
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 04/23] CLI/show: complete conversion to new configuration framework.

In reply to this post by David Bremner-2
In order to open the database in main() for this command, we may need
to re-open it in the (possibly less common) case where crypto options
require it.
---
 notmuch-show.c           | 26 +++++++-------------------
 notmuch.c                |  2 +-
 test/T035-read-config.sh |  2 --
 3 files changed, 8 insertions(+), 22 deletions(-)

diff --git a/notmuch-show.c b/notmuch-show.c
index c3c42caa..4a26f8ce 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -1215,9 +1215,8 @@ static const notmuch_show_format_t *formatters[] = {
 };
 
 int
-notmuch_show_command (notmuch_config_t *config, unused(notmuch_database_t *notmuch), int argc, char *argv[])
+notmuch_show_command (unused(notmuch_config_t *config), notmuch_database_t *notmuch, int argc, char *argv[])
 {
-    notmuch_database_t *notmuch;
     notmuch_query_t *query;
     char *query_string;
     int opt_index, ret;
@@ -1234,7 +1233,7 @@ notmuch_show_command (notmuch_config_t *config, unused(notmuch_database_t *notmu
     bool entire_thread_set = false;
     bool single_message;
     bool unthreaded = FALSE;
-    char *status_string = NULL;
+    notmuch_status_t status;
 
     notmuch_opt_desc_t options[] = {
  { .opt_keyword = &format, .name = "format", .keywords =
@@ -1324,25 +1323,14 @@ notmuch_show_command (notmuch_config_t *config, unused(notmuch_database_t *notmu
  fprintf (stderr, "Warning: --include-html only implemented for format=text, format=json and format=sexp\n");
     }
 
-    notmuch_database_mode_t mode = NOTMUCH_DATABASE_MODE_READ_ONLY;
-    if (params.crypto.decrypt == NOTMUCH_DECRYPT_TRUE)
- mode = NOTMUCH_DATABASE_MODE_READ_WRITE;
-    if (notmuch_database_open_with_config (NULL,
-   mode,
-   _notmuch_config_get_path (config),
-   NULL,
-   &notmuch,
-   &status_string)) {
- if (status_string) {
-    fputs (status_string, stderr);
-    free (status_string);
+    if (params.crypto.decrypt == NOTMUCH_DECRYPT_TRUE) {
+ status = notmuch_database_reopen (notmuch, NOTMUCH_DATABASE_MODE_READ_WRITE);
+ if (status) {
+    fprintf (stderr, "Error reopening database for READ_WRITE: %s\n", notmuch_status_to_string (status));
+    return EXIT_FAILURE;
  }
-
- return EXIT_FAILURE;
     }
 
-    config = NULL;
-
     notmuch_exit_if_unmatched_db_uuid (notmuch);
 
     query_string = query_string_from_args (notmuch, argc - opt_index, argv + opt_index);
diff --git a/notmuch.c b/notmuch.c
index 7360e0e6..71482e43 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -152,7 +152,7 @@ static command_t commands[] = {
       "Search for messages matching the given search terms." },
     { "address", notmuch_address_command, NOTMUCH_COMMAND_DATABASE_EARLY,
       "Get addresses from messages matching the given search terms." },
-    { "show", notmuch_show_command, NOTMUCH_COMMAND_CONFIG_OPEN,
+    { "show", notmuch_show_command, NOTMUCH_COMMAND_DATABASE_EARLY,
       "Show all messages matching the search terms." },
     { "count", notmuch_count_command, NOTMUCH_COMMAND_DATABASE_EARLY,
       "Count messages matching the search terms." },
diff --git a/test/T035-read-config.sh b/test/T035-read-config.sh
index 205d1736..ac0f420b 100755
--- a/test/T035-read-config.sh
+++ b/test/T035-read-config.sh
@@ -378,7 +378,6 @@ restore_database
 test_expect_equal "$output" "OK"
 
 test_begin_subtest "show with alternate config (xdg)"
-test_subtest_known_broken
 backup_database
 notmuch tag -- +foobar17 '*'
 xdg_config
@@ -389,7 +388,6 @@ restore_config
 test_expect_equal "$output" "OK"
 
 test_begin_subtest "show with alternate config (xdg+profile)"
-test_subtest_known_broken
 backup_database
 notmuch tag -- +foobar17 '*'
 xdg_config foobar17
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 05/23] lib/open: support NOTMUCH_DATABASE environment variable

In reply to this post by David Bremner-2
The additional code is trivial, but making sure we get the priority of
various options correct takes a few tests.
---
 lib/open.cc            |  4 +++
 test/T590-libconfig.sh | 67 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/lib/open.cc b/lib/open.cc
index a927472e..c200bed6 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -167,6 +167,10 @@ _choose_database_path (const char *config_path,
  return status;
     }
 
+    if (! *database_path) {
+       *database_path = getenv ("NOTMUCH_DATABASE");
+    }
+
     if (! *database_path && *key_file)
  *database_path = g_key_file_get_value (*key_file, "database", "path", NULL);
 
diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh
index e7e6e08a..4e510e97 100755
--- a/test/T590-libconfig.sh
+++ b/test/T590-libconfig.sh
@@ -27,7 +27,7 @@ int main (int argc, char** argv)
                                               &db,
                                               &msg);
    if (stat != NOTMUCH_STATUS_SUCCESS) {
-     fprintf (stderr, "error opening database: %d %s\n", stat, msg ? msg : "");
+     fprintf (stderr, "error opening database\n%s\n%s\n", notmuch_status_to_string (stat), msg ? msg : "");
      exit (1);
    }
 EOF
@@ -505,4 +505,69 @@ EOF
 test_expect_equal_file EXPECTED OUTPUT
 restore_database
 
+test_begin_subtest "no config, fail to open database"
+old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG}
+unset NOTMUCH_CONFIG
+cat c_head - c_tail <<'EOF' | test_C %NULL% '' %NULL%
+{
+   printf("NOT RUN");
+}
+EOF
+NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
+cat <<'EOF' >EXPECTED
+== stdout ==
+== stderr ==
+error opening database
+Erroneous NULL pointer
+Error: Cannot open a database for a NULL path.
+
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "open database from NOTMUCH_DATABASE"
+old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG}
+unset NOTMUCH_CONFIG
+export NOTMUCH_DATABASE=${MAIL_DIR}
+cat c_head - c_tail <<'EOF' | test_C %NULL% '' %NULL%
+{
+   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
+   printf("test.key1 = %s\n", val);
+   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
+   printf("test.key2 = %s\n", val);
+}
+EOF
+NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
+unset NOTMUCH_DATABASE
+cat <<'EOF' >EXPECTED
+== stdout ==
+test.key1 = testvalue1
+test.key2 = testvalue2
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "NOTMUCH_DATABASE overrides config"
+old_path=$(notmuch config get database.path)
+notmuch config set database.path /nonexistent
+export NOTMUCH_DATABASE=${MAIL_DIR}
+cat c_head - c_tail <<'EOF' | test_C %NULL% '' %NULL%
+{
+   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
+   printf("test.key1 = %s\n", val);
+   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
+   printf("test.key2 = %s\n", val);
+}
+EOF
+NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
+unset NOTMUCH_DATABASE
+cat <<'EOF' >EXPECTED
+== stdout ==
+test.key1 = testvalue1
+test.key2 = testvalue2
+== stderr ==
+EOF
+notmuch config set database.path "${old_path}"
+test_expect_equal_file EXPECTED OUTPUT
+
+
 test_done
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 06/23] lib/open: allocate notmuch_t struct early

In reply to this post by David Bremner-2
This gives more flexibility in restructuring the database opening
code.
---
 lib/open.cc | 46 +++++++++++++++++++++++++++++-----------------
 1 file changed, 29 insertions(+), 17 deletions(-)

diff --git a/lib/open.cc b/lib/open.cc
index c200bed6..09fec6e4 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -186,6 +186,20 @@ _choose_database_path (const char *config_path,
     return NOTMUCH_STATUS_SUCCESS;
 }
 
+notmuch_database_t * _alloc_notmuch() {
+    notmuch_database_t * notmuch;
+    notmuch = talloc_zero (NULL, notmuch_database_t);
+    if (!notmuch)
+ return NULL;
+
+    notmuch->exception_reported = false;
+    notmuch->status_string = NULL;
+    notmuch->writable_xapian_db = NULL;
+    notmuch->atomic_nesting = 0;
+    notmuch->view = 1;
+    return notmuch;
+}
+
 notmuch_status_t
 notmuch_database_open_with_config (const char *database_path,
    notmuch_database_mode_t mode,
@@ -205,9 +219,18 @@ notmuch_database_open_with_config (const char *database_path,
     GKeyFile *key_file = NULL;
     static int initialized = 0;
 
+    notmuch = _alloc_notmuch ();
+    if (!notmuch) {
+ status = NOTMUCH_STATUS_OUT_OF_MEMORY;
+ goto DONE;
+    }
+
     if ((status = _choose_database_path (config_path, profile, &key_file, &database_path, &message)))
  goto DONE;
 
+    notmuch->path = talloc_strdup (notmuch, database_path);
+    strip_trailing (notmuch->path, '/');
+
     if (! (notmuch_path = talloc_asprintf (local, "%s/%s", database_path, ".notmuch"))) {
  message = strdup ("Out of memory\n");
  status = NOTMUCH_STATUS_OUT_OF_MEMORY;
@@ -222,6 +245,12 @@ notmuch_database_open_with_config (const char *database_path,
  goto DONE;
     }
 
+    if (! (notmuch->xapian_path = talloc_asprintf (local, "%s/%s", notmuch_path, "xapian"))) {
+ message = strdup ("Out of memory\n");
+ status = NOTMUCH_STATUS_OUT_OF_MEMORY;
+ goto DONE;
+    }
+
     /* Initialize the GLib type system and threads */
 #if ! GLIB_CHECK_VERSION (2, 35, 1)
     g_type_init ();
@@ -233,23 +262,6 @@ notmuch_database_open_with_config (const char *database_path,
  initialized = 1;
     }
 
-    notmuch = talloc_zero (NULL, notmuch_database_t);
-    notmuch->exception_reported = false;
-    notmuch->status_string = NULL;
-    notmuch->path = talloc_strdup (notmuch, database_path);
-
-    strip_trailing (notmuch->path, '/');
-
-    notmuch->writable_xapian_db = NULL;
-    notmuch->atomic_nesting = 0;
-    notmuch->view = 1;
-
-    if (! (notmuch->xapian_path = talloc_asprintf (notmuch, "%s/%s", notmuch_path, "xapian"))) {
- message = strdup ("Out of memory\n");
- status = NOTMUCH_STATUS_OUT_OF_MEMORY;
- goto DONE;
-    }
-
     try {
  std::string last_thread_id;
  std::string last_mod;
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 07/23] support splitting mail from database location.

In reply to this post by David Bremner-2
Introduce a new configuration value for the mail root, and use it in
preference to the database.path (which previously implied the mail was
also in this location.

Multiple changes to the CLI and third party clients will be needed to
work in this split configuration.
---
 doc/man1/notmuch-config.rst | 14 +++++++--
 lib/config.cc               | 11 +++++--
 lib/database.cc             |  2 +-
 lib/message-file.c          |  2 +-
 lib/message.cc              |  2 +-
 lib/notmuch.h               |  1 +
 test/T055-path-config.sh    | 60 +++++++++++++++++++++++++++++++++++++
 test/T590-libconfig.sh      |  1 +
 8 files changed, 84 insertions(+), 9 deletions(-)
 create mode 100755 test/T055-path-config.sh

diff --git a/doc/man1/notmuch-config.rst b/doc/man1/notmuch-config.rst
index bc597957..ec8c10d5 100644
--- a/doc/man1/notmuch-config.rst
+++ b/doc/man1/notmuch-config.rst
@@ -43,12 +43,20 @@ configuration file and corresponding database.
 The available configuration items are described below.
 
 **database.path**
+    Notmuch will store its database within a
+    sub-directory of the path configured here named ``.notmuch``.
+
+    Default: ``$MAILDIR`` variable if set, otherwise ``$HOME/mail``.
+
+**database.mail_root**
     The top-level directory where your mail currently exists and to
     where mail will be delivered in the future. Files should be
-    individual email messages. Notmuch will store its database within
-    a sub-directory of the path configured here named ``.notmuch``.
+    individual email messages.
 
-    Default: ``$MAILDIR`` variable if set, otherwise ``$HOME/mail``.
+    History: this configuration value was introduced in notmuch 0.32.
+
+    Default: For compatibility with older configurations, the value of
+    database.path is used if database.mail\_root is unset..
 
 **database.hook_dir**
 
diff --git a/lib/config.cc b/lib/config.cc
index 948751bc..bfa6b4ae 100644
--- a/lib/config.cc
+++ b/lib/config.cc
@@ -390,6 +390,8 @@ _notmuch_config_key_to_string (notmuch_config_key_t key) {
     switch (key) {
     case NOTMUCH_CONFIG_DATABASE_PATH:
  return "database.path";
+    case NOTMUCH_CONFIG_MAIL_ROOT:
+ return "database.mail_root";
     case NOTMUCH_CONFIG_HOOK_DIR:
  return "database.hook_dir";
     case NOTMUCH_CONFIG_EXCLUDE_TAGS:
@@ -412,18 +414,21 @@ _notmuch_config_key_to_string (notmuch_config_key_t key) {
 }
 
 static const char *
-_notmuch_config_default (void *ctx, notmuch_config_key_t key) {
+_notmuch_config_default (notmuch_database_t *notmuch, notmuch_config_key_t key) {
     char *path;
 
     switch (key) {
     case NOTMUCH_CONFIG_DATABASE_PATH:
  path = getenv ("MAILDIR");
  if (path)
-    path = talloc_strdup (ctx, path);
+    path = talloc_strdup (notmuch, path);
  else
-    path = talloc_asprintf (ctx, "%s/mail",
+    path = talloc_asprintf (notmuch, "%s/mail",
     getenv ("HOME"));
  return path;
+    case NOTMUCH_CONFIG_MAIL_ROOT:
+ /* by default, mail root is the same as database path */
+ return notmuch_database_get_path (notmuch);
     case NOTMUCH_CONFIG_EXCLUDE_TAGS:
  return "";
     case NOTMUCH_CONFIG_NEW_TAGS:
diff --git a/lib/database.cc b/lib/database.cc
index b231a619..1fc3ce9c 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -1345,7 +1345,7 @@ _notmuch_database_relative_path (notmuch_database_t *notmuch,
     const char *db_path, *relative;
     unsigned int db_path_len;
 
-    db_path = notmuch_database_get_path (notmuch);
+    db_path = notmuch_config_get (notmuch, NOTMUCH_CONFIG_MAIL_ROOT);
     db_path_len = strlen (db_path);
 
     relative = path;
diff --git a/lib/message-file.c b/lib/message-file.c
index 311bd478..a23493f1 100644
--- a/lib/message-file.c
+++ b/lib/message-file.c
@@ -64,7 +64,7 @@ _notmuch_message_file_open_ctx (notmuch_database_t *notmuch,
     if (unlikely (message == NULL))
  return NULL;
 
-    const char *prefix = notmuch_database_get_path (notmuch);
+    const char *prefix = notmuch_config_get (notmuch, NOTMUCH_CONFIG_MAIL_ROOT);
     if (prefix == NULL)
  goto FAIL;
 
diff --git a/lib/message.cc b/lib/message.cc
index 1bea90f0..35f0b87a 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -1098,7 +1098,7 @@ _notmuch_message_ensure_filename_list (notmuch_message_t *message)
 
  *colon = '\0';
 
- db_path = notmuch_database_get_path (message->notmuch);
+ db_path = notmuch_config_get (message->notmuch, NOTMUCH_CONFIG_MAIL_ROOT);
 
  directory = _notmuch_database_get_directory_path (local,
   message->notmuch,
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 0c13f607..8fcd3eed 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -2467,6 +2467,7 @@ notmuch_config_list_destroy (notmuch_config_list_t *config_list);
 typedef enum _notmuch_config_key {
     NOTMUCH_CONFIG_FIRST,
     NOTMUCH_CONFIG_DATABASE_PATH = NOTMUCH_CONFIG_FIRST,
+    NOTMUCH_CONFIG_MAIL_ROOT,
     NOTMUCH_CONFIG_HOOK_DIR,
     NOTMUCH_CONFIG_EXCLUDE_TAGS,
     NOTMUCH_CONFIG_NEW_TAGS,
diff --git a/test/T055-path-config.sh b/test/T055-path-config.sh
new file mode 100755
index 00000000..54c337ef
--- /dev/null
+++ b/test/T055-path-config.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+test_description='Configuration of mail-root and database path'
+. $(dirname "$0")/test-lib.sh || exit 1
+
+backup_config () {
+    local test_name=$(basename $0 .sh)
+    cp ${NOTMUCH_CONFIG} notmuch-config-backup.${test_name}
+}
+
+restore_config () {
+    local test_name=$(basename $0 .sh)
+    export NOTMUCH_CONFIG="${TMP_DIRECTORY}/notmuch-config"
+    unset CONFIG_PATH
+    unset DATABASE_PATH
+    unset NOTMUCH_PROFILE
+    cp notmuch-config-backup.${test_name} ${NOTMUCH_CONFIG}
+}
+
+split_config () {
+    local dir
+    backup_config
+    dir="$TMP_DIRECTORY/database.$test_count"
+    rm -rf $dir
+    mkdir $dir
+    notmuch config set database.path $dir
+    notmuch config set database.mail_root $MAIL_DIR
+    DATABASE_PATH=$dir
+}
+
+add_email_corpus
+
+for config in traditional split+prefix; do
+    backup_database
+
+    case $config in
+ traditional)
+    backup_config
+    ;;
+ split+prefix)
+    split_config
+    mv mail/.notmuch $DATABASE_PATH
+    ;;
+    esac
+
+    test_begin_subtest "count ($config)"
+    output=$(notmuch count '*')
+    test_expect_equal "$output" '52'
+
+    test_begin_subtest "count+tag ($config)"
+    tag="tag${RANDOM}"
+    notmuch tag +$tag '*'
+    output=$(notmuch count tag:$tag)
+    notmuch tag -$tag '*'
+    test_expect_equal "$output" '52'
+
+    restore_config
+    restore_database
+done
+
+test_done
diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh
index 4e510e97..5cf70987 100755
--- a/test/T590-libconfig.sh
+++ b/test/T590-libconfig.sh
@@ -364,6 +364,7 @@ EOF
 cat <<'EOF' >EXPECTED
 == stdout ==
 MAIL_DIR
+MAIL_DIR
 MAIL_DIR/.notmuch/hooks
 
 inbox;unread
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 08/23] support splitting mail from database location.

In reply to this post by David Bremner-2
Introduce a new configuration value for the mail root, and use it in
preference to the database.path (which previously implied the mail was
also in this location.

Multiple changes to the CLI and third party clients will be needed to
work in this split configuration.
---
 test/T055-path-config.sh | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/test/T055-path-config.sh b/test/T055-path-config.sh
index 54c337ef..1da0e9fe 100755
--- a/test/T055-path-config.sh
+++ b/test/T055-path-config.sh
@@ -27,10 +27,11 @@ split_config () {
     DATABASE_PATH=$dir
 }
 
-add_email_corpus
+
 
 for config in traditional split+prefix; do
-    backup_database
+    # start each set of tests with a known set of messages
+    add_email_corpus
 
     case $config in
  traditional)
@@ -54,7 +55,6 @@ for config in traditional split+prefix; do
     test_expect_equal "$output" '52'
 
     restore_config
-    restore_database
 done
 
 test_done
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 09/23] lib/open: factor out library intialization

In reply to this post by David Bremner-2
This is slightly more tidy, but more importantly it allows for re-use
of this code in n_d_create_with_config
---
 lib/open.cc | 29 ++++++++++++++++++-----------
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/lib/open.cc b/lib/open.cc
index 09fec6e4..ff298030 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -200,6 +200,22 @@ notmuch_database_t * _alloc_notmuch() {
     return notmuch;
 }
 
+static void _init_libs () {
+
+    static int initialized = 0;
+
+    /* Initialize the GLib type system and threads */
+#if ! GLIB_CHECK_VERSION (2, 35, 1)
+    g_type_init ();
+#endif
+
+    /* Initialize gmime */
+    if (! initialized) {
+ g_mime_init ();
+ initialized = 1;
+    }
+}
+
 notmuch_status_t
 notmuch_database_open_with_config (const char *database_path,
    notmuch_database_mode_t mode,
@@ -219,6 +235,8 @@ notmuch_database_open_with_config (const char *database_path,
     GKeyFile *key_file = NULL;
     static int initialized = 0;
 
+    _init_libs ();
+
     notmuch = _alloc_notmuch ();
     if (!notmuch) {
  status = NOTMUCH_STATUS_OUT_OF_MEMORY;
@@ -251,17 +269,6 @@ notmuch_database_open_with_config (const char *database_path,
  goto DONE;
     }
 
-    /* Initialize the GLib type system and threads */
-#if ! GLIB_CHECK_VERSION (2, 35, 1)
-    g_type_init ();
-#endif
-
-    /* Initialize gmime */
-    if (! initialized) {
- g_mime_init ();
- initialized = 1;
-    }
-
     try {
  std::string last_thread_id;
  std::string last_mod;
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 10/23] lib/open: factor out the second half of n_d_open_with_config

In reply to this post by David Bremner-2
The idea is to allow reuse in n_d_create_with_config. This is
primarily code movement, with some changes in error messages to reduce
the number of input parameters.
---
 lib/open.cc | 118 +++++++++++++++++++++++++++++-----------------------
 1 file changed, 67 insertions(+), 51 deletions(-)

diff --git a/lib/open.cc b/lib/open.cc
index ff298030..74fac37d 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -216,58 +216,17 @@ static void _init_libs () {
     }
 }
 
-notmuch_status_t
-notmuch_database_open_with_config (const char *database_path,
-   notmuch_database_mode_t mode,
-   const char *config_path,
-   unused(const char *profile),
-   notmuch_database_t **database,
-   char **status_string)
+static notmuch_status_t
+_finish_open (notmuch_database_t *notmuch,
+      const char *profile,
+      notmuch_database_mode_t mode,
+      GKeyFile *key_file,
+      char **message_ptr)
 {
     notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
-    void *local = talloc_new (NULL);
-    notmuch_database_t *notmuch = NULL;
-    char *notmuch_path, *incompat_features;
+    char *incompat_features;
     char *message = NULL;
-    struct stat st;
-    int err;
     unsigned int version;
-    GKeyFile *key_file = NULL;
-    static int initialized = 0;
-
-    _init_libs ();
-
-    notmuch = _alloc_notmuch ();
-    if (!notmuch) {
- status = NOTMUCH_STATUS_OUT_OF_MEMORY;
- goto DONE;
-    }
-
-    if ((status = _choose_database_path (config_path, profile, &key_file, &database_path, &message)))
- goto DONE;
-
-    notmuch->path = talloc_strdup (notmuch, database_path);
-    strip_trailing (notmuch->path, '/');
-
-    if (! (notmuch_path = talloc_asprintf (local, "%s/%s", database_path, ".notmuch"))) {
- message = strdup ("Out of memory\n");
- status = NOTMUCH_STATUS_OUT_OF_MEMORY;
- goto DONE;
-    }
-
-    err = stat (notmuch_path, &st);
-    if (err) {
- IGNORE_RESULT (asprintf (&message, "Error opening database at %s: %s\n",
- notmuch_path, strerror (errno)));
- status = NOTMUCH_STATUS_FILE_ERROR;
- goto DONE;
-    }
-
-    if (! (notmuch->xapian_path = talloc_asprintf (local, "%s/%s", notmuch_path, "xapian"))) {
- message = strdup ("Out of memory\n");
- status = NOTMUCH_STATUS_OUT_OF_MEMORY;
- goto DONE;
-    }
 
     try {
  std::string last_thread_id;
@@ -290,7 +249,7 @@ notmuch_database_open_with_config (const char *database_path,
      "Error: Notmuch database at %s\n"
      "       has a newer database format version (%u) than supported by this\n"
      "       version of notmuch (%u).\n",
-     notmuch_path, version, NOTMUCH_DATABASE_VERSION));
+     notmuch->path, version, NOTMUCH_DATABASE_VERSION));
     notmuch_database_destroy (notmuch);
     notmuch = NULL;
     status = NOTMUCH_STATUS_FILE_ERROR;
@@ -300,7 +259,7 @@ notmuch_database_open_with_config (const char *database_path,
  /* Check features. */
  incompat_features = NULL;
  notmuch->features = _notmuch_database_parse_features (
-    local, notmuch->xapian_db->get_metadata ("features").c_str (),
+    notmuch, notmuch->xapian_db->get_metadata ("features").c_str (),
     version, mode == NOTMUCH_DATABASE_MODE_READ_WRITE ? 'w' : 'r',
     &incompat_features);
  if (incompat_features) {
@@ -308,7 +267,7 @@ notmuch_database_open_with_config (const char *database_path,
      "Error: Notmuch database at %s\n"
      "       requires features (%s)\n"
      "       not supported by this version of notmuch.\n",
-     notmuch_path, incompat_features));
+     notmuch->path, incompat_features));
     notmuch_database_destroy (notmuch);
     notmuch = NULL;
     status = NOTMUCH_STATUS_FILE_ERROR;
@@ -386,6 +345,63 @@ notmuch_database_open_with_config (const char *database_path,
  notmuch = NULL;
  status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
     }
+ DONE:
+    if (message_ptr)
+ *message_ptr = message;
+    return status;
+}
+
+notmuch_status_t
+notmuch_database_open_with_config (const char *database_path,
+   notmuch_database_mode_t mode,
+   const char *config_path,
+   unused(const char *profile),
+   notmuch_database_t **database,
+   char **status_string)
+{
+    notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
+    void *local = talloc_new (NULL);
+    notmuch_database_t *notmuch = NULL;
+    char *notmuch_path;
+    char *message = NULL;
+    struct stat st;
+    int err;
+    GKeyFile *key_file = NULL;
+
+    _init_libs ();
+
+    notmuch = _alloc_notmuch ();
+    if (!notmuch) {
+ status = NOTMUCH_STATUS_OUT_OF_MEMORY;
+ goto DONE;
+    }
+
+    if ((status = _choose_database_path (config_path, profile, &key_file, &database_path, &message)))
+ goto DONE;
+
+    notmuch->path = talloc_strdup (notmuch, database_path);
+    strip_trailing (notmuch->path, '/');
+
+    if (! (notmuch_path = talloc_asprintf (local, "%s/%s", database_path, ".notmuch"))) {
+ message = strdup ("Out of memory\n");
+ status = NOTMUCH_STATUS_OUT_OF_MEMORY;
+ goto DONE;
+    }
+
+    err = stat (notmuch_path, &st);
+    if (err) {
+ IGNORE_RESULT (asprintf (&message, "Error opening database at %s: %s\n",
+ notmuch_path, strerror (errno)));
+ status = NOTMUCH_STATUS_FILE_ERROR;
+ goto DONE;
+    }
+
+    if (! (notmuch->xapian_path = talloc_asprintf (notmuch, "%s/%s", notmuch_path, "xapian"))) {
+ status = NOTMUCH_STATUS_OUT_OF_MEMORY;
+ goto DONE;
+    }
+
+    status = _finish_open (notmuch, profile, mode, key_file, &message);
 
   DONE:
     talloc_free (local);
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 11/23] lib/open: use _finish_open in n_d_create_with_config

In reply to this post by David Bremner-2
This avoids reading the configuration file twice.
---
 lib/open.cc | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/lib/open.cc b/lib/open.cc
index 74fac37d..f4690763 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -459,14 +459,25 @@ notmuch_database_create_with_config (const char *database_path,
     notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
     notmuch_database_t *notmuch = NULL;
     char *notmuch_path = NULL;
+    char *xapian_path = NULL;
     char *message = NULL;
     GKeyFile *key_file = NULL;
     struct stat st;
     int err;
+    void *local = talloc_new (NULL);
+
+    notmuch = _alloc_notmuch ();
+    if (! notmuch) {
+ status = NOTMUCH_STATUS_OUT_OF_MEMORY;
+ goto DONE;
+    }
 
     if ((status = _choose_database_path (config_path, profile, &key_file, &database_path, &message)))
  goto DONE;
 
+    notmuch->path = talloc_strdup (notmuch, database_path);
+    strip_trailing (notmuch->path, '/');
+
     err = stat (database_path, &st);
     if (err) {
  IGNORE_RESULT (asprintf (&message, "Error: Cannot create database at %s: %s.\n",
@@ -483,12 +494,14 @@ notmuch_database_create_with_config (const char *database_path,
  goto DONE;
     }
 
-    notmuch_path = talloc_asprintf (NULL, "%s/%s", database_path, ".notmuch");
+    notmuch_path = talloc_asprintf (local, "%s/%s", database_path, ".notmuch");
 
     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)));
@@ -497,12 +510,16 @@ notmuch_database_create_with_config (const char *database_path,
  goto DONE;
     }
 
-    /* XXX this reads the config file twice, which is a bit wasteful */
-    status = notmuch_database_open_with_config (database_path,
- NOTMUCH_DATABASE_MODE_READ_WRITE,
- config_path,
- profile,
- &notmuch, &message);
+    if (! (notmuch->xapian_path = talloc_asprintf (notmuch, "%s/%s", notmuch_path, "xapian"))) {
+ status = NOTMUCH_STATUS_OUT_OF_MEMORY;
+ goto DONE;
+    }
+
+    status = _finish_open (notmuch,
+   profile,
+   NOTMUCH_DATABASE_MODE_READ_WRITE,
+   key_file,
+   &message);
     if (status)
  goto DONE;
 
@@ -519,8 +536,7 @@ notmuch_database_create_with_config (const char *database_path,
     }
 
   DONE:
-    if (notmuch_path)
- talloc_free (notmuch_path);
+    talloc_free(local);
 
     if (message) {
  if (status_string)
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 12/23] lib/open: reuse directory checks from n_d_c_with_config

In reply to this post by David Bremner-2
Make checks more uniform between creating new databases and opening
existing ones.
---
 lib/open.cc            | 50 +++++++++++++++++++++++++++---------------
 test/T560-lib-error.sh |  4 ++--
 2 files changed, 34 insertions(+), 20 deletions(-)

diff --git a/lib/open.cc b/lib/open.cc
index f4690763..b5a56e73 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -152,6 +152,29 @@ DONE:
     return status;
 }
 
+static notmuch_status_t
+_db_dir_exists (const char *database_path, char **message)
+{
+    struct stat st;
+    int err;
+
+    err = stat (database_path, &st);
+    if (err) {
+ IGNORE_RESULT (asprintf (message, "Error: Cannot open database at %s: %s.\n",
+ database_path, strerror (errno)));
+ return NOTMUCH_STATUS_FILE_ERROR;
+    }
+
+    if (! S_ISDIR (st.st_mode)) {
+ IGNORE_RESULT (asprintf (message, "Error: Cannot open database at %s: "
+ "Not a directory.\n",
+ database_path));
+ return NOTMUCH_STATUS_FILE_ERROR;
+    }
+
+    return NOTMUCH_STATUS_SUCCESS;
+}
+
 static notmuch_status_t
 _choose_database_path (const char *config_path,
        const char *profile,
@@ -379,6 +402,10 @@ notmuch_database_open_with_config (const char *database_path,
     if ((status = _choose_database_path (config_path, profile, &key_file, &database_path, &message)))
  goto DONE;
 
+    status = _db_dir_exists (database_path, &message);
+    if (status)
+ goto DONE;
+
     notmuch->path = talloc_strdup (notmuch, database_path);
     strip_trailing (notmuch->path, '/');
 
@@ -462,9 +489,8 @@ notmuch_database_create_with_config (const char *database_path,
     char *xapian_path = NULL;
     char *message = NULL;
     GKeyFile *key_file = NULL;
-    struct stat st;
-    int err;
     void *local = talloc_new (NULL);
+    int err;
 
     notmuch = _alloc_notmuch ();
     if (! notmuch) {
@@ -475,24 +501,12 @@ notmuch_database_create_with_config (const char *database_path,
     if ((status = _choose_database_path (config_path, profile, &key_file, &database_path, &message)))
  goto DONE;
 
-    notmuch->path = talloc_strdup (notmuch, database_path);
-    strip_trailing (notmuch->path, '/');
-
-    err = stat (database_path, &st);
-    if (err) {
- IGNORE_RESULT (asprintf (&message, "Error: Cannot create database at %s: %s.\n",
- database_path, strerror (errno)));
- status = NOTMUCH_STATUS_FILE_ERROR;
+    status = _db_dir_exists (database_path, &message);
+    if (status)
  goto DONE;
-    }
 
-    if (! S_ISDIR (st.st_mode)) {
- IGNORE_RESULT (asprintf (&message, "Error: Cannot create database at %s: "
- "Not a directory.\n",
- database_path));
- status = NOTMUCH_STATUS_FILE_ERROR;
- goto DONE;
-    }
+    notmuch->path = talloc_strdup (notmuch, database_path);
+    strip_trailing (notmuch->path, '/');
 
     notmuch_path = talloc_asprintf (local, "%s/%s", database_path, ".notmuch");
 
diff --git a/test/T560-lib-error.sh b/test/T560-lib-error.sh
index ade376ef..03df69d9 100755
--- a/test/T560-lib-error.sh
+++ b/test/T560-lib-error.sh
@@ -76,7 +76,7 @@ EOF
 cat <<'EOF' >EXPECTED
 == stdout ==
 == stderr ==
-Error opening database at CWD/nonexistent/foo/.notmuch: No such file or directory
+Error: Cannot open database at CWD/nonexistent/foo: No such file or directory.
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
@@ -111,7 +111,7 @@ EOF
 cat <<'EOF' >EXPECTED
 == stdout ==
 == stderr ==
-Error: Cannot create database at CWD/nonexistent/foo: No such file or directory.
+Error: Cannot open database at CWD/nonexistent/foo: No such file or directory.
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 13/23] lib/open: open existing databases without .notmuch in path

In reply to this post by David Bremner-2
In a split configuration, it does not make sense to have the extra
.notmuch/ directory. Leave the xapian/ level of the path to allow the
use of the top level e.g. as a place to store backups as is currently
done by upgrade code in notmuch-new.
---
 lib/open.cc                | 71 +++++++++++++++++++++++++++-----------
 test/T030-config.sh        |  2 +-
 test/T055-path-config.sh   |  5 ++-
 test/T360-symbol-hiding.sh |  2 +-
 test/T750-user-header.sh   |  2 +-
 5 files changed, 57 insertions(+), 25 deletions(-)

diff --git a/lib/open.cc b/lib/open.cc
index b5a56e73..887bc44d 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -223,6 +223,54 @@ notmuch_database_t * _alloc_notmuch() {
     return notmuch;
 }
 
+static notmuch_status_t
+_trial_open (const char *xapian_path, char **message_ptr)
+{
+    try {
+ Xapian::Database db(xapian_path);
+    } catch (const Xapian::DatabaseOpeningError &error) {
+ IGNORE_RESULT (asprintf (message_ptr,
+ "Cannot open Xapian database at %s: %s\n",
+ xapian_path,
+ error.get_msg ().c_str ()));
+ return NOTMUCH_STATUS_PATH_ERROR;
+    } catch (const Xapian::Error &error) {
+ IGNORE_RESULT (asprintf (message_ptr,
+ "A Xapian exception occurred opening database: %s\n",
+ error.get_msg ().c_str ()));
+       return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+    }
+    return NOTMUCH_STATUS_SUCCESS;
+}
+
+static notmuch_status_t
+_choose_xapian_path (void *ctx, const char *database_path, const char **xapian_path, char **message_ptr){
+    notmuch_status_t status;
+    const char *trial_path, *notmuch_path;
+
+    status = _db_dir_exists (database_path, message_ptr);
+    if (status)
+ goto DONE;
+
+    trial_path = talloc_asprintf (ctx, "%s/xapian", database_path);
+    status = _trial_open (trial_path, message_ptr);
+    if (status != NOTMUCH_STATUS_PATH_ERROR)
+ goto DONE;
+
+    notmuch_path = talloc_asprintf (ctx, "%s/.notmuch", database_path);
+    status = _db_dir_exists (notmuch_path, message_ptr);
+    if (status)
+ goto DONE;
+
+    trial_path = talloc_asprintf (ctx, "%s/xapian", notmuch_path);
+    status = _trial_open (trial_path, message_ptr);
+
+ DONE:
+    if (status == NOTMUCH_STATUS_SUCCESS)
+ *xapian_path = trial_path;
+    return status;
+}
+
 static void _init_libs () {
 
     static int initialized = 0;
@@ -385,10 +433,7 @@ notmuch_database_open_with_config (const char *database_path,
     notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
     void *local = talloc_new (NULL);
     notmuch_database_t *notmuch = NULL;
-    char *notmuch_path;
     char *message = NULL;
-    struct stat st;
-    int err;
     GKeyFile *key_file = NULL;
 
     _init_libs ();
@@ -409,24 +454,9 @@ notmuch_database_open_with_config (const char *database_path,
     notmuch->path = talloc_strdup (notmuch, database_path);
     strip_trailing (notmuch->path, '/');
 
-    if (! (notmuch_path = talloc_asprintf (local, "%s/%s", database_path, ".notmuch"))) {
- message = strdup ("Out of memory\n");
- status = NOTMUCH_STATUS_OUT_OF_MEMORY;
- goto DONE;
-    }
-
-    err = stat (notmuch_path, &st);
-    if (err) {
- IGNORE_RESULT (asprintf (&message, "Error opening database at %s: %s\n",
- notmuch_path, strerror (errno)));
- status = NOTMUCH_STATUS_FILE_ERROR;
- goto DONE;
-    }
-
-    if (! (notmuch->xapian_path = talloc_asprintf (notmuch, "%s/%s", notmuch_path, "xapian"))) {
- status = NOTMUCH_STATUS_OUT_OF_MEMORY;
+    status = _choose_xapian_path (local, database_path, &notmuch->xapian_path, &message);
+    if (status)
  goto DONE;
-    }
 
     status = _finish_open (notmuch, profile, mode, key_file, &message);
 
@@ -486,7 +516,6 @@ notmuch_database_create_with_config (const char *database_path,
     notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
     notmuch_database_t *notmuch = NULL;
     char *notmuch_path = NULL;
-    char *xapian_path = NULL;
     char *message = NULL;
     GKeyFile *key_file = NULL;
     void *local = talloc_new (NULL);
diff --git a/test/T030-config.sh b/test/T030-config.sh
index 883541d5..67c9545c 100755
--- a/test/T030-config.sh
+++ b/test/T030-config.sh
@@ -61,7 +61,7 @@ built_with.compact=something
 built_with.field_processor=something
 built_with.retry_lock=something
 ====
-Error opening database at MAIL_DIR/.notmuch: No such file or directory
+Error: Cannot open database at MAIL_DIR/.notmuch: No such file or directory.
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
diff --git a/test/T055-path-config.sh b/test/T055-path-config.sh
index 1da0e9fe..59b12337 100755
--- a/test/T055-path-config.sh
+++ b/test/T055-path-config.sh
@@ -28,7 +28,6 @@ split_config () {
 }
 
 
-
 for config in traditional split+prefix; do
     # start each set of tests with a known set of messages
     add_email_corpus
@@ -41,6 +40,10 @@ for config in traditional split+prefix; do
     split_config
     mv mail/.notmuch $DATABASE_PATH
     ;;
+ split)
+    split_config
+    mv mail/.notmuch/xapian $DATABASE_PATH
+    ;;
     esac
 
     test_begin_subtest "count ($config)"
diff --git a/test/T360-symbol-hiding.sh b/test/T360-symbol-hiding.sh
index 729b9d72..642457bf 100755
--- a/test/T360-symbol-hiding.sh
+++ b/test/T360-symbol-hiding.sh
@@ -17,7 +17,7 @@ $TEST_DIRECTORY/symbol-test ${PWD}/fakedb ${PWD}/nonexistent 2>&1 \
  | notmuch_dir_sanitize | sed -e "s,\`,\',g" -e "s,No [^[:space:]]* database,No XXXXXX database,g" > OUTPUT
 
 cat <<EOF > EXPECTED
-A Xapian exception occurred opening database: Couldn't stat 'CWD/fakedb/.notmuch/xapian'
+Cannot open Xapian database at CWD/fakedb/.notmuch/xapian: Couldn't stat 'CWD/fakedb/.notmuch/xapian'
 caught No XXXXXX database found at path 'CWD/nonexistent'
 EOF
 test_expect_equal_file EXPECTED OUTPUT
diff --git a/test/T750-user-header.sh b/test/T750-user-header.sh
index ff554b06..b19db571 100755
--- a/test/T750-user-header.sh
+++ b/test/T750-user-header.sh
@@ -5,7 +5,7 @@ test_description='indexing user specified headers'
 test_begin_subtest "error adding user header before initializing DB"
 notmuch config set index.header.List List-Id 2>&1 | notmuch_dir_sanitize > OUTPUT
 cat <<EOF > EXPECTED
-Error opening database at MAIL_DIR/.notmuch: No such file or directory
+Error: Cannot open database at MAIL_DIR/.notmuch: No such file or directory.
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 14/23] lib/open: support XDG_DATA_HOME as a fallback database location.

In reply to this post by David Bremner-2
This changes some error reporting, either intentionally by reporting
the highest level missing directory, or by side effect from looking in
XDG locations when given null database location.
---
 lib/open.cc              | 60 ++++++++++++++++++++++++++++------------
 test/T055-path-config.sh | 34 +++++++++++++++++++++--
 test/T560-lib-error.sh   |  4 +--
 test/T590-libconfig.sh   |  4 +--
 4 files changed, 79 insertions(+), 23 deletions(-)

diff --git a/lib/open.cc b/lib/open.cc
index 887bc44d..efb0d6a3 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -176,10 +176,12 @@ _db_dir_exists (const char *database_path, char **message)
 }
 
 static notmuch_status_t
-_choose_database_path (const char *config_path,
+_choose_database_path (void * ctx,
+                       const char *config_path,
        const char *profile,
        GKeyFile **key_file,
        const char **database_path,
+       bool *split,
        char **message)
 {
     notmuch_status_t status;
@@ -197,6 +199,11 @@ _choose_database_path (const char *config_path,
     if (! *database_path && *key_file)
  *database_path = g_key_file_get_value (*key_file, "database", "path", NULL);
 
+    if (! *database_path) {
+ *database_path = _xdg_dir (ctx, "XDG_DATA_HOME", ".local/share", profile);
+ *split = true;
+    }
+
     if (*database_path == NULL) {
  *message = strdup ("Error: Cannot open a database for a NULL path.\n");
  return NOTMUCH_STATUS_NULL_POINTER;
@@ -435,6 +442,7 @@ notmuch_database_open_with_config (const char *database_path,
     notmuch_database_t *notmuch = NULL;
     char *message = NULL;
     GKeyFile *key_file = NULL;
+    bool split = false;
 
     _init_libs ();
 
@@ -444,7 +452,9 @@ notmuch_database_open_with_config (const char *database_path,
  goto DONE;
     }
 
-    if ((status = _choose_database_path (config_path, profile, &key_file, &database_path, &message)))
+    if ((status = _choose_database_path (local, config_path, profile,
+ &key_file, &database_path, &split,
+ &message)))
  goto DONE;
 
     status = _db_dir_exists (database_path, &message);
@@ -515,11 +525,12 @@ notmuch_database_create_with_config (const char *database_path,
 {
     notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
     notmuch_database_t *notmuch = NULL;
-    char *notmuch_path = NULL;
+    const char *notmuch_path = NULL;
     char *message = NULL;
     GKeyFile *key_file = NULL;
     void *local = talloc_new (NULL);
     int err;
+    bool split = false;
 
     notmuch = _alloc_notmuch ();
     if (! notmuch) {
@@ -527,7 +538,9 @@ notmuch_database_create_with_config (const char *database_path,
  goto DONE;
     }
 
-    if ((status = _choose_database_path (config_path, profile, &key_file, &database_path, &message)))
+    if ((status = _choose_database_path (local, config_path, profile,
+ &key_file, &database_path, &split,
+ &message)))
  goto DONE;
 
     status = _db_dir_exists (database_path, &message);
@@ -537,22 +550,35 @@ notmuch_database_create_with_config (const char *database_path,
     notmuch->path = talloc_strdup (notmuch, database_path);
     strip_trailing (notmuch->path, '/');
 
-    notmuch_path = talloc_asprintf (local, "%s/%s", database_path, ".notmuch");
+    if (key_file && !split) {
+ const char *mail_root = g_key_file_get_value (key_file, "database", "mail_root", NULL);
+ /* XXX compare canonicalized versions */
+ split = (mail_root && (0 != strcmp (mail_root, database_path)));
+    }
 
-    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;
+    if (split) {
+ notmuch_path = database_path;
+    } else {
+ if (! (notmuch_path = talloc_asprintf (local, "%s/%s", database_path, ".notmuch"))) {
+    status = NOTMUCH_STATUS_OUT_OF_MEMORY;
+    goto DONE;
  }
- 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;
+    }
+    goto DONE;
+ }
+    }
     if (! (notmuch->xapian_path = talloc_asprintf (notmuch, "%s/%s", notmuch_path, "xapian"))) {
  status = NOTMUCH_STATUS_OUT_OF_MEMORY;
  goto DONE;
diff --git a/test/T055-path-config.sh b/test/T055-path-config.sh
index 59b12337..c82b6a14 100755
--- a/test/T055-path-config.sh
+++ b/test/T055-path-config.sh
@@ -27,9 +27,31 @@ split_config () {
     DATABASE_PATH=$dir
 }
 
+xdg_config () {
+    local dir
+    local profile=${1:-default}
+
+    if [[ $profile != default ]]; then
+ export NOTMUCH_PROFILE=$profile
+    fi
+
+    backup_config
+    DATABASE_PATH="${HOME}/.local/share/notmuch/${profile}"
+    rm -rf $DATABASE_PATH
+    mkdir -p $DATABASE_PATH
+
+    config_dir="${HOME}/.config/notmuch/${profile}"
+    mkdir -p ${config_dir}
+    CONFIG_PATH=$config_dir/config
+    mv ${NOTMUCH_CONFIG} $CONFIG_PATH
+    unset NOTMUCH_CONFIG
 
-for config in traditional split+prefix; do
-    # start each set of tests with a known set of messages
+    notmuch --config=${CONFIG_PATH} config set database.mail_root ${TMP_DIRECTORY}/mail
+    notmuch --config=${CONFIG_PATH} config set database.path
+}
+
+for config in traditional split+prefix split XDG XDG+profile; do
+    #start each set of tests with an known set of messages
     add_email_corpus
 
     case $config in
@@ -44,6 +66,14 @@ for config in traditional split+prefix; do
     split_config
     mv mail/.notmuch/xapian $DATABASE_PATH
     ;;
+ XDG)
+    xdg_config
+    mv mail/.notmuch/xapian $DATABASE_PATH
+    ;;
+ XDG+profile)
+    xdg_config ${RANDOM}
+    mv mail/.notmuch/xapian $DATABASE_PATH
+    ;;
     esac
 
     test_begin_subtest "count ($config)"
diff --git a/test/T560-lib-error.sh b/test/T560-lib-error.sh
index 03df69d9..89447e9a 100755
--- a/test/T560-lib-error.sh
+++ b/test/T560-lib-error.sh
@@ -22,7 +22,7 @@ EOF
 cat <<'EOF' >EXPECTED
 == stdout ==
 == stderr ==
-Error: Cannot open a database for a NULL path.
+Error: Cannot open database at CWD/home/.local/share/notmuch/default: No such file or directory.
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
@@ -93,7 +93,7 @@ EOF
 cat <<'EOF' >EXPECTED
 == stdout ==
 == stderr ==
-Error: Cannot open a database for a NULL path.
+Error: Cannot open database at CWD/home/.local/share/notmuch/default: No such file or directory.
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh
index 5cf70987..c21c139b 100755
--- a/test/T590-libconfig.sh
+++ b/test/T590-libconfig.sh
@@ -519,8 +519,8 @@ cat <<'EOF' >EXPECTED
 == stdout ==
 == stderr ==
 error opening database
-Erroneous NULL pointer
-Error: Cannot open a database for a NULL path.
+Something went wrong trying to read or write a file
+Error: Cannot open database at CWD/home/.local/share/notmuch/default: No such file or directory.
 
 EOF
 test_expect_equal_file EXPECTED OUTPUT
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 15/23] CLI/new: support split database and mail location

In reply to this post by David Bremner-2
This adds new state variable for the mail root, and uses it most
places db_path was used. The notable exception is dumps from backups.
---
 notmuch-new.c            | 54 ++++++++++++++++++++++++++--------------
 test/T055-path-config.sh | 13 ++++++++++
 2 files changed, 48 insertions(+), 19 deletions(-)

diff --git a/notmuch-new.c b/notmuch-new.c
index 21e66af1..63ac10a6 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -43,6 +43,7 @@ enum verbosity {
 
 typedef struct {
     const char *db_path;
+    const char *mail_root;
 
     int output_is_a_tty;
     enum verbosity verbosity;
@@ -307,18 +308,18 @@ _setup_ignore (notmuch_database_t *notmuch, add_files_state_t *state)
 }
 
 static char *
-_get_relative_path (const char *db_path, const char *dirpath, const char *entry)
+_get_relative_path (const char *mail_root, const char *dirpath, const char *entry)
 {
-    size_t db_path_len = strlen (db_path);
+    size_t mail_root_len = strlen (mail_root);
 
     /* paranoia? */
-    if (strncmp (dirpath, db_path, db_path_len) != 0) {
+    if (strncmp (dirpath, mail_root, mail_root_len) != 0) {
  fprintf (stderr, "Warning: '%s' is not a subdirectory of '%s'\n",
- dirpath, db_path);
+ dirpath, mail_root);
  return NULL;
     }
 
-    dirpath += db_path_len;
+    dirpath += mail_root_len;
     while (*dirpath == '/')
  dirpath++;
 
@@ -346,7 +347,7 @@ _entry_in_ignore_list (add_files_state_t *state, const char *dirpath,
     if (state->ignore_regex_length == 0)
  return false;
 
-    path = _get_relative_path (state->db_path, dirpath, entry);
+    path = _get_relative_path (state->mail_root, dirpath, entry);
     if (! path)
  return false;
 
@@ -1047,22 +1048,34 @@ _maybe_upgrade (notmuch_database_t *notmuch, add_files_state_t *state) {
     if (notmuch_database_needs_upgrade (notmuch)) {
  time_t now = time (NULL);
  struct tm *gm_time = gmtime (&now);
+ struct stat st;
+ int err;
  notmuch_status_t status;
  char *dot_notmuch_path = talloc_asprintf (notmuch, "%s/%s", state->db_path, ".notmuch");
 
+ const char *backup_name;
+
+ err = stat(dot_notmuch_path, &st);
+ if (err) {
+    if (errno == ENOENT) {
+ dot_notmuch_path = NULL;
+    } else {
+ fprintf(stderr, "Failed to stat %s: %s\n", dot_notmuch_path, strerror(errno));
+ return EXIT_FAILURE;
+    }
+ }
+
  /* since dump files are written atomically, the amount of
  * harm from overwriting one within a second seems
  * relatively small. */
-
- const char *backup_name =
-    talloc_asprintf (notmuch, "%s/dump-%04d%02d%02dT%02d%02d%02d.gz",
-     dot_notmuch_path,
-     gm_time->tm_year + 1900,
-     gm_time->tm_mon + 1,
-     gm_time->tm_mday,
-     gm_time->tm_hour,
-     gm_time->tm_min,
-     gm_time->tm_sec);
+ backup_name = talloc_asprintf (notmuch, "%s/dump-%04d%02d%02dT%02d%02d%02d.gz",
+       dot_notmuch_path ? dot_notmuch_path : state->db_path,
+       gm_time->tm_year + 1900,
+       gm_time->tm_mon + 1,
+       gm_time->tm_mday,
+       gm_time->tm_hour,
+       gm_time->tm_min,
+       gm_time->tm_sec);
 
  if (state->verbosity >= VERBOSITY_NORMAL) {
     printf ("Welcome to a new version of notmuch! Your database will now be upgraded.\n");
@@ -1104,7 +1117,7 @@ notmuch_new_command (unused(notmuch_config_t *config), notmuch_database_t *notmu
     };
     struct timeval tv_start;
     int ret = 0;
-    const char *db_path;
+    const char *db_path, *mail_root;
     struct sigaction action;
     _filename_node_t *f;
     int opt_index;
@@ -1149,6 +1162,9 @@ notmuch_new_command (unused(notmuch_config_t *config), notmuch_database_t *notmu
     db_path = notmuch_config_get (notmuch, NOTMUCH_CONFIG_DATABASE_PATH);
     add_files_state.db_path = db_path;
 
+    mail_root = notmuch_config_get (notmuch, NOTMUCH_CONFIG_MAIL_ROOT);
+    add_files_state.mail_root = mail_root;
+
     if (! _setup_ignore (notmuch, &add_files_state))
  return EXIT_FAILURE;
 
@@ -1175,7 +1191,7 @@ notmuch_new_command (unused(notmuch_config_t *config), notmuch_database_t *notmu
 
     if (notmuch_database_get_revision (notmuch, NULL) == 0) {
  int count = 0;
- count_files (db_path, &count, &add_files_state);
+ count_files (mail_root, &count, &add_files_state);
  if (interrupted)
     return EXIT_FAILURE;
 
@@ -1221,7 +1237,7 @@ notmuch_new_command (unused(notmuch_config_t *config), notmuch_database_t *notmu
  timer_is_active = true;
     }
 
-    ret = add_files (notmuch, db_path, &add_files_state);
+    ret = add_files (notmuch, mail_root, &add_files_state);
     if (ret)
  goto DONE;
 
diff --git a/test/T055-path-config.sh b/test/T055-path-config.sh
index c82b6a14..6882ab16 100755
--- a/test/T055-path-config.sh
+++ b/test/T055-path-config.sh
@@ -87,6 +87,19 @@ for config in traditional split+prefix split XDG XDG+profile; do
     notmuch tag -$tag '*'
     test_expect_equal "$output" '52'
 
+    test_begin_subtest "create database ($config)"
+    rm -rf $DATABASE_PATH/{.notmuch,}/xapian
+    notmuch new
+    output=$(notmuch count '*')
+    test_expect_equal "$output" '52'
+
+    test_begin_subtest "detect new files ($config)"
+    generate_message
+    generate_message
+    notmuch new
+    output=$(notmuch count '*')
+    test_expect_equal "$output" '54'
+
     restore_config
 done
 
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 16/23] CLI/insert: support split database and mail root

In reply to this post by David Bremner-2
The new test is in T055-path-config because it uses the helper
function split_config, and because it seems easier to follow the
database path related tests in one place.
---
 notmuch-insert.c         | 12 +++---------
 test/T055-path-config.sh | 10 ++++++++++
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index 0f272e2e..38a0dfe6 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -448,7 +448,7 @@ notmuch_insert_command (unused(notmuch_config_t *config),notmuch_database_t *not
 {
     notmuch_status_t status, close_status;
     struct sigaction action;
-    const char *db_path;
+    const char *mail_root;
     notmuch_config_values_t *new_tags = NULL;
     tag_op_list_t *tag_ops;
     char *query_string = NULL;
@@ -480,13 +480,7 @@ notmuch_insert_command (unused(notmuch_config_t *config),notmuch_database_t *not
 
     notmuch_process_shared_options (argv[0]);
 
-
-    db_path = notmuch_config_get (notmuch, NOTMUCH_CONFIG_DATABASE_PATH);
-
-    if (! db_path)
- INTERNAL_ERROR ("Unable to retrieve database path");
-    else
- db_path = talloc_strdup (local, db_path);
+    mail_root = notmuch_config_get (notmuch, NOTMUCH_CONFIG_MAIL_ROOT);
 
     new_tags = notmuch_config_get_values (notmuch, NOTMUCH_CONFIG_NEW_TAGS);
 
@@ -532,7 +526,7 @@ notmuch_insert_command (unused(notmuch_config_t *config),notmuch_database_t *not
  return EXIT_FAILURE;
     }
 
-    maildir = talloc_asprintf (local, "%s/%s", db_path, folder);
+    maildir = talloc_asprintf (local, "%s/%s", mail_root, folder);
     if (! maildir) {
  fprintf (stderr, "Out of memory\n");
  return EXIT_FAILURE;
diff --git a/test/T055-path-config.sh b/test/T055-path-config.sh
index 6882ab16..1bae1b1b 100755
--- a/test/T055-path-config.sh
+++ b/test/T055-path-config.sh
@@ -100,6 +100,16 @@ for config in traditional split+prefix split XDG XDG+profile; do
     output=$(notmuch count '*')
     test_expect_equal "$output" '54'
 
+    test_begin_subtest "insert+search ($config)"
+    generate_message \
+ "[subject]=\"insert-subject\"" \
+ "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" \
+ "[body]=\"insert-message\""
+    mkdir -p "$MAIL_DIR"/{cur,new,tmp}
+    notmuch insert < "$gen_msg_filename"
+    cur_msg_filename=$(notmuch search --output=files "subject:insert-subject")
+    test_expect_equal_file "$cur_msg_filename" "$gen_msg_filename"
+
     restore_config
 done
 
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 17/23] lib: remove "path" from notmuch struct

In reply to this post by David Bremner-2
This removes duplication between the struct element and the
configuration string_map entry.
---
 lib/config.cc          |  3 +++
 lib/database-private.h |  3 ---
 lib/database.cc        |  2 +-
 lib/open.cc            | 22 +++++++++++++++-------
 4 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/lib/config.cc b/lib/config.cc
index bfa6b4ae..44d546db 100644
--- a/lib/config.cc
+++ b/lib/config.cc
@@ -478,5 +478,8 @@ notmuch_config_set (notmuch_database_t *notmuch, notmuch_config_key_t key, const
 
 void
 _notmuch_config_cache (notmuch_database_t *notmuch, notmuch_config_key_t key, const char *val) {
+    if (notmuch->config == NULL)
+ notmuch->config = _notmuch_string_map_create (notmuch);
+
     _notmuch_string_map_set (notmuch->config, _notmuch_config_key_to_string (key), val);
 }
diff --git a/lib/database-private.h b/lib/database-private.h
index d936b216..2900382d 100644
--- a/lib/database-private.h
+++ b/lib/database-private.h
@@ -189,9 +189,6 @@ operator& (notmuch_field_flag_t a, notmuch_field_flag_t b)
 struct _notmuch_database {
     bool exception_reported;
 
-    /* Path to database parent directory and or/mail root */
-    char *path;
-
     /* Path to actual database */
     const char *xapian_path;
 
diff --git a/lib/database.cc b/lib/database.cc
index 1fc3ce9c..1d8839a5 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -748,7 +748,7 @@ notmuch_database_destroy (notmuch_database_t *notmuch)
 const char *
 notmuch_database_get_path (notmuch_database_t *notmuch)
 {
-    return notmuch->path;
+    return notmuch_config_get (notmuch, NOTMUCH_CONFIG_DATABASE_PATH);
 }
 
 unsigned int
diff --git a/lib/open.cc b/lib/open.cc
index efb0d6a3..a577ddca 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -305,6 +305,7 @@ _finish_open (notmuch_database_t *notmuch,
     char *incompat_features;
     char *message = NULL;
     unsigned int version;
+    const char *database_path = notmuch_database_get_path (notmuch);
 
     try {
  std::string last_thread_id;
@@ -327,7 +328,7 @@ _finish_open (notmuch_database_t *notmuch,
      "Error: Notmuch database at %s\n"
      "       has a newer database format version (%u) than supported by this\n"
      "       version of notmuch (%u).\n",
-     notmuch->path, version, NOTMUCH_DATABASE_VERSION));
+     database_path, version, NOTMUCH_DATABASE_VERSION));
     notmuch_database_destroy (notmuch);
     notmuch = NULL;
     status = NOTMUCH_STATUS_FILE_ERROR;
@@ -345,7 +346,7 @@ _finish_open (notmuch_database_t *notmuch,
      "Error: Notmuch database at %s\n"
      "       requires features (%s)\n"
      "       not supported by this version of notmuch.\n",
-     notmuch->path, incompat_features));
+     database_path, incompat_features));
     notmuch_database_destroy (notmuch);
     notmuch = NULL;
     status = NOTMUCH_STATUS_FILE_ERROR;
@@ -429,6 +430,16 @@ _finish_open (notmuch_database_t *notmuch,
     return status;
 }
 
+static void
+_set_database_path (notmuch_database_t *notmuch,
+   const char *database_path) {
+    char *path=talloc_strdup (notmuch, database_path);
+
+    strip_trailing (path, '/');
+
+    _notmuch_config_cache (notmuch, NOTMUCH_CONFIG_DATABASE_PATH, path);
+}
+
 notmuch_status_t
 notmuch_database_open_with_config (const char *database_path,
    notmuch_database_mode_t mode,
@@ -461,8 +472,7 @@ notmuch_database_open_with_config (const char *database_path,
     if (status)
  goto DONE;
 
-    notmuch->path = talloc_strdup (notmuch, database_path);
-    strip_trailing (notmuch->path, '/');
+    _set_database_path (notmuch, database_path);
 
     status = _choose_xapian_path (local, database_path, &notmuch->xapian_path, &message);
     if (status)
@@ -547,8 +557,7 @@ notmuch_database_create_with_config (const char *database_path,
     if (status)
  goto DONE;
 
-    notmuch->path = talloc_strdup (notmuch, database_path);
-    strip_trailing (notmuch->path, '/');
+    _set_database_path (notmuch, database_path);
 
     if (key_file && !split) {
  const char *mail_root = g_key_file_get_value (key_file, "database", "mail_root", NULL);
@@ -565,7 +574,6 @@ notmuch_database_create_with_config (const char *database_path,
  }
 
  err = mkdir (notmuch_path, 0755);
-
  if (err) {
     if (errno == EEXIST) {
  status = NOTMUCH_STATUS_DATABASE_EXISTS;
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 18/23] CLI/show: add tests for raw output in split config

In reply to this post by David Bremner-2
This is a case where the CLI accesses both the database and the raw
mail file
---
 test/T055-path-config.sh | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/test/T055-path-config.sh b/test/T055-path-config.sh
index 1bae1b1b..e5036400 100755
--- a/test/T055-path-config.sh
+++ b/test/T055-path-config.sh
@@ -110,6 +110,12 @@ for config in traditional split+prefix split XDG XDG+profile; do
     cur_msg_filename=$(notmuch search --output=files "subject:insert-subject")
     test_expect_equal_file "$cur_msg_filename" "$gen_msg_filename"
 
+    test_begin_subtest "Show a raw message ($config)"
+    add_message
+    notmuch show --format=raw id:$gen_msg_id > OUTPUT
+    test_expect_equal_file $gen_msg_filename OUTPUT
+    rm -f $gen_msg_filename
+
     restore_config
 done
 
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
David Bremner-2 David Bremner-2
Reply | Threaded
Open this post in threaded view
|

[PATCH 19/23] lib/compact: enable split config

In reply to this post by David Bremner-2
This promotes _choose_xapian_path from static to extern linkage in
order to share between open.cc and database.cc.
---
 lib/database.cc          | 13 ++++---------
 lib/notmuch-private.h    |  4 ++++
 lib/open.cc              |  6 +++---
 test/T055-path-config.sh |  6 ++++++
 4 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 1d8839a5..ffd42ac4 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -607,11 +607,12 @@ notmuch_database_compact_db (notmuch_database_t *notmuch,
      notmuch_compact_status_cb_t status_cb,
      void *closure) {
     void *local;
-    char *notmuch_path, *xapian_path, *compact_xapian_path;
+    const char *xapian_path, *compact_xapian_path;
     const char* path;
     notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;
     struct stat statbuf;
     bool keep_backup;
+    char *message;
 
     ret = _notmuch_database_ensure_writable (notmuch);
     if (ret)
@@ -625,15 +626,9 @@ notmuch_database_compact_db (notmuch_database_t *notmuch,
     if (! local)
  return NOTMUCH_STATUS_OUT_OF_MEMORY;
 
-    if (! (notmuch_path = talloc_asprintf (local, "%s/%s", path, ".notmuch"))) {
- ret = NOTMUCH_STATUS_OUT_OF_MEMORY;
- goto DONE;
-    }
-
-    if (! (xapian_path = talloc_asprintf (local, "%s/%s", notmuch_path, "xapian"))) {
- ret = NOTMUCH_STATUS_OUT_OF_MEMORY;
+    ret = _notmuch_choose_xapian_path (local, path, &xapian_path, &message);
+    if (ret)
  goto DONE;
-    }
 
     if (! (compact_xapian_path = talloc_asprintf (local, "%s.compact", xapian_path))) {
  ret = NOTMUCH_STATUS_OUT_OF_MEMORY;
diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index 731757cc..ecad87a6 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -726,6 +726,10 @@ _notmuch_config_load_defaults (notmuch_database_t * db);
 void
 _notmuch_config_cache (notmuch_database_t *db, notmuch_config_key_t key, const char* val);
 
+/* open.cc */
+notmuch_status_t
+_notmuch_choose_xapian_path (void *ctx, const char *database_path, const char **xapian_path, char **message);
+
 NOTMUCH_END_DECLS
 
 #ifdef __cplusplus
diff --git a/lib/open.cc b/lib/open.cc
index a577ddca..2311d4a0 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -250,8 +250,8 @@ _trial_open (const char *xapian_path, char **message_ptr)
     return NOTMUCH_STATUS_SUCCESS;
 }
 
-static notmuch_status_t
-_choose_xapian_path (void *ctx, const char *database_path, const char **xapian_path, char **message_ptr){
+notmuch_status_t
+_notmuch_choose_xapian_path (void *ctx, const char *database_path, const char **xapian_path, char **message_ptr){
     notmuch_status_t status;
     const char *trial_path, *notmuch_path;
 
@@ -474,7 +474,7 @@ notmuch_database_open_with_config (const char *database_path,
 
     _set_database_path (notmuch, database_path);
 
-    status = _choose_xapian_path (local, database_path, &notmuch->xapian_path, &message);
+    status = _notmuch_choose_xapian_path (local, database_path, &notmuch->xapian_path, &message);
     if (status)
  goto DONE;
 
diff --git a/test/T055-path-config.sh b/test/T055-path-config.sh
index e5036400..7bd9739b 100755
--- a/test/T055-path-config.sh
+++ b/test/T055-path-config.sh
@@ -116,6 +116,12 @@ for config in traditional split+prefix split XDG XDG+profile; do
     test_expect_equal_file $gen_msg_filename OUTPUT
     rm -f $gen_msg_filename
 
+    test_begin_subtest "compact+search ($config)"
+    notmuch search --output=messages '*' | sort > EXPECTED
+    notmuch compact
+    notmuch search --output=messages '*' | sort > OUTPUT
+    test_expect_equal_file EXPECTED OUTPUT
+
     restore_config
 done
 
--
2.30.0
_______________________________________________
notmuch mailing list -- [hidden email]
To unsubscribe send an email to [hidden email]
12