]> git.notmuchmail.org Git - notmuch/commitdiff
Merge tag '0.20.2'
authorDavid Bremner <david@tethera.net>
Sat, 27 Jun 2015 13:29:52 +0000 (15:29 +0200)
committerDavid Bremner <david@tethera.net>
Sat, 27 Jun 2015 13:29:52 +0000 (15:29 +0200)
notmuch 0.20.2 release

Conflicts:
NEWS

38 files changed:
Makefile.local
NEWS
bindings/Makefile [new file with mode: 0644]
bindings/Makefile.local [new file with mode: 0644]
bindings/ruby/README [new file with mode: 0644]
bindings/ruby/extconf.rb
configure
debian/rules
devel/release-checks.sh
doc/man1/notmuch.rst
emacs/notmuch.el
lib/Makefile.local
lib/database.cc
lib/notmuch.h
notmuch-client.h
notmuch-compact.c
notmuch-config.c
notmuch-count.c
notmuch-dump.c
notmuch-insert.c
notmuch-new.c
notmuch-reply.c
notmuch-restore.c
notmuch-search.c
notmuch-setup.c
notmuch-show.c
notmuch-tag.c
notmuch.c
performance-test/perf-test-lib.sh
test/T010-help-test.sh
test/T070-insert.sh
test/T360-symbol-hiding.sh
test/T390-python.sh
test/T395-ruby.sh [new file with mode: 0755]
test/T560-lib-error.sh
test/random-corpus.c
test/symbol-test.cc
test/test-lib.sh

index 6d54742334a238cb2fb08e65e9ff0ed09416fe13..61a9c4c3a7398ada89ff7dc7a78bd0f7af473ae2 100644 (file)
@@ -59,7 +59,7 @@ endif
 FINAL_LIBNOTMUCH_LDFLAGS = $(LDFLAGS) $(AS_NEEDED_LDFLAGS) $(CONFIGURE_LDFLAGS)
 
 .PHONY: all
-all: notmuch notmuch-shared build-man
+all: notmuch notmuch-shared build-man ruby-bindings
 ifeq ($(MAKECMDGOALS),)
 ifeq ($(shell cat .first-build-message 2>/dev/null),)
        @NOTMUCH_FIRST_BUILD=1 $(MAKE) --no-print-directory all
diff --git a/NEWS b/NEWS
index cc8d7edf2432dc804e06dd3c69669e2acfea8acc..e474e53ed7d5b99eae1a62d0442b6bbb4b9c7d36 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+Notmuch 0.21 (UNRELEASED)
+=========================
+
+Library
+-------
+
+The use of absolute paths is now enforced when calling notmuch_database_{open, create}
+
 Notmuch 0.20.2 (2015-06-27)
 ===========================
 
@@ -2767,7 +2775,7 @@ New 'G' key binding to trigger mail refresh (G == "Get new mail")
 
   The 'G' key works wherever '=' works. Before refreshing the screen
   it calls an external program that can be used to poll email servers,
-  run notmuch new and setup specific tags for the new emails. The
+  run notmuch new and set up specific tags for the new emails. The
   script to be called should be configured with the "Notmuch Poll
   Script" setting in the customize interface. This script will
   typically invoke "notmuch new" and then perhaps several "notmuch
diff --git a/bindings/Makefile b/bindings/Makefile
new file mode 100644 (file)
index 0000000..de492a7
--- /dev/null
@@ -0,0 +1,7 @@
+# See Makefile.local for the list of files to be compiled in this
+# directory.
+all:
+       $(MAKE) -C .. all
+
+.DEFAULT:
+       $(MAKE) -C .. $@
diff --git a/bindings/Makefile.local b/bindings/Makefile.local
new file mode 100644 (file)
index 0000000..4ecf839
--- /dev/null
@@ -0,0 +1,21 @@
+# -*- makefile -*-
+
+dir := bindings
+
+# force the shared library to be built
+ruby-bindings: lib/$(LINKER_NAME)
+ifeq ($(HAVE_RUBY_DEV),1)
+       cd $(dir)/ruby && \
+               EXTRA_LDFLAGS="$(NO_UNDEFINED_LDFLAGS)" \
+               LIBNOTMUCH="../../lib/$(LINKER_NAME)" \
+               ruby extconf.rb --vendor
+       $(MAKE) -C $(dir)/ruby
+else
+       @echo Missing dependency, skipping ruby bindings
+endif
+
+CLEAN += $(patsubst %,$(dir)/ruby/%, \
+       .RUBYARCHDIR.time \
+       Makefile database.o directory.o filenames.o\
+       init.o message.o messages.o mkmf.log notmuch.so query.o \
+       status.o tags.o thread.o threads.o)
diff --git a/bindings/ruby/README b/bindings/ruby/README
new file mode 100644 (file)
index 0000000..a2946b6
--- /dev/null
@@ -0,0 +1,7 @@
+To build the the notmuch ruby extension, run the following commands
+from the *top level* notmuch source directory:
+
+% ./configure
+% make ruby-bindings
+
+The generic documentation about building notmuch also applies.
index 6160db26e2ea10286fb16065c2c030ea90a0c07e..ddaa6841e5ff2d507c65501f6d81dd00f9e942fe 100644 (file)
@@ -10,22 +10,16 @@ dir = File.join('..', '..', 'lib')
 # includes
 $INCFLAGS = "-I#{dir} #{$INCFLAGS}"
 
-# make sure there are no undefined symbols
-$LDFLAGS += ' -Wl,--no-undefined'
-
-def have_local_library(lib, path, func, headers = nil)
-  checking_for checking_message(func, lib) do
-    lib = File.join(path, lib)
-    if try_func(func, lib, headers)
-      $LOCAL_LIBS += lib
-    end
-  end
+if ENV['EXTRA_LDFLAGS']
+  $LDFLAGS += " " + ENV['EXTRA_LDFLAGS']
 end
 
-if not have_local_library('libnotmuch.so', dir, 'notmuch_database_create', 'notmuch.h')
+if not ENV['LIBNOTMUCH']
   exit 1
 end
 
+$LOCAL_LIBS += ENV['LIBNOTMUCH']
+
 # Create Makefile
 dir_config('notmuch')
 create_makefile('notmuch')
index 4af7ba94f7bd344cba6fb9e355e10ae5034717a4..b967a4ed04294d76d855ee509c66337c6f21d00f 100755 (executable)
--- a/configure
+++ b/configure
@@ -21,6 +21,7 @@ srcdir=$(dirname "$0")
 
 subdirs="util compat lib parse-time-string completion doc emacs"
 subdirs="${subdirs} performance-test test test/test-databases"
+subdirs="${subdirs} bindings"
 
 # For a non-srcdir configure invocation (such as ../configure), create
 # the directory structure and copy Makefiles.
@@ -47,9 +48,11 @@ CC=${CC:-cc}
 CXX=${CXX:-c++}
 CFLAGS=${CFLAGS:--g -O2}
 CPPFLAGS=${CPPFLAGS:-}
+CXXFLAGS_for_sh=${CXXFLAGS:-${CFLAGS}}
 CXXFLAGS=${CXXFLAGS:-\$(CFLAGS)}
 LDFLAGS=${LDFLAGS:-}
 XAPIAN_CONFIG=${XAPIAN_CONFIG:-xapian-config}
+PYTHON=${PYTHON:-}
 
 # We don't allow the EMACS or GZIP Makefile variables inherit values
 # from the environment as we do with CC and CXX above. The reason is
@@ -269,6 +272,35 @@ dependencies are available:
 EOF
 
 errors=0
+printf "int main(void){return 0;}\n" > minimal.c
+
+printf "Sanity checking C compilation environment... "
+if ${CC} ${CFLAGS} ${CPPFLAGS} minimal.c ${LDFLAGS} -o minimal > /dev/null 2>&1
+then
+    printf "OK.\n"
+else
+    printf "Fail.\n"
+    errors=$((errors + 1))
+fi
+
+printf "Sanity checking C++ compilation environment... "
+if ${CXX} ${CXXFLAGS_for_sh} ${CPPFLAGS} minimal.c ${LDFLAGS} -o minimal > /dev/null 2>&1
+then
+    printf "OK.\n"
+else
+    printf "Fail.\n"
+    errors=$((errors + 1))
+fi
+
+if [ $errors -gt 0 ]; then
+    cat <<EOF
+*** Error: Initial sanity checking of environment failed.  Please try
+running configure in a clean environment, and if the problem persists,
+report a bug.
+EOF
+    rm -f minimal minimal.c
+    exit 1
+fi
 
 if pkg-config --version > /dev/null 2>&1; then
     have_pkg_config=1
@@ -377,7 +409,7 @@ fi
 printf "Checking for python... "
 have_python=0
 
-for name in python python2 python3; do
+for name in ${PYTHON} python python2 python3; do
     if command -v $name > /dev/null; then
        have_python=1
        python=$name
@@ -443,6 +475,15 @@ else
     have_doxygen=0
 fi
 
+printf "Checking for ruby development files... "
+if ruby -e "require 'mkmf'"> /dev/null 2>&1; then
+    printf "Yes.\n"
+    have_ruby_dev=1
+else
+    printf "No (skipping ruby bindings)\n"
+    have_ruby_dev=0
+fi
+
 printf "Checking if sphinx is available and supports nroff output... "
 if command -v sphinx-build > /dev/null && ${python} -m sphinx.writers.manpage > /dev/null 2>&1 ; then
     printf "Yes.\n"
@@ -690,8 +731,6 @@ else
 fi
 rm -f compat/check_asctime
 
-printf "int main(void){return 0;}\n" > minimal.c
-
 printf "Checking for rpath support... "
 if ${CC} -Wl,--enable-new-dtags -Wl,-rpath,/tmp/ -o minimal minimal.c >/dev/null 2>&1
 then
@@ -712,6 +751,16 @@ else
     as_needed_ldflags=""
 fi
 
+printf "Checking for -Wl,--no-undefined... "
+if ${CC} -Wl,--no-undefined -o minimal minimal.c >/dev/null 2>&1
+then
+    printf "Yes.\n"
+    no_undefined_ldflags="-Wl,--no-undefined"
+else
+    printf "No (nothing to worry about).\n"
+    no_undefined_ldflags=""
+fi
+
 WARN_CXXFLAGS=""
 printf "Checking for available C++ compiler warning flags... "
 for flag in -Wall -Wextra -Wwrite-strings; do
@@ -858,6 +907,10 @@ HAVE_CANONICALIZE_FILE_NAME = ${have_canonicalize_file_name}
 # build its own version)
 HAVE_GETLINE = ${have_getline}
 
+# Are the ruby development files (and ruby) available? If not skip
+# building/testing ruby bindings.
+HAVE_RUBY_DEV = ${have_ruby_dev}
+
 # Whether the strcasestr function is available (if not, then notmuch will
 # build its own version)
 HAVE_STRCASESTR = ${have_strcasestr}
@@ -912,6 +965,9 @@ RPATH_LDFLAGS = ${rpath_ldflags}
 # Flags needed to have linker link only to necessary libraries
 AS_NEEDED_LDFLAGS = ${as_needed_ldflags}
 
+# Flags to have the linker flag undefined symbols in object files
+NO_UNDEFINED_LDFLAGS = ${no_undefined_ldflags}
+
 # Whether valgrind header files are available
 HAVE_VALGRIND = ${have_valgrind}
 
@@ -970,6 +1026,10 @@ NOTMUCH_HAVE_MAN=$((have_sphinx))
 
 # Name of python interpreter
 NOTMUCH_PYTHON=${python}
+
+# Are the ruby development files (and ruby) available? If not skip
+# building/testing ruby bindings.
+NOTMUCH_HAVE_RUBY_DEV=${have_ruby_dev}
 EOF
 
 # Finally, after everything configured, inform the user how to continue.
index 56378ecd66827c6c1391c7e9011319153352c341..04f0062a53ab992eb8f0f927a7644ab1a48d128a 100755 (executable)
@@ -19,7 +19,6 @@ override_dh_auto_build:
        dh_auto_build -- V=1
        dh_auto_build --sourcedirectory bindings/python
        cd bindings/python && $(python3_all) setup.py build
-       cd bindings/ruby && ruby extconf.rb --vendor && make
        $(MAKE) -C contrib/notmuch-mutt
 
 override_dh_auto_clean:
index ae02f557af23bda8488035367d2ae8eae5f95bb6..efd0b3441f2e9aecd7398cf941c1156eec77ff0d 100755 (executable)
@@ -59,6 +59,17 @@ readonly VERSION
 
 # In the rest of this file, tests collect list of errors to be fixed
 
+echo -n "Checking that git working directory is clean... "
+git_status=`git status --porcelain`
+if [ "$git_status" = '' ]
+then
+       echo Yes.
+else
+       echo No.
+       append_emsg "Git working directory is not clean (git status --porcelain)."
+fi
+unset git_status
+
 verfail ()
 {
        echo No.
index b33738ed33166699fb3872610634aa2f984e7c74..ae0461a2725e09d8c367dfcd5eefbaca2c1a51c4 100644 (file)
@@ -49,6 +49,10 @@ Supported global options for ``notmuch`` include
         Specify the configuration file to use. This overrides any
         configuration file specified by ${NOTMUCH\_CONFIG}.
 
+All global options except ``--config`` can also be specified after the
+command. For example, ``notmuch subcommand --version`` is equivalent to
+``notmuch --version subcommand``.
+
 COMMANDS
 ========
 
index ab00454357ef12f26b2f92b9705f30093d753a1f..6564816f078659f23ab5f6a6c6fc51478aa695ae 100644 (file)
@@ -181,6 +181,7 @@ there will be called at other points of notmuch execution."
 (defvar notmuch-search-stash-map
   (let ((map (make-sparse-keymap)))
     (define-key map "i" 'notmuch-search-stash-thread-id)
+    (define-key map "q" 'notmuch-stash-query)
     (define-key map "?" 'notmuch-subkeymap-help)
     map)
   "Submap for stash commands")
@@ -191,6 +192,11 @@ there will be called at other points of notmuch execution."
   (interactive)
   (notmuch-common-do-stash (notmuch-search-find-thread-id)))
 
+(defun notmuch-stash-query ()
+  "Copy current query to kill-ring."
+  (interactive)
+  (notmuch-common-do-stash (notmuch-search-get-query)))
+
 (defvar notmuch-search-query-string)
 (defvar notmuch-search-target-thread)
 (defvar notmuch-search-target-line)
@@ -855,13 +861,15 @@ See `notmuch-tag' for information on the format of TAG-CHANGES."
   "Read a notmuch-query from the minibuffer with completion.
 
 PROMPT is the string to prompt with."
-  (lexical-let
-      ((completions
-       (append (list "folder:" "path:" "thread:" "id:" "date:" "from:" "to:"
-                     "subject:" "attachment:" "mimetype:")
-               (mapcar (lambda (tag)
-                         (concat "tag:" (notmuch-escape-boolean-term tag)))
-                       (process-lines notmuch-command "search" "--output=tags" "*")))))
+  (lexical-let*
+      ((all-tags
+        (mapcar (lambda (tag) (notmuch-escape-boolean-term tag))
+                (process-lines notmuch-command "search" "--output=tags" "*")))
+       (completions
+        (append (list "folder:" "path:" "thread:" "id:" "date:" "from:" "to:"
+                      "subject:" "attachment:" "mimetype:")
+                (mapcar (lambda (tag) (concat "tag:" tag)) all-tags)
+                (mapcar (lambda (tag) (concat "is:" tag)) all-tags))))
     (let ((keymap (copy-keymap minibuffer-local-map))
          (current-query (case major-mode
                           (notmuch-search-mode (notmuch-search-get-query))
index f9ecd50e7366f6afed8e5cd132e4ea83185d33cd..b58b4e8a425f8bbf0da01642fc44902268962899 100644 (file)
@@ -33,7 +33,7 @@ LIBRARY_SUFFIX = so
 LINKER_NAME = libnotmuch.$(LIBRARY_SUFFIX)
 SONAME = $(LINKER_NAME).$(LIBNOTMUCH_VERSION_MAJOR)
 LIBNAME = $(SONAME).$(LIBNOTMUCH_VERSION_MINOR).$(LIBNOTMUCH_VERSION_RELEASE)
-LIBRARY_LINK_FLAG = -shared -Wl,--version-script=notmuch.sym,-soname=$(SONAME) -Wl,--no-undefined
+LIBRARY_LINK_FLAG = -shared -Wl,--version-script=notmuch.sym,-soname=$(SONAME) $(NO_UNDEFINED_LDFLAGS)
 ifeq ($(PLATFORM),OPENBSD)
 LIBRARY_LINK_FLAG += -lc
 endif
index cffab62c895b3dd318855ae27445ad55488de97b..6a15174959812cbb73455670038e55415b5a3105 100644 (file)
@@ -342,6 +342,8 @@ notmuch_status_to_string (notmuch_status_t status)
        return "Unsupported operation";
     case NOTMUCH_STATUS_UPGRADE_REQUIRED:
        return "Operation requires a database upgrade";
+    case NOTMUCH_STATUS_PATH_ERROR:
+       return "Path supplied is illegal for this function";
     default:
     case NOTMUCH_STATUS_LAST_STATUS:
        return "Unknown error status value";
@@ -657,6 +659,12 @@ notmuch_database_create_verbose (const char *path,
        goto DONE;
     }
 
+    if (path[0] != '/') {
+       message = strdup ("Error: Database path must be absolute.\n");
+       status = NOTMUCH_STATUS_PATH_ERROR;
+       goto DONE;
+    }
+
     err = stat (path, &st);
     if (err) {
        IGNORE_RESULT (asprintf (&message, "Error: Cannot create database at %s: %s.\n",
@@ -847,6 +855,12 @@ notmuch_database_open_verbose (const char *path,
        goto DONE;
     }
 
+    if (path[0] != '/') {
+       message = strdup ("Error: Database path must be absolute.\n");
+       status = NOTMUCH_STATUS_PATH_ERROR;
+       goto DONE;
+    }
+
     if (! (notmuch_path = talloc_asprintf (local, "%s/%s", path, ".notmuch"))) {
        message = strdup ("Out of memory\n");
        status = NOTMUCH_STATUS_OUT_OF_MEMORY;
@@ -1336,7 +1350,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
        return NOTMUCH_STATUS_SUCCESS;
 
     if (progress_notify) {
-       /* Setup our handler for SIGALRM */
+       /* Set up our handler for SIGALRM */
        memset (&action, 0, sizeof (struct sigaction));
        action.sa_handler = handle_sigalrm;
        sigemptyset (&action.sa_mask);
index 20c4e0190c5cdc2f9e5d5464e9ab67192d424534..c8edc84dcbd702a3916b6204a6171d786b9956d2 100644 (file)
@@ -163,6 +163,11 @@ typedef enum _notmuch_status {
      * The operation requires a database upgrade.
      */
     NOTMUCH_STATUS_UPGRADE_REQUIRED,
+    /**
+     * There is a problem with the proposed path, e.g. a relative path
+     * passed to a function expecting an absolute path.
+     */
+    NOTMUCH_STATUS_PATH_ERROR,
     /**
      * Not an actual status value. Just a way to find out how many
      * valid status values there are.
index fb3021cc37c1aec68a9b2b193b1cea9c011cd200..78680aa122af56dc9cd9432982e51e713594db14 100644 (file)
@@ -466,4 +466,8 @@ notmuch_database_dump (notmuch_database_t *notmuch,
                       notmuch_bool_t gzip_output);
 
 #include "command-line-arguments.h"
+extern const notmuch_opt_desc_t  notmuch_shared_options [];
+void notmuch_process_shared_options (const char* subcommand_name);
+int notmuch_minimal_options (const char* subcommand_name,
+                            int argc, char **argv);
 #endif
index 2fc012a982d7f3b879fc6fe795d01b194b240c31..5be551d4ed733750cf1d685bcc89ac831e19de4b 100644 (file)
@@ -38,12 +38,16 @@ notmuch_compact_command (notmuch_config_t *config, int argc, char *argv[])
     notmuch_opt_desc_t options[] = {
        { NOTMUCH_OPT_STRING, &backup_path, "backup", 0, 0 },
        { NOTMUCH_OPT_BOOLEAN,  &quiet, "quiet", 'q', 0 },
+       { NOTMUCH_OPT_INHERIT, (void *) &notmuch_shared_options, NULL, 0, 0 },
+       { 0, 0, 0, 0, 0}
     };
 
     opt_index = parse_arguments (argc, argv, options, 1);
     if (opt_index < 0)
        return EXIT_FAILURE;
 
+    notmuch_process_shared_options (argv[0]);
+
     if (! quiet)
        printf ("Compacting database...\n");
     ret = notmuch_database_compact (path, backup_path,
index 2d5c297b7f5f2996b89c6e7c9502df90a06c93d6..934827874b1eb3548fa6b9fa1fdf4d9955174ee6 100644 (file)
@@ -872,8 +872,15 @@ int
 notmuch_config_command (notmuch_config_t *config, int argc, char *argv[])
 {
     int ret;
+    int opt_index;
 
-    argc--; argv++; /* skip subcommand argument */
+    opt_index = notmuch_minimal_options ("config", argc, argv);
+    if (opt_index < 0)
+       return EXIT_FAILURE;
+
+    /* skip at least subcommand argument */
+    argc-= opt_index;
+    argv+= opt_index;
 
     if (argc < 1) {
        fprintf (stderr, "Error: notmuch config requires at least one argument.\n");
index 6058f7c9510d6bdbc15a22c4f24a630eadc50666..57a88a8d1806df1bb0616b64a2555994319f37dd 100644 (file)
@@ -146,6 +146,7 @@ notmuch_count_command (notmuch_config_t *config, int argc, char *argv[])
                                  { 0, 0 } } },
        { NOTMUCH_OPT_BOOLEAN, &batch, "batch", 0, 0 },
        { NOTMUCH_OPT_STRING, &input_file_name, "input", 'i', 0 },
+       { NOTMUCH_OPT_INHERIT, (void *) &notmuch_shared_options, NULL, 0, 0 },
        { 0, 0, 0, 0, 0 }
     };
 
@@ -153,6 +154,8 @@ notmuch_count_command (notmuch_config_t *config, int argc, char *argv[])
     if (opt_index < 0)
        return EXIT_FAILURE;
 
+    notmuch_process_shared_options (argv[0]);
+
     if (input_file_name) {
        batch = TRUE;
        input = fopen (input_file_name, "r");
index 9c6ad7f47b0fde514a5e64c96705d598f2eee7ec..fab22bdd6bcfe7f1b0ca26e433001d49e416c4ab 100644 (file)
@@ -228,6 +228,7 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])
                                  { 0, 0 } } },
        { NOTMUCH_OPT_STRING, &output_file_name, "output", 'o', 0  },
        { NOTMUCH_OPT_BOOLEAN, &gzip_output, "gzip", 'z', 0 },
+       { NOTMUCH_OPT_INHERIT, (void *) &notmuch_shared_options, NULL, 0, 0 },
        { 0, 0, 0, 0, 0 }
     };
 
@@ -235,6 +236,8 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])
     if (opt_index < 0)
        return EXIT_FAILURE;
 
+    notmuch_process_shared_options (argv[0]);
+
     if (opt_index < argc) {
        query_str = query_string_from_args (notmuch, argc - opt_index, argv + opt_index);
        if (query_str == NULL) {
index 90fe3bad2bfb7291d3d81e6deafb50e6b62d913e..c277d6206712a23718cbd4c75d55c7fc3bb688e7 100644 (file)
@@ -466,6 +466,7 @@ notmuch_insert_command (notmuch_config_t *config, int argc, char *argv[])
        { NOTMUCH_OPT_BOOLEAN, &create_folder, "create-folder", 0, 0 },
        { NOTMUCH_OPT_BOOLEAN, &keep, "keep", 0, 0 },
        { NOTMUCH_OPT_BOOLEAN,  &no_hooks, "no-hooks", 'n', 0 },
+       { NOTMUCH_OPT_INHERIT, (void *) &notmuch_shared_options, NULL, 0, 0 },
        { NOTMUCH_OPT_END, 0, 0, 0, 0 }
     };
 
@@ -473,6 +474,8 @@ notmuch_insert_command (notmuch_config_t *config, int argc, char *argv[])
     if (opt_index < 0)
        return EXIT_FAILURE;
 
+    notmuch_process_shared_options (argv[0]);
+
     db_path = notmuch_config_get_database_path (config);
     new_tags = notmuch_config_get_new_tags (config, &new_tags_length);
     synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config);
@@ -521,7 +524,7 @@ notmuch_insert_command (notmuch_config_t *config, int argc, char *argv[])
            return EXIT_FAILURE;
     }
 
-    /* Setup our handler for SIGINT. We do not set SA_RESTART so that copying
+    /* Set up our handler for SIGINT. We do not set SA_RESTART so that copying
      * from standard input may be interrupted. */
     memset (&action, 0, sizeof (struct sigaction));
     action.sa_handler = handle_sigint;
index e6c283eb7ca123b762f0db4fa69cb33cb17d3e31..8ff1ade70e49565b0c456272e51133e2e7c9bf17 100644 (file)
@@ -662,7 +662,7 @@ setup_progress_printing_timer (void)
     struct sigaction action;
     struct itimerval timerval;
 
-    /* Setup our handler for SIGALRM */
+    /* Set up our handler for SIGALRM */
     memset (&action, 0, sizeof (struct sigaction));
     action.sa_handler = handle_sigalrm;
     sigemptyset (&action.sa_mask);
@@ -934,6 +934,7 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
        { NOTMUCH_OPT_BOOLEAN,  &verbose, "verbose", 'v', 0 },
        { NOTMUCH_OPT_BOOLEAN,  &add_files_state.debug, "debug", 'd', 0 },
        { NOTMUCH_OPT_BOOLEAN,  &no_hooks, "no-hooks", 'n', 0 },
+       { NOTMUCH_OPT_INHERIT, (void *) &notmuch_shared_options, NULL, 0, 0 },
        { 0, 0, 0, 0, 0 }
     };
 
@@ -941,6 +942,8 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
     if (opt_index < 0)
        return EXIT_FAILURE;
 
+    notmuch_process_shared_options (argv[0]);
+
     /* quiet trumps verbose */
     if (quiet)
        add_files_state.verbosity = VERBOSITY_QUIET;
@@ -1047,7 +1050,7 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
     if (notmuch == NULL)
        return EXIT_FAILURE;
 
-    /* Setup our handler for SIGINT. We do this after having
+    /* Set up our handler for SIGINT. We do this after having
      * potentially done a database upgrade we this interrupt handler
      * won't support. */
     memset (&action, 0, sizeof (struct sigaction));
index d51fdfc360dd58edc1e5358433663273188aa8a9..4464741fe3567e974e6f07038b93f6446b744150 100644 (file)
@@ -790,6 +790,7 @@ notmuch_reply_command (notmuch_config_t *config, int argc, char *argv[])
                                  { "sender", FALSE },
                                  { 0, 0 } } },
        { NOTMUCH_OPT_BOOLEAN, &params.crypto.decrypt, "decrypt", 'd', 0 },
+       { NOTMUCH_OPT_INHERIT, (void *) &notmuch_shared_options, NULL, 0, 0 },
        { 0, 0, 0, 0, 0 }
     };
 
@@ -797,6 +798,8 @@ notmuch_reply_command (notmuch_config_t *config, int argc, char *argv[])
     if (opt_index < 0)
        return EXIT_FAILURE;
 
+    notmuch_process_shared_options (argv[0]);
+
     if (format == FORMAT_HEADERS_ONLY) {
        reply_format_func = notmuch_reply_format_headers_only;
     } else if (format == FORMAT_JSON) {
index 584d9f96ade8dc33a12213b4df6384ed553f9027..2a534dc4544886febb16a246c2caf8d60245baf0 100644 (file)
@@ -154,6 +154,7 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[])
                                  { 0, 0 } } },
        { NOTMUCH_OPT_STRING, &input_file_name, "input", 'i', 0 },
        { NOTMUCH_OPT_BOOLEAN,  &accumulate, "accumulate", 'a', 0 },
+       { NOTMUCH_OPT_INHERIT, (void *) &notmuch_shared_options, NULL, 0, 0 },
        { 0, 0, 0, 0, 0 }
     };
 
@@ -163,6 +164,7 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[])
        goto DONE;
     }
 
+    notmuch_process_shared_options (argv[0]);
     name_for_error = input_file_name ? input_file_name : "stdin";
 
     if (! accumulate)
index b81ac0134ef23cbcfec3d37f063a6f758cc99fdf..b89a17e5c4bfd5adeb5c3a9ce4aa74ca1c58da14 100644 (file)
@@ -681,6 +681,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
        { NOTMUCH_OPT_INT, &ctx->limit, "limit", 'L', 0  },
        { NOTMUCH_OPT_INT, &ctx->dupe, "duplicate", 'D', 0  },
        { NOTMUCH_OPT_INHERIT, (void *) &common_options, NULL, 0, 0 },
+       { NOTMUCH_OPT_INHERIT, (void *) &notmuch_shared_options, NULL, 0, 0 },
        { 0, 0, 0, 0, 0 }
     };
 
@@ -689,6 +690,8 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
     if (opt_index < 0)
        return EXIT_FAILURE;
 
+    notmuch_process_shared_options (argv[0]);
+
     if (ctx->output != OUTPUT_FILES && ctx->output != OUTPUT_MESSAGES &&
        ctx->dupe != -1) {
         fprintf (stderr, "Error: --duplicate=N is only supported with --output=files and --output=messages.\n");
@@ -737,6 +740,7 @@ notmuch_address_command (notmuch_config_t *config, int argc, char *argv[])
                                  { "false", NOTMUCH_EXCLUDE_FALSE },
                                  { 0, 0 } } },
        { NOTMUCH_OPT_INHERIT, (void *) &common_options, NULL, 0, 0 },
+       { NOTMUCH_OPT_INHERIT, (void *) &notmuch_shared_options, NULL, 0, 0 },
        { 0, 0, 0, 0, 0 }
     };
 
@@ -744,6 +748,8 @@ notmuch_address_command (notmuch_config_t *config, int argc, char *argv[])
     if (opt_index < 0)
        return EXIT_FAILURE;
 
+    notmuch_process_shared_options (argv[0]);
+
     if (! (ctx->output & (OUTPUT_SENDER | OUTPUT_RECIPIENTS)))
        ctx->output |= OUTPUT_SENDER;
 
index 36a6171a695b2bde194eab0dab3a577c91e265fe..7dd5822a9365c0490b9860532de03c1c4c18251c 100644 (file)
@@ -145,6 +145,9 @@ notmuch_setup_command (notmuch_config_t *config,
        chomp_newline (response);                               \
     } while (0)
 
+    if (notmuch_minimal_options ("setup", argc, argv) < 0)
+       return EXIT_FAILURE;
+
     if (notmuch_config_is_new (config))
        welcome_message_pre_setup ();
 
index 43bf71c8c8924e80c28f08469d2615642cba44b4..b80933ad3a00963e07047c56707863291d9e321e 100644 (file)
@@ -1114,6 +1114,7 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[])
        { NOTMUCH_OPT_BOOLEAN, &params.crypto.verify, "verify", 'v', 0 },
        { NOTMUCH_OPT_BOOLEAN, &params.output_body, "body", 'b', 0 },
        { NOTMUCH_OPT_BOOLEAN, &params.include_html, "include-html", 0, 0 },
+       { NOTMUCH_OPT_INHERIT, (void *) &notmuch_shared_options, NULL, 0, 0 },
        { 0, 0, 0, 0, 0 }
     };
 
@@ -1121,6 +1122,8 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[])
     if (opt_index < 0)
        return EXIT_FAILURE;
 
+    notmuch_process_shared_options (argv[0]);
+
     /* decryption implies verification */
     if (params.crypto.decrypt)
        params.crypto.verify = TRUE;
index 5b2f1e48d6a7ce7d19bae37f9838ad040cbf2642..38d99aa9db0be0a40ee720b5776f0fa3ae7167f6 100644 (file)
@@ -195,7 +195,7 @@ notmuch_tag_command (notmuch_config_t *config, int argc, char *argv[])
     int opt_index;
     int ret;
 
-    /* Setup our handler for SIGINT */
+    /* Set up our handler for SIGINT */
     memset (&action, 0, sizeof (struct sigaction));
     action.sa_handler = handle_sigint;
     sigemptyset (&action.sa_mask);
@@ -206,6 +206,7 @@ notmuch_tag_command (notmuch_config_t *config, int argc, char *argv[])
        { NOTMUCH_OPT_BOOLEAN, &batch, "batch", 0, 0 },
        { NOTMUCH_OPT_STRING, &input_file_name, "input", 'i', 0 },
        { NOTMUCH_OPT_BOOLEAN, &remove_all, "remove-all", 0, 0 },
+       { NOTMUCH_OPT_INHERIT, (void *) &notmuch_shared_options, NULL, 0, 0 },
        { 0, 0, 0, 0, 0 }
     };
 
@@ -213,6 +214,8 @@ notmuch_tag_command (notmuch_config_t *config, int argc, char *argv[])
     if (opt_index < 0)
        return EXIT_FAILURE;
 
+    notmuch_process_shared_options (argv[0]);
+
     if (input_file_name) {
        batch = TRUE;
        input = fopen (input_file_name, "r");
index a5b2877aee09243044b960d6b3b1f833fbf091af..c528dce2d12100b66d9dffd00093faefd33f5965 100644 (file)
--- a/notmuch.c
+++ b/notmuch.c
@@ -43,11 +43,62 @@ notmuch_help_command (notmuch_config_t *config, int argc, char *argv[]);
 static int
 notmuch_command (notmuch_config_t *config, int argc, char *argv[]);
 
+static int
+_help_for (const char *topic);
+
+static notmuch_bool_t print_version = FALSE, print_help = FALSE;
+
+const notmuch_opt_desc_t notmuch_shared_options [] = {
+    { NOTMUCH_OPT_BOOLEAN, &print_version, "version", 'v', 0 },
+    { NOTMUCH_OPT_BOOLEAN, &print_help, "help", 'h', 0 },
+    {0, 0, 0, 0, 0}
+};
+
+/* any subcommand wanting to support these options should call
+ * inherit notmuch_shared_options and call
+ * notmuch_process_shared_options (subcommand_name);
+ */
+void
+notmuch_process_shared_options (const char *subcommand_name) {
+    if (print_version) {
+       printf ("notmuch " STRINGIFY(NOTMUCH_VERSION) "\n");
+       exit (EXIT_SUCCESS);
+    }
+
+    if (print_help) {
+       int ret = _help_for (subcommand_name);
+       exit (ret);
+    }
+}
+
+/* This is suitable for subcommands that do not actually open the
+ * database.
+ */
+int notmuch_minimal_options (const char *subcommand_name,
+                                 int argc, char **argv)
+{
+    int opt_index;
+
+    notmuch_opt_desc_t options[] = {
+       { NOTMUCH_OPT_INHERIT, (void *) &notmuch_shared_options, NULL, 0, 0 },
+       { 0, 0, 0, 0, 0 }
+    };
+
+    opt_index = parse_arguments (argc, argv, options, 1);
+
+    if (opt_index < 0)
+       return -1;
+
+    /* We can't use argv here as it is sometimes NULL */
+    notmuch_process_shared_options (subcommand_name);
+    return opt_index;
+}
+
 static command_t commands[] = {
     { NULL, notmuch_command, TRUE,
       "Notmuch main command." },
     { "setup", notmuch_setup_command, TRUE,
-      "Interactively setup notmuch for first use." },
+      "Interactively set up notmuch for first use." },
     { "new", notmuch_new_command, FALSE,
       "Find and import new messages to the notmuch database." },
     { "insert", notmuch_insert_command, FALSE,
@@ -177,21 +228,19 @@ exec_man (const char *page)
 }
 
 static int
-notmuch_help_command (notmuch_config_t *config, int argc, char *argv[])
+_help_for (const char *topic_name)
 {
     command_t *command;
     help_topic_t *topic;
     unsigned int i;
 
-    argc--; argv++; /* Ignore "help" */
-
-    if (argc == 0) {
+    if (!topic_name) {
        printf ("The notmuch mail system.\n\n");
        usage (stdout);
        return EXIT_SUCCESS;
     }
 
-    if (strcmp (argv[0], "help") == 0) {
+    if (strcmp (topic_name, "help") == 0) {
        printf ("The notmuch help system.\n\n"
                "\tNotmuch uses the man command to display help. In case\n"
                "\tof difficulties check that MANPATH includes the pages\n"
@@ -200,26 +249,46 @@ notmuch_help_command (notmuch_config_t *config, int argc, char *argv[])
        return EXIT_SUCCESS;
     }
 
-    command = find_command (argv[0]);
+    command = find_command (topic_name);
     if (command) {
-       char *page = talloc_asprintf (config, "notmuch-%s", command->name);
+       char *page = talloc_asprintf (NULL, "notmuch-%s", command->name);
        exec_man (page);
     }
 
     for (i = 0; i < ARRAY_SIZE (help_topics); i++) {
        topic = &help_topics[i];
-       if (strcmp (argv[0], topic->name) == 0) {
-           char *page = talloc_asprintf (config, "notmuch-%s", topic->name);
+       if (strcmp (topic_name, topic->name) == 0) {
+           char *page = talloc_asprintf (NULL, "notmuch-%s", topic->name);
            exec_man (page);
        }
     }
 
     fprintf (stderr,
             "\nSorry, %s is not a known command. There's not much I can do to help.\n\n",
-            argv[0]);
+            topic_name);
     return EXIT_FAILURE;
 }
 
+static int
+notmuch_help_command (unused (notmuch_config_t * config), int argc, char *argv[])
+{
+    int opt_index;
+
+    opt_index = notmuch_minimal_options ("help", argc, argv);
+    if (opt_index < 0)
+       return EXIT_FAILURE;
+
+    /* skip at least subcommand argument */
+    argc-= opt_index;
+    argv+= opt_index;
+
+    if (argc == 0) {
+       return _help_for (NULL);
+    }
+
+    return _help_for (argv[0]);
+}
+
 /* Handle the case of "notmuch" being invoked with no command
  * argument. For now we just call notmuch_setup_command, but we plan
  * to be more clever about this in the future.
@@ -285,14 +354,12 @@ main (int argc, char *argv[])
     command_t *command;
     char *config_file_name = NULL;
     notmuch_config_t *config = NULL;
-    notmuch_bool_t print_help=FALSE, print_version=FALSE;
     int opt_index;
     int ret;
 
     notmuch_opt_desc_t options[] = {
-       { NOTMUCH_OPT_BOOLEAN, &print_help, "help", 'h', 0 },
-       { NOTMUCH_OPT_BOOLEAN, &print_version, "version", 'v', 0 },
        { NOTMUCH_OPT_STRING, &config_file_name, "config", 'c', 0 },
+       { NOTMUCH_OPT_INHERIT, (void *) &notmuch_shared_options, NULL, 0, 0 },
        { 0, 0, 0, 0, 0 }
     };
 
@@ -314,24 +381,7 @@ main (int argc, char *argv[])
        goto DONE;
     }
 
-    /* Handle notmuch --help [command] and notmuch command --help. */
-    if (print_help ||
-       (opt_index + 1 < argc && strcmp (argv[opt_index + 1], "--help") == 0)) {
-       /*
-        * Pass the first positional argument as argv[1] so the help
-        * command can give help for it. The help command ignores the
-        * argv[0] passed to it.
-        */
-       ret = notmuch_help_command (NULL, argc - opt_index + 1,
-                                   argv + opt_index - 1);
-       goto DONE;
-    }
-
-    if (print_version) {
-       printf ("notmuch " STRINGIFY(NOTMUCH_VERSION) "\n");
-       ret = EXIT_SUCCESS;
-       goto DONE;
-    }
+    notmuch_process_shared_options (NULL);
 
     if (opt_index < argc)
        command_name = argv[opt_index];
index 75e3d8787ad6db09aeda709707950f5be839468f..88601fc79f884bf418ca53ed320fbde4fdca5831 100644 (file)
@@ -203,7 +203,7 @@ time_done ()
     fi
 }
 
-cd -P "$test" || error "Cannot setup test environment"
+cd -P "$test" || error "Cannot set up test environment"
 test_failure=0
 test_count=0
 
index caf8bdb094805f54ccbbe232a78cc26a4a504c5c..d7266ffca73d945c75fbab0aab198d543cb81768 100755 (executable)
@@ -12,9 +12,9 @@ if [ $NOTMUCH_HAVE_MAN -eq 1 ]; then
     test_expect_success 'notmuch help tag' 'notmuch help tag'
 else
     test_expect_success 'notmuch --help tag (man pages not available)' \
-       'test_must_fail notmuch --help tag'
+       'test_must_fail notmuch --help tag >/dev/null'
     test_expect_success 'notmuch help tag (man pages not available)' \
-       'test_must_fail notmuch help tag'
+       'test_must_fail notmuch help tag >/dev/null'
 fi
 
 test_done
index 74f1955203f0f5cedcf0be633bcef440eeb5aa51..7e71c3b12afc1164faa9c5196f8d2296af56693b 100755 (executable)
@@ -188,7 +188,7 @@ notmuch config set new.tags $OLDCONFIG
 # DUPLICATE_MESSAGE_ID is not tested here, because it should actually pass.
 
 for code in OUT_OF_MEMORY XAPIAN_EXCEPTION FILE_NOT_EMAIL \
-    READ_ONLY_DATABASE UPGRADE_REQUIRED; do
+    READ_ONLY_DATABASE UPGRADE_REQUIRED PATH_ERROR; do
 gen_insert_msg
 cat <<EOF > index-file-$code.gdb
 set breakpoint pending on
index d2b5d1f5a90281bbf69f9d2b968ab3ff2cbd8761..98e4d4dc3e4289a55e1889d970961f09902162e9 100755 (executable)
@@ -11,16 +11,17 @@ test_description='exception symbol hiding'
 
 . ./test-lib.sh
 
-run_test(){
-    result=$(LD_LIBRARY_PATH="$TEST_DIRECTORY/../lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" $TEST_DIRECTORY/symbol-test 2>&1)
-}
-
-output="A Xapian exception occurred opening database: Couldn't stat 'fakedb/.notmuch/xapian'
-caught No chert database found at path \`./nonexistent'"
-
-mkdir -p fakedb/.notmuch
-
-test_expect_success 'running test' run_test
+test_begin_subtest 'running test' run_test
+mkdir -p ${PWD}/fakedb/.notmuch
+( LD_LIBRARY_PATH="$TEST_DIRECTORY/../lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" \
+                $TEST_DIRECTORY/symbol-test ${PWD}/fakedb ${PWD}/nonexistent \
+                2>&1 | sed "s,${PWD},CWD,g") > OUTPUT
+
+cat <<EOF > EXPECTED
+A Xapian exception occurred opening database: Couldn't stat 'CWD/fakedb/.notmuch/xapian'
+caught No chert database found at path \`CWD/nonexistent'
+EOF
+test_expect_equal_file EXPECTED OUTPUT
 
 test_begin_subtest 'checking output'
 test_expect_equal "$result" "$output"
index 3f03a2e3a966018a273bdb75dece7fcc1b224ddd..26d0b97663dd91fba902b35a5854d0bd68490f87 100755 (executable)
@@ -11,7 +11,7 @@ db = notmuch.Database(mode=notmuch.Database.MODE.READ_ONLY)
 q_new = notmuch.Query(db, 'tag:inbox')
 q_new.set_sort(notmuch.Query.SORT.OLDEST_FIRST)
 for t in q_new.search_threads():
-    print t.get_thread_id()
+    print (t.get_thread_id())
 EOF
 notmuch search --sort=oldest-first --output=threads tag:inbox | sed s/^thread:// > EXPECTED
 test_expect_equal_file OUTPUT EXPECTED
@@ -23,7 +23,7 @@ db = notmuch.Database(mode=notmuch.Database.MODE.READ_ONLY)
 q_new = notmuch.Query(db, 'tag:inbox')
 q_new.set_sort(notmuch.Query.SORT.OLDEST_FIRST)
 for m in q_new.search_messages():
-    print m.get_message_id()
+    print (m.get_message_id())
 EOF
 notmuch search --sort=oldest-first --output=messages tag:inbox | sed s/^id:// > EXPECTED
 test_expect_equal_file OUTPUT EXPECTED
@@ -32,7 +32,7 @@ test_begin_subtest "get non-existent file"
 test_python <<EOF
 import notmuch
 db = notmuch.Database(mode=notmuch.Database.MODE.READ_ONLY)
-print db.find_message_by_filename("i-dont-exist")
+print (db.find_message_by_filename("i-dont-exist"))
 EOF
 test_expect_equal "$(cat OUTPUT)" "None"
 
diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh
new file mode 100755 (executable)
index 0000000..8b8e6d2
--- /dev/null
@@ -0,0 +1,86 @@
+#!/usr/bin/env bash
+test_description="ruby bindings"
+. ./test-lib.sh
+
+if [ "${NOTMUCH_HAVE_RUBY_DEV}" = "0" ]; then
+    test_subtest_missing_external_prereq_["ruby development files"]=t
+fi
+
+add_email_corpus
+
+test_begin_subtest "compare thread ids"
+test_ruby <<"EOF"
+require 'notmuch'
+$maildir = ENV['MAIL_DIR']
+if not $maildir then
+  abort('environment variable MAIL_DIR must be set')
+end
+@db = Notmuch::Database.new($maildir)
+@q = @db.query('tag:inbox')
+@q.sort = Notmuch::SORT_OLDEST_FIRST
+for t in @q.search_threads do
+  print t.thread_id, "\n"
+end
+EOF
+notmuch search --sort=oldest-first --output=threads tag:inbox | sed s/^thread:// > EXPECTED
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "compare message ids"
+test_ruby <<"EOF"
+require 'notmuch'
+$maildir = ENV['MAIL_DIR']
+if not $maildir then
+  abort('environment variable MAIL_DIR must be set')
+end
+@db = Notmuch::Database.new($maildir)
+@q = @db.query('tag:inbox')
+@q.sort = Notmuch::SORT_OLDEST_FIRST
+for m in @q.search_messages do
+  print m.message_id, "\n"
+end
+EOF
+notmuch search --sort=oldest-first --output=messages tag:inbox | sed s/^id:// > EXPECTED
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "get non-existent file"
+test_ruby <<"EOF"
+require 'notmuch'
+$maildir = ENV['MAIL_DIR']
+if not $maildir then
+  abort('environment variable MAIL_DIR must be set')
+end
+@db = Notmuch::Database.new($maildir)
+result = @db.find_message_by_filename('i-dont-exist')
+print (result == nil)
+EOF
+test_expect_equal "$(cat OUTPUT)" "true"
+
+test_begin_subtest "count messages"
+test_ruby <<"EOF"
+require 'notmuch'
+$maildir = ENV['MAIL_DIR']
+if not $maildir then
+  abort('environment variable MAIL_DIR must be set')
+end
+@db = Notmuch::Database.new($maildir)
+@q = @db.query('tag:inbox')
+print @q.count_messages(),"\n"
+EOF
+notmuch count --output=messages tag:inbox > EXPECTED
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "count threads"
+test_ruby <<"EOF"
+require 'notmuch'
+$maildir = ENV['MAIL_DIR']
+if not $maildir then
+  abort('environment variable MAIL_DIR must be set')
+end
+@db = Notmuch::Database.new($maildir)
+@q = @db.query('tag:inbox')
+print @q.count_threads(),"\n"
+EOF
+notmuch count --output=threads tag:inbox > EXPECTED
+test_expect_equal_file OUTPUT EXPECTED
+
+test_done
index c99b17ed2fee141a43fb9faca006d3318f20d98e..b1e77aa0ee3878506d5136050376ed2d2c6f4a75 100755 (executable)
@@ -35,7 +35,7 @@ Error: Cannot open a database for a NULL path.
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
-test_begin_subtest "Open nonexistent database"
+test_begin_subtest "Open relative path"
 test_C <<'EOF'
 #include <stdio.h>
 #include <notmuch.h>
@@ -49,7 +49,43 @@ EOF
 cat <<'EOF' >EXPECTED
 == stdout ==
 == stderr ==
-Error opening database at ./nonexistent/foo/.notmuch: No such file or directory
+Error: Database path must be absolute.
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "Create database in relative path"
+test_C <<'EOF'
+#include <stdio.h>
+#include <notmuch.h>
+int main (int argc, char** argv)
+{
+    notmuch_database_t *db;
+    notmuch_status_t stat;
+    stat = notmuch_database_create ("./nonexistent/foo", &db);
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+== stderr ==
+Error: Database path must be absolute.
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "Open nonexistent database"
+test_C ${PWD}/nonexistent/foo <<'EOF'
+#include <stdio.h>
+#include <notmuch.h>
+int main (int argc, char** argv)
+{
+    notmuch_database_t *db;
+    notmuch_status_t stat;
+    stat = notmuch_database_open (argv[1], 0, 0);
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+== stderr ==
+Error opening database at CWD/nonexistent/foo/.notmuch: No such file or directory
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
@@ -70,21 +106,21 @@ Error: Cannot create a database for a NULL path.
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
-test_begin_subtest "Create database in non-existant directory"
-test_C <<'EOF'
+test_begin_subtest "Create database in nonexistent directory"
+test_C ${PWD}/nonexistent/foo<<'EOF'
 #include <stdio.h>
 #include <notmuch.h>
 int main (int argc, char** argv)
 {
     notmuch_database_t *db;
     notmuch_status_t stat;
-    stat = notmuch_database_create ("./nonexistent/foo", &db);
+    stat = notmuch_database_create (argv[1], &db);
 }
 EOF
 cat <<'EOF' >EXPECTED
 == stdout ==
 == stderr ==
-Error: Cannot create database at ./nonexistent/foo: No such file or directory.
+Error: Cannot create database at CWD/nonexistent/foo: No such file or directory.
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
index 790193d2ee3eed2f5b7edbb4b4e7f3637f6f23d4..b377eb40bfdce0964880e736f493f33f3e2066d0 100644 (file)
@@ -114,6 +114,23 @@ random_utf8_string (void *ctx, size_t char_count)
     return buf;
 }
 
+/* stubs since we cannot link with notmuch.o */
+const notmuch_opt_desc_t notmuch_shared_options[] = {
+       { 0, 0, 0, 0, 0 }
+};
+
+void
+notmuch_process_shared_options (unused (const char *dummy))
+{
+}
+
+int
+notmuch_minimal_options (unused (const char *subcommand),
+                        unused (int argc),
+                        unused (char **argv))
+{
+    return 0;
+}
 
 int
 main (int argc, char **argv)
index f17ddc854c720eb79749f8c4d5428fc5a13ce19b..fb77b418a1a859dbaea0467b1c4a5c395c7fc52f 100644 (file)
@@ -4,18 +4,18 @@
 #include <notmuch.h>
 
 
-int main() {
+int main(int argc, char** argv) {
   notmuch_database_t *notmuch;
   char *message = NULL;
 
-  if (notmuch_database_open_verbose  ("fakedb", NOTMUCH_DATABASE_MODE_READ_ONLY, &notmuch, &message))
+  if (notmuch_database_open_verbose  (argv[1], NOTMUCH_DATABASE_MODE_READ_ONLY, &notmuch, &message))
       if (message) {
          fputs (message, stderr);
          free (message);
       }
 
   try {
-    (void) new Xapian::WritableDatabase("./nonexistent", Xapian::DB_OPEN);
+    (void) new Xapian::WritableDatabase(argv[2], Xapian::DB_OPEN);
   } catch (const Xapian::Error &error) {
     printf("caught %s\n", error.get_msg().c_str());
     return 0;
index 486d1c430adbd714f1d08297612c390b4853e3f3..3466e9cf842ac1f439f1a2607daf70a9931f846f 100644 (file)
@@ -1163,6 +1163,11 @@ test_python() {
                | $cmd -
 }
 
+test_ruby() {
+    export LD_LIBRARY_PATH=$TEST_DIRECTORY/../lib
+    MAIL_DIR=$MAIL_DIR ruby -I $TEST_DIRECTORY/../bindings/ruby> OUTPUT
+}
+
 test_C () {
     exec_file="test${test_count}"
     test_file="${exec_file}.c"
@@ -1231,7 +1236,7 @@ emacs_generate_script
 
 # Use -P to resolve symlinks in our working directory so that the cwd
 # in subprocesses like git equals our $PWD (for pathname comparisons).
-cd -P "$test" || error "Cannot setup test environment"
+cd -P "$test" || error "Cannot set up test environment"
 
 if test "$verbose" = "t"
 then