unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
* [PATCH 0/5] Fix notmuch_database_get_directory API
@ 2012-05-13 19:57 Austin Clements
  2012-05-13 19:57 ` [PATCH 1/5] lib/cli: Make notmuch_database_get_directory return a status code Austin Clements
                   ` (6 more replies)
  0 siblings, 7 replies; 17+ messages in thread
From: Austin Clements @ 2012-05-13 19:57 UTC (permalink / raw)
  To: notmuch; +Cc: tomi.ollila

This is a proposed last-minute change for 0.13.  It fixes the
notmuch_database_get_directory API in the same way we're fixing
notmuch_database_open, etc in this release.  Since this is a
backwards-incompatible change, it would be nice to lump it with the
other API-breaking changes.

To keep the patch simple, this does not change the behavior of
notmuch_database_get_directory, but it puts us in a good position to
fix it in the future.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 1/5] lib/cli: Make notmuch_database_get_directory return a status code
  2012-05-13 19:57 [PATCH 0/5] Fix notmuch_database_get_directory API Austin Clements
@ 2012-05-13 19:57 ` Austin Clements
  2012-05-13 19:57 ` [PATCH 2/5] go: Update for changes to notmuch_database_get_directory Austin Clements
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 17+ messages in thread
From: Austin Clements @ 2012-05-13 19:57 UTC (permalink / raw)
  To: notmuch; +Cc: tomi.ollila

Previously, notmuch_database_get_directory had no way to indicate how
it had failed.  This changes its prototype to return a status code and
set an out-argument to the retrieved directory, like similar functions
in the library API.  This does *not* change its currently broken
behavior of creating directory objects when they don't exist, but it
does document it and paves the way for fixing this.  Also, it can now
check for a read-only database and return
NOTMUCH_STATUS_READ_ONLY_DATABASE instead of crashing.

In the interest of atomicity, this also updates calls from the CLI so
that notmuch still compiles.
---
 lib/database.cc |   22 ++++++++++++++++------
 lib/notmuch.h   |   24 +++++++++++++++++++++---
 notmuch-new.c   |   21 ++++++++++++++-------
 3 files changed, 51 insertions(+), 16 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 07f186e..f8c4a7d 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -955,8 +955,8 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
 		mtime = Xapian::sortable_unserialise (
 		    document.get_value (NOTMUCH_VALUE_TIMESTAMP));
 
-		directory = notmuch_database_get_directory (notmuch,
-							    term.c_str() + 10);
+		directory = _notmuch_directory_create (notmuch, term.c_str() + 10,
+						       &status);
 		notmuch_directory_set_mtime (directory, mtime);
 		notmuch_directory_destroy (directory);
 	    }
@@ -1304,20 +1304,30 @@ _notmuch_database_relative_path (notmuch_database_t *notmuch,
     return relative;
 }
 
-notmuch_directory_t *
+notmuch_status_t
 notmuch_database_get_directory (notmuch_database_t *notmuch,
-				const char *path)
+				const char *path,
+				notmuch_directory_t **directory)
 {
     notmuch_status_t status;
 
+    if (directory == NULL)
+	return NOTMUCH_STATUS_NULL_POINTER;
+    *directory = NULL;
+
+    /* XXX Handle read-only databases properly */
+    if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
+	return NOTMUCH_STATUS_READ_ONLY_DATABASE;
+
     try {
-	return _notmuch_directory_create (notmuch, path, &status);
+	*directory = _notmuch_directory_create (notmuch, path, &status);
     } catch (const Xapian::Error &error) {
 	fprintf (stderr, "A Xapian exception occurred getting directory: %s.\n",
 		 error.get_msg().c_str());
 	notmuch->exception_reported = TRUE;
-	return NULL;
+	status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
     }
+    return status;
 }
 
 /* Allocate a document ID that satisfies the following criteria:
diff --git a/lib/notmuch.h b/lib/notmuch.h
index e6e5cc2..d414198 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -300,11 +300,29 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch);
  * (see notmuch_database_get_path), or else should be an absolute path
  * with initial components that match the path of 'database'.
  *
- * Can return NULL if a Xapian exception occurs.
+ * Note: Currently this will create the directory object if it doesn't
+ * exist.  This is not intentional behavior and is likely to change in
+ * the near future.  To future-proof, when this returns
+ * NOTMUCH_STATUS_SUCCESS, callers should check that *directory is not
+ * NULL.
+ *
+ * Return value:
+ *
+ * NOTMUCH_STATUS_SUCCESS: Successfully retrieved directory.
+ *
+ * NOTMUCH_STATUS_NULL_POINTER: The given 'directory' argument is NULL.
+ *
+ * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred;
+ *	directory not retrieved.
+ *
+ * NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
+ *	mode so the directory cannot be created (this case will be
+ *	removed in the future).
  */
-notmuch_directory_t *
+notmuch_status_t
 notmuch_database_get_directory (notmuch_database_t *database,
-				const char *path);
+				const char *path,
+				notmuch_directory_t **directory);
 
 /* Add a new message to the given notmuch database or associate an
  * additional filename with an existing message.
diff --git a/notmuch-new.c b/notmuch-new.c
index cb720cc..a3a8bec 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -250,7 +250,7 @@ add_files_recursive (notmuch_database_t *notmuch,
     notmuch_status_t status, ret = NOTMUCH_STATUS_SUCCESS;
     notmuch_message_t *message = NULL;
     struct dirent **fs_entries = NULL;
-    int i, num_fs_entries;
+    int i, num_fs_entries = 0;
     notmuch_directory_t *directory;
     notmuch_filenames_t *db_files = NULL;
     notmuch_filenames_t *db_subdirs = NULL;
@@ -274,8 +274,12 @@ add_files_recursive (notmuch_database_t *notmuch,
 
     fs_mtime = st.st_mtime;
 
-    directory = notmuch_database_get_directory (notmuch, path);
-    db_mtime = notmuch_directory_get_mtime (directory);
+    status = notmuch_database_get_directory (notmuch, path, &directory);
+    if (status) {
+	ret = status;
+	goto DONE;
+    }
+    db_mtime = directory ? notmuch_directory_get_mtime (directory) : 0;
 
     new_directory = db_mtime ? FALSE : TRUE;
 
@@ -295,7 +299,7 @@ add_files_recursive (notmuch_database_t *notmuch,
      * by a new out-argument, or by recording this information and
      * providing an accessor.
      */
-    if (new_directory)
+    if (new_directory && directory)
 	notmuch_directory_set_mtime (directory, -1);
 
     /* If the database knows about this directory, then we sort based
@@ -810,7 +814,9 @@ _remove_directory (void *ctx,
     notmuch_filenames_t *files, *subdirs;
     char *absolute;
 
-    directory = notmuch_database_get_directory (notmuch, path);
+    status = notmuch_database_get_directory (notmuch, path, &directory);
+    if (status || !directory)
+	return status;
 
     for (files = notmuch_directory_get_child_files (directory);
 	 notmuch_filenames_valid (files);
@@ -981,9 +987,10 @@ notmuch_new_command (void *ctx, int argc, char *argv[])
     }
 
     for (f = add_files_state.directory_mtimes->head; f && !interrupted; f = f->next) {
+	notmuch_status_t status;
 	notmuch_directory_t *directory;
-	directory = notmuch_database_get_directory (notmuch, f->filename);
-	if (directory) {
+	status = notmuch_database_get_directory (notmuch, f->filename, &directory);
+	if (status == NOTMUCH_STATUS_SUCCESS && directory) {
 	    notmuch_directory_set_mtime (directory, f->mtime);
 	    notmuch_directory_destroy (directory);
 	}
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 2/5] go: Update for changes to notmuch_database_get_directory
  2012-05-13 19:57 [PATCH 0/5] Fix notmuch_database_get_directory API Austin Clements
  2012-05-13 19:57 ` [PATCH 1/5] lib/cli: Make notmuch_database_get_directory return a status code Austin Clements
@ 2012-05-13 19:57 ` Austin Clements
  2012-05-13 21:51   ` Justus Winter
  2012-05-13 19:57 ` [PATCH 3/5] python: " Austin Clements
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Austin Clements @ 2012-05-13 19:57 UTC (permalink / raw)
  To: notmuch; +Cc: tomi.ollila

---
 bindings/go/src/notmuch/notmuch.go  |   13 +++++++------
 bindings/python/notmuch/database.py |    4 ++--
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/bindings/go/src/notmuch/notmuch.go b/bindings/go/src/notmuch/notmuch.go
index 12de4c8..00bd53a 100644
--- a/bindings/go/src/notmuch/notmuch.go
+++ b/bindings/go/src/notmuch/notmuch.go
@@ -191,19 +191,20 @@ func (self *Database) NeedsUpgrade() bool {
  *
  * Can return NULL if a Xapian exception occurs.
  */
-func (self *Database) GetDirectory(path string) *Directory {
+func (self *Database) GetDirectory(path string) (*Directory, Status) {
 	var c_path *C.char = C.CString(path)
 	defer C.free(unsafe.Pointer(c_path))
 
 	if c_path == nil {
-		return nil
+		return nil, STATUS_OUT_OF_MEMORY
 	}
 
-	c_dir := C.notmuch_database_get_directory(self.db, c_path)
-	if c_dir == nil {
-		return nil
+	var c_dir *C.notmuch_directory_t
+	st := Status(C.notmuch_database_get_directory(self.db, c_path, &c_dir))
+	if st != STATUS_SUCCESS || c_dir == nil {
+		return nil, st
 	}
-	return &Directory{dir: c_dir}
+	return &Directory{dir: c_dir}, st
 }
 
 /* Add a new message to the given notmuch database.
diff --git a/bindings/python/notmuch/database.py b/bindings/python/notmuch/database.py
index 1b1ddc3..0a58dd0 100644
--- a/bindings/python/notmuch/database.py
+++ b/bindings/python/notmuch/database.py
@@ -73,8 +73,8 @@ class Database(object):
 
     """notmuch_database_get_directory"""
     _get_directory = nmlib.notmuch_database_get_directory
-    _get_directory.argtypes = [NotmuchDatabaseP, c_char_p]
-    _get_directory.restype = NotmuchDirectoryP
+    _get_directory.argtypes = [NotmuchDatabaseP, c_char_p, POINTER(NotmuchDirectoryP)]
+    _get_directory.restype = c_uint
 
     """notmuch_database_get_path"""
     _get_path = nmlib.notmuch_database_get_path
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 3/5] python: Update for changes to notmuch_database_get_directory
  2012-05-13 19:57 [PATCH 0/5] Fix notmuch_database_get_directory API Austin Clements
  2012-05-13 19:57 ` [PATCH 1/5] lib/cli: Make notmuch_database_get_directory return a status code Austin Clements
  2012-05-13 19:57 ` [PATCH 2/5] go: Update for changes to notmuch_database_get_directory Austin Clements
@ 2012-05-13 19:57 ` Austin Clements
  2012-05-13 19:57 ` [PATCH 4/5] ruby: " Austin Clements
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 17+ messages in thread
From: Austin Clements @ 2012-05-13 19:57 UTC (permalink / raw)
  To: notmuch; +Cc: tomi.ollila

notmuch_database_get_directory now returns
NOTMUCH_STATUS_READ_ONLY_DATABASE on its own (rather than crashing) so
the workaround in Database.get_directory is no longer necessary.
---
 bindings/python/notmuch/database.py |   15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/bindings/python/notmuch/database.py b/bindings/python/notmuch/database.py
index 0a58dd0..797554d 100644
--- a/bindings/python/notmuch/database.py
+++ b/bindings/python/notmuch/database.py
@@ -359,13 +359,6 @@ class Database(object):
         """
         self._assert_db_is_initialized()
 
-        # work around libnotmuch calling exit(3), see
-        # id:20120221002921.8534.57091@thinkbox.jade-hamburg.de
-        # TODO: remove once this issue is resolved
-        if self.mode != Database.MODE.READ_WRITE:
-            raise ReadOnlyDatabaseError('The database has to be opened in '
-                                        'read-write mode for get_directory')
-
         # sanity checking if path is valid, and make path absolute
         if path and path[0] == os.sep:
             # we got an absolute path
@@ -378,7 +371,13 @@ class Database(object):
             #we got a relative path, make it absolute
             abs_dirpath = os.path.abspath(os.path.join(self.get_path(), path))
 
-        dir_p = Database._get_directory(self._db, _str(path))
+        dir_p = NotmuchDirectoryP()
+        status = Database._get_directory(self._db, _str(path), byref(dir_p))
+
+        if status != STATUS.SUCCESS:
+            raise NotmuchError(status)
+        if not dir_p:
+            return None
 
         # return the Directory, init it with the absolute path
         return Directory(abs_dirpath, dir_p, self)
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 4/5] ruby: Update for changes to notmuch_database_get_directory
  2012-05-13 19:57 [PATCH 0/5] Fix notmuch_database_get_directory API Austin Clements
                   ` (2 preceding siblings ...)
  2012-05-13 19:57 ` [PATCH 3/5] python: " Austin Clements
@ 2012-05-13 19:57 ` Austin Clements
  2012-05-13 19:57 ` [PATCH 5/5] news: " Austin Clements
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 17+ messages in thread
From: Austin Clements @ 2012-05-13 19:57 UTC (permalink / raw)
  To: notmuch; +Cc: tomi.ollila

---
 bindings/ruby/database.c |   11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/bindings/ruby/database.c b/bindings/ruby/database.c
index 409d54f..e84f726 100644
--- a/bindings/ruby/database.c
+++ b/bindings/ruby/database.c
@@ -252,6 +252,7 @@ VALUE
 notmuch_rb_database_get_directory (VALUE self, VALUE pathv)
 {
     const char *path;
+    notmuch_status_t ret;
     notmuch_directory_t *dir;
     notmuch_database_t *db;
 
@@ -260,11 +261,11 @@ notmuch_rb_database_get_directory (VALUE self, VALUE pathv)
     SafeStringValue (pathv);
     path = RSTRING_PTR (pathv);
 
-    dir = notmuch_database_get_directory (db, path);
-    if (!dir)
-        rb_raise (notmuch_rb_eXapianError, "Xapian exception");
-
-    return Data_Wrap_Struct (notmuch_rb_cDirectory, NULL, NULL, dir);
+    ret = notmuch_database_get_directory (db, path, &dir);
+    notmuch_rb_status_raise (ret);
+    if (dir)
+	return Data_Wrap_Struct (notmuch_rb_cDirectory, NULL, NULL, dir);
+    return Qnil;
 }
 
 /*
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 5/5] news: Update for changes to notmuch_database_get_directory
  2012-05-13 19:57 [PATCH 0/5] Fix notmuch_database_get_directory API Austin Clements
                   ` (3 preceding siblings ...)
  2012-05-13 19:57 ` [PATCH 4/5] ruby: " Austin Clements
@ 2012-05-13 19:57 ` Austin Clements
  2012-05-13 20:49 ` [PATCH 0/5] Fix notmuch_database_get_directory API Tomi Ollila
  2012-05-13 23:36 ` [PATCH v2 " Austin Clements
  6 siblings, 0 replies; 17+ messages in thread
From: Austin Clements @ 2012-05-13 19:57 UTC (permalink / raw)
  To: notmuch; +Cc: tomi.ollila

---
 NEWS |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/NEWS b/NEWS
index c67f186..f987811 100644
--- a/NEWS
+++ b/NEWS
@@ -91,12 +91,12 @@ notmuch_database_close and notmuch_database_destroy
   database and thus release the lock associated with it without
   destroying the data structures obtained from it.
 
-notmuch_database_open and notmuch_database_create now return errors
+notmuch_database_open, notmuch_database_create, and
+notmuch_database_get_directory now return errors
 
-  The type signatures of notmuch_database_open and
-  notmuch_database_create have changed so that the functions now
-  return a notmuch_status_t and take an out-argument for returning the
-  new database object.
+  The type signatures of these functions have changed so that the
+  functions now return a notmuch_status_t and take an out-argument for
+  returning the new database object or directory object.
 
 go bindings changes
 -------------------
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 0/5] Fix notmuch_database_get_directory API
  2012-05-13 19:57 [PATCH 0/5] Fix notmuch_database_get_directory API Austin Clements
                   ` (4 preceding siblings ...)
  2012-05-13 19:57 ` [PATCH 5/5] news: " Austin Clements
@ 2012-05-13 20:49 ` Tomi Ollila
  2012-05-13 21:55   ` Justus Winter
  2012-05-13 23:36 ` [PATCH v2 " Austin Clements
  6 siblings, 1 reply; 17+ messages in thread
From: Tomi Ollila @ 2012-05-13 20:49 UTC (permalink / raw)
  To: Austin Clements, notmuch

On Sun, May 13 2012, Austin Clements <amdragon@MIT.EDU> wrote:

> This is a proposed last-minute change for 0.13.  It fixes the
> notmuch_database_get_directory API in the same way we're fixing
> notmuch_database_open, etc in this release.  Since this is a
> backwards-incompatible change, it would be nice to lump it with the
> other API-breaking changes.
>
> To keep the patch simple, this does not change the behavior of
> notmuch_database_get_directory, but it puts us in a good position to
> fix it in the future.

Looks good to me (and applied in my current environment). The c/c++ 
changes were easy to understand and the python/go/ruby binding
changes looks like the old changes -- but those who understand more
(and actually uses those bindings) could do better review.

It would be nice to get those in so that we may have chance not
updating SONAME for notmuch 0.14.


Tomi

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5] go: Update for changes to notmuch_database_get_directory
  2012-05-13 19:57 ` [PATCH 2/5] go: Update for changes to notmuch_database_get_directory Austin Clements
@ 2012-05-13 21:51   ` Justus Winter
  2012-05-13 23:15     ` Austin Clements
  0 siblings, 1 reply; 17+ messages in thread
From: Justus Winter @ 2012-05-13 21:51 UTC (permalink / raw)
  To: Austin Clements, notmuch; +Cc: tomi.ollila

Hi Austin,

thanks for taking care of this.

Quoting Austin Clements (2012-05-13 21:57:06)
> ---
>  bindings/go/src/notmuch/notmuch.go  |   13 +++++++------
>  bindings/python/notmuch/database.py |    4 ++--

A change to the python bindings slipped into this one.

Other than that this looks good.

I just saw that I marked another function as problematic,
notmuch_database_find_message_by_filename ends up calling
_notmuch_directory_create that aborts if the database is not
writable. But this might have to wait and might not even requira an
api change.

Justus

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 0/5] Fix notmuch_database_get_directory API
  2012-05-13 20:49 ` [PATCH 0/5] Fix notmuch_database_get_directory API Tomi Ollila
@ 2012-05-13 21:55   ` Justus Winter
  0 siblings, 0 replies; 17+ messages in thread
From: Justus Winter @ 2012-05-13 21:55 UTC (permalink / raw)
  To: Tomi Ollila, Austin Clements, notmuch

Quoting Tomi Ollila (2012-05-13 22:49:58)
> On Sun, May 13 2012, Austin Clements <amdragon@MIT.EDU> wrote:
> 
> > This is a proposed last-minute change for 0.13.  It fixes the
> > notmuch_database_get_directory API in the same way we're fixing
> > notmuch_database_open, etc in this release.  Since this is a
> > backwards-incompatible change, it would be nice to lump it with the
> > other API-breaking changes.
> >
> > To keep the patch simple, this does not change the behavior of
> > notmuch_database_get_directory, but it puts us in a good position to
> > fix it in the future.
> 
> Looks good to me (and applied in my current environment). The c/c++ 
> changes were easy to understand and the python/go/ruby binding
> changes looks like the old changes -- but those who understand more
> (and actually uses those bindings) could do better review.

I'd say the changes to the python and go bindings are fine.

> It would be nice to get those in so that we may have chance not
> updating SONAME for notmuch 0.14.

Yes, I'd love to see this in 0.13 as well, but I don't really see the
problem with breaking the api if this fixes design issues. After all,
notmuch is young and so are all the projects building uppon it.

Justus

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5] go: Update for changes to notmuch_database_get_directory
  2012-05-13 21:51   ` Justus Winter
@ 2012-05-13 23:15     ` Austin Clements
  0 siblings, 0 replies; 17+ messages in thread
From: Austin Clements @ 2012-05-13 23:15 UTC (permalink / raw)
  To: Justus Winter; +Cc: tomi.ollila, notmuch

Quoth Justus Winter on May 13 at 11:51 pm:
> Hi Austin,
> 
> thanks for taking care of this.
> 
> Quoting Austin Clements (2012-05-13 21:57:06)
> > ---
> >  bindings/go/src/notmuch/notmuch.go  |   13 +++++++------
> >  bindings/python/notmuch/database.py |    4 ++--
> 
> A change to the python bindings slipped into this one.

Sure enough.  I'll send a v2 that moves that hunk to the python patch.

> Other than that this looks good.
> 
> I just saw that I marked another function as problematic,
> notmuch_database_find_message_by_filename ends up calling
> _notmuch_directory_create that aborts if the database is not
> writable. But this might have to wait and might not even requira an
> api change.

Right.  notmuch_database_find_message_by_filename already has a status
return, so its API is fine.  (Actually, I was starting to fix its
implementation when I realized notmuch_database_get_directory was
problematic.)

> Justus

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 0/5] Fix notmuch_database_get_directory API
  2012-05-13 19:57 [PATCH 0/5] Fix notmuch_database_get_directory API Austin Clements
                   ` (5 preceding siblings ...)
  2012-05-13 20:49 ` [PATCH 0/5] Fix notmuch_database_get_directory API Tomi Ollila
@ 2012-05-13 23:36 ` Austin Clements
  2012-05-13 23:36   ` [PATCH v2 1/5] lib/cli: Make notmuch_database_get_directory return a status code Austin Clements
                     ` (5 more replies)
  6 siblings, 6 replies; 17+ messages in thread
From: Austin Clements @ 2012-05-13 23:36 UTC (permalink / raw)
  To: notmuch; +Cc: tomi.ollila

This version moves a Python bindings change that had slipped into the
Go patch into the Python patch and words the future-proofing warning
on notmuch_database_get_directory more strongly.  There are no code
changes from v1.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 1/5] lib/cli: Make notmuch_database_get_directory return a status code
  2012-05-13 23:36 ` [PATCH v2 " Austin Clements
@ 2012-05-13 23:36   ` Austin Clements
  2012-05-13 23:36   ` [PATCH v2 2/5] go: Update for changes to notmuch_database_get_directory Austin Clements
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Austin Clements @ 2012-05-13 23:36 UTC (permalink / raw)
  To: notmuch; +Cc: tomi.ollila

Previously, notmuch_database_get_directory had no way to indicate how
it had failed.  This changes its prototype to return a status code and
set an out-argument to the retrieved directory, like similar functions
in the library API.  This does *not* change its currently broken
behavior of creating directory objects when they don't exist, but it
does document it and paves the way for fixing this.  Also, it can now
check for a read-only database and return
NOTMUCH_STATUS_READ_ONLY_DATABASE instead of crashing.

In the interest of atomicity, this also updates calls from the CLI so
that notmuch still compiles.
---
 lib/database.cc |   22 ++++++++++++++++------
 lib/notmuch.h   |   23 ++++++++++++++++++++---
 notmuch-new.c   |   21 ++++++++++++++-------
 3 files changed, 50 insertions(+), 16 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 07f186e..f8c4a7d 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -955,8 +955,8 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
 		mtime = Xapian::sortable_unserialise (
 		    document.get_value (NOTMUCH_VALUE_TIMESTAMP));
 
-		directory = notmuch_database_get_directory (notmuch,
-							    term.c_str() + 10);
+		directory = _notmuch_directory_create (notmuch, term.c_str() + 10,
+						       &status);
 		notmuch_directory_set_mtime (directory, mtime);
 		notmuch_directory_destroy (directory);
 	    }
@@ -1304,20 +1304,30 @@ _notmuch_database_relative_path (notmuch_database_t *notmuch,
     return relative;
 }
 
-notmuch_directory_t *
+notmuch_status_t
 notmuch_database_get_directory (notmuch_database_t *notmuch,
-				const char *path)
+				const char *path,
+				notmuch_directory_t **directory)
 {
     notmuch_status_t status;
 
+    if (directory == NULL)
+	return NOTMUCH_STATUS_NULL_POINTER;
+    *directory = NULL;
+
+    /* XXX Handle read-only databases properly */
+    if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
+	return NOTMUCH_STATUS_READ_ONLY_DATABASE;
+
     try {
-	return _notmuch_directory_create (notmuch, path, &status);
+	*directory = _notmuch_directory_create (notmuch, path, &status);
     } catch (const Xapian::Error &error) {
 	fprintf (stderr, "A Xapian exception occurred getting directory: %s.\n",
 		 error.get_msg().c_str());
 	notmuch->exception_reported = TRUE;
-	return NULL;
+	status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
     }
+    return status;
 }
 
 /* Allocate a document ID that satisfies the following criteria:
diff --git a/lib/notmuch.h b/lib/notmuch.h
index e6e5cc2..bbb17e4 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -300,11 +300,28 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch);
  * (see notmuch_database_get_path), or else should be an absolute path
  * with initial components that match the path of 'database'.
  *
- * Can return NULL if a Xapian exception occurs.
+ * Note: Currently this will create the directory object if it doesn't
+ * exist.  In the future, when a directory object does not exist this
+ * will return NOTMUCH_STATUS_SUCCESS and set *directory to NULL.
+ * Callers should be prepared for this.
+ *
+ * Return value:
+ *
+ * NOTMUCH_STATUS_SUCCESS: Successfully retrieved directory.
+ *
+ * NOTMUCH_STATUS_NULL_POINTER: The given 'directory' argument is NULL.
+ *
+ * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred;
+ *	directory not retrieved.
+ *
+ * NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
+ *	mode so the directory cannot be created (this case will be
+ *	removed in the future).
  */
-notmuch_directory_t *
+notmuch_status_t
 notmuch_database_get_directory (notmuch_database_t *database,
-				const char *path);
+				const char *path,
+				notmuch_directory_t **directory);
 
 /* Add a new message to the given notmuch database or associate an
  * additional filename with an existing message.
diff --git a/notmuch-new.c b/notmuch-new.c
index cb720cc..a3a8bec 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -250,7 +250,7 @@ add_files_recursive (notmuch_database_t *notmuch,
     notmuch_status_t status, ret = NOTMUCH_STATUS_SUCCESS;
     notmuch_message_t *message = NULL;
     struct dirent **fs_entries = NULL;
-    int i, num_fs_entries;
+    int i, num_fs_entries = 0;
     notmuch_directory_t *directory;
     notmuch_filenames_t *db_files = NULL;
     notmuch_filenames_t *db_subdirs = NULL;
@@ -274,8 +274,12 @@ add_files_recursive (notmuch_database_t *notmuch,
 
     fs_mtime = st.st_mtime;
 
-    directory = notmuch_database_get_directory (notmuch, path);
-    db_mtime = notmuch_directory_get_mtime (directory);
+    status = notmuch_database_get_directory (notmuch, path, &directory);
+    if (status) {
+	ret = status;
+	goto DONE;
+    }
+    db_mtime = directory ? notmuch_directory_get_mtime (directory) : 0;
 
     new_directory = db_mtime ? FALSE : TRUE;
 
@@ -295,7 +299,7 @@ add_files_recursive (notmuch_database_t *notmuch,
      * by a new out-argument, or by recording this information and
      * providing an accessor.
      */
-    if (new_directory)
+    if (new_directory && directory)
 	notmuch_directory_set_mtime (directory, -1);
 
     /* If the database knows about this directory, then we sort based
@@ -810,7 +814,9 @@ _remove_directory (void *ctx,
     notmuch_filenames_t *files, *subdirs;
     char *absolute;
 
-    directory = notmuch_database_get_directory (notmuch, path);
+    status = notmuch_database_get_directory (notmuch, path, &directory);
+    if (status || !directory)
+	return status;
 
     for (files = notmuch_directory_get_child_files (directory);
 	 notmuch_filenames_valid (files);
@@ -981,9 +987,10 @@ notmuch_new_command (void *ctx, int argc, char *argv[])
     }
 
     for (f = add_files_state.directory_mtimes->head; f && !interrupted; f = f->next) {
+	notmuch_status_t status;
 	notmuch_directory_t *directory;
-	directory = notmuch_database_get_directory (notmuch, f->filename);
-	if (directory) {
+	status = notmuch_database_get_directory (notmuch, f->filename, &directory);
+	if (status == NOTMUCH_STATUS_SUCCESS && directory) {
 	    notmuch_directory_set_mtime (directory, f->mtime);
 	    notmuch_directory_destroy (directory);
 	}
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 2/5] go: Update for changes to notmuch_database_get_directory
  2012-05-13 23:36 ` [PATCH v2 " Austin Clements
  2012-05-13 23:36   ` [PATCH v2 1/5] lib/cli: Make notmuch_database_get_directory return a status code Austin Clements
@ 2012-05-13 23:36   ` Austin Clements
  2012-05-13 23:36   ` [PATCH v2 3/5] python: " Austin Clements
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Austin Clements @ 2012-05-13 23:36 UTC (permalink / raw)
  To: notmuch; +Cc: tomi.ollila

---
 bindings/go/src/notmuch/notmuch.go |   13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/bindings/go/src/notmuch/notmuch.go b/bindings/go/src/notmuch/notmuch.go
index 12de4c8..00bd53a 100644
--- a/bindings/go/src/notmuch/notmuch.go
+++ b/bindings/go/src/notmuch/notmuch.go
@@ -191,19 +191,20 @@ func (self *Database) NeedsUpgrade() bool {
  *
  * Can return NULL if a Xapian exception occurs.
  */
-func (self *Database) GetDirectory(path string) *Directory {
+func (self *Database) GetDirectory(path string) (*Directory, Status) {
 	var c_path *C.char = C.CString(path)
 	defer C.free(unsafe.Pointer(c_path))
 
 	if c_path == nil {
-		return nil
+		return nil, STATUS_OUT_OF_MEMORY
 	}
 
-	c_dir := C.notmuch_database_get_directory(self.db, c_path)
-	if c_dir == nil {
-		return nil
+	var c_dir *C.notmuch_directory_t
+	st := Status(C.notmuch_database_get_directory(self.db, c_path, &c_dir))
+	if st != STATUS_SUCCESS || c_dir == nil {
+		return nil, st
 	}
-	return &Directory{dir: c_dir}
+	return &Directory{dir: c_dir}, st
 }
 
 /* Add a new message to the given notmuch database.
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 3/5] python: Update for changes to notmuch_database_get_directory
  2012-05-13 23:36 ` [PATCH v2 " Austin Clements
  2012-05-13 23:36   ` [PATCH v2 1/5] lib/cli: Make notmuch_database_get_directory return a status code Austin Clements
  2012-05-13 23:36   ` [PATCH v2 2/5] go: Update for changes to notmuch_database_get_directory Austin Clements
@ 2012-05-13 23:36   ` Austin Clements
  2012-05-13 23:36   ` [PATCH v2 4/5] ruby: " Austin Clements
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Austin Clements @ 2012-05-13 23:36 UTC (permalink / raw)
  To: notmuch; +Cc: tomi.ollila

notmuch_database_get_directory now returns
NOTMUCH_STATUS_READ_ONLY_DATABASE on its own (rather than crashing) so
the workaround in Database.get_directory is no longer necessary.
---
 bindings/python/notmuch/database.py |   19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/bindings/python/notmuch/database.py b/bindings/python/notmuch/database.py
index 1b1ddc3..797554d 100644
--- a/bindings/python/notmuch/database.py
+++ b/bindings/python/notmuch/database.py
@@ -73,8 +73,8 @@ class Database(object):
 
     """notmuch_database_get_directory"""
     _get_directory = nmlib.notmuch_database_get_directory
-    _get_directory.argtypes = [NotmuchDatabaseP, c_char_p]
-    _get_directory.restype = NotmuchDirectoryP
+    _get_directory.argtypes = [NotmuchDatabaseP, c_char_p, POINTER(NotmuchDirectoryP)]
+    _get_directory.restype = c_uint
 
     """notmuch_database_get_path"""
     _get_path = nmlib.notmuch_database_get_path
@@ -359,13 +359,6 @@ class Database(object):
         """
         self._assert_db_is_initialized()
 
-        # work around libnotmuch calling exit(3), see
-        # id:20120221002921.8534.57091@thinkbox.jade-hamburg.de
-        # TODO: remove once this issue is resolved
-        if self.mode != Database.MODE.READ_WRITE:
-            raise ReadOnlyDatabaseError('The database has to be opened in '
-                                        'read-write mode for get_directory')
-
         # sanity checking if path is valid, and make path absolute
         if path and path[0] == os.sep:
             # we got an absolute path
@@ -378,7 +371,13 @@ class Database(object):
             #we got a relative path, make it absolute
             abs_dirpath = os.path.abspath(os.path.join(self.get_path(), path))
 
-        dir_p = Database._get_directory(self._db, _str(path))
+        dir_p = NotmuchDirectoryP()
+        status = Database._get_directory(self._db, _str(path), byref(dir_p))
+
+        if status != STATUS.SUCCESS:
+            raise NotmuchError(status)
+        if not dir_p:
+            return None
 
         # return the Directory, init it with the absolute path
         return Directory(abs_dirpath, dir_p, self)
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 4/5] ruby: Update for changes to notmuch_database_get_directory
  2012-05-13 23:36 ` [PATCH v2 " Austin Clements
                     ` (2 preceding siblings ...)
  2012-05-13 23:36   ` [PATCH v2 3/5] python: " Austin Clements
@ 2012-05-13 23:36   ` Austin Clements
  2012-05-13 23:36   ` [PATCH v2 5/5] news: " Austin Clements
  2012-05-15 12:04   ` [PATCH v2 0/5] Fix notmuch_database_get_directory API David Bremner
  5 siblings, 0 replies; 17+ messages in thread
From: Austin Clements @ 2012-05-13 23:36 UTC (permalink / raw)
  To: notmuch; +Cc: tomi.ollila

---
 bindings/ruby/database.c |   11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/bindings/ruby/database.c b/bindings/ruby/database.c
index 409d54f..e84f726 100644
--- a/bindings/ruby/database.c
+++ b/bindings/ruby/database.c
@@ -252,6 +252,7 @@ VALUE
 notmuch_rb_database_get_directory (VALUE self, VALUE pathv)
 {
     const char *path;
+    notmuch_status_t ret;
     notmuch_directory_t *dir;
     notmuch_database_t *db;
 
@@ -260,11 +261,11 @@ notmuch_rb_database_get_directory (VALUE self, VALUE pathv)
     SafeStringValue (pathv);
     path = RSTRING_PTR (pathv);
 
-    dir = notmuch_database_get_directory (db, path);
-    if (!dir)
-        rb_raise (notmuch_rb_eXapianError, "Xapian exception");
-
-    return Data_Wrap_Struct (notmuch_rb_cDirectory, NULL, NULL, dir);
+    ret = notmuch_database_get_directory (db, path, &dir);
+    notmuch_rb_status_raise (ret);
+    if (dir)
+	return Data_Wrap_Struct (notmuch_rb_cDirectory, NULL, NULL, dir);
+    return Qnil;
 }
 
 /*
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 5/5] news: Update for changes to notmuch_database_get_directory
  2012-05-13 23:36 ` [PATCH v2 " Austin Clements
                     ` (3 preceding siblings ...)
  2012-05-13 23:36   ` [PATCH v2 4/5] ruby: " Austin Clements
@ 2012-05-13 23:36   ` Austin Clements
  2012-05-15 12:04   ` [PATCH v2 0/5] Fix notmuch_database_get_directory API David Bremner
  5 siblings, 0 replies; 17+ messages in thread
From: Austin Clements @ 2012-05-13 23:36 UTC (permalink / raw)
  To: notmuch; +Cc: tomi.ollila

---
 NEWS |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/NEWS b/NEWS
index c67f186..f987811 100644
--- a/NEWS
+++ b/NEWS
@@ -91,12 +91,12 @@ notmuch_database_close and notmuch_database_destroy
   database and thus release the lock associated with it without
   destroying the data structures obtained from it.
 
-notmuch_database_open and notmuch_database_create now return errors
+notmuch_database_open, notmuch_database_create, and
+notmuch_database_get_directory now return errors
 
-  The type signatures of notmuch_database_open and
-  notmuch_database_create have changed so that the functions now
-  return a notmuch_status_t and take an out-argument for returning the
-  new database object.
+  The type signatures of these functions have changed so that the
+  functions now return a notmuch_status_t and take an out-argument for
+  returning the new database object or directory object.
 
 go bindings changes
 -------------------
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 0/5] Fix notmuch_database_get_directory API
  2012-05-13 23:36 ` [PATCH v2 " Austin Clements
                     ` (4 preceding siblings ...)
  2012-05-13 23:36   ` [PATCH v2 5/5] news: " Austin Clements
@ 2012-05-15 12:04   ` David Bremner
  5 siblings, 0 replies; 17+ messages in thread
From: David Bremner @ 2012-05-15 12:04 UTC (permalink / raw)
  To: Austin Clements, notmuch; +Cc: tomi.ollila

Austin Clements <amdragon@MIT.EDU> writes:

> This version moves a Python bindings change that had slipped into the
> Go patch into the Python patch and words the future-proofing warning
> on notmuch_database_get_directory more strongly.  There are no code
> changes from v1.

Pushed to master, for now.  Assuming no fires break out, I'll merge to
release later today, and call that 0.13

d

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2012-05-15 12:04 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-13 19:57 [PATCH 0/5] Fix notmuch_database_get_directory API Austin Clements
2012-05-13 19:57 ` [PATCH 1/5] lib/cli: Make notmuch_database_get_directory return a status code Austin Clements
2012-05-13 19:57 ` [PATCH 2/5] go: Update for changes to notmuch_database_get_directory Austin Clements
2012-05-13 21:51   ` Justus Winter
2012-05-13 23:15     ` Austin Clements
2012-05-13 19:57 ` [PATCH 3/5] python: " Austin Clements
2012-05-13 19:57 ` [PATCH 4/5] ruby: " Austin Clements
2012-05-13 19:57 ` [PATCH 5/5] news: " Austin Clements
2012-05-13 20:49 ` [PATCH 0/5] Fix notmuch_database_get_directory API Tomi Ollila
2012-05-13 21:55   ` Justus Winter
2012-05-13 23:36 ` [PATCH v2 " Austin Clements
2012-05-13 23:36   ` [PATCH v2 1/5] lib/cli: Make notmuch_database_get_directory return a status code Austin Clements
2012-05-13 23:36   ` [PATCH v2 2/5] go: Update for changes to notmuch_database_get_directory Austin Clements
2012-05-13 23:36   ` [PATCH v2 3/5] python: " Austin Clements
2012-05-13 23:36   ` [PATCH v2 4/5] ruby: " Austin Clements
2012-05-13 23:36   ` [PATCH v2 5/5] news: " Austin Clements
2012-05-15 12:04   ` [PATCH v2 0/5] Fix notmuch_database_get_directory API David Bremner

Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).