[PATCH 37/39] CLI: use configured hook directory

Subject: [PATCH 37/39] CLI: use configured hook directory

Date: Fri, 5 Feb 2021 09:26:52 -0400

To: notmuch@notmuchmail.org

Cc: David Bremner

From: David Bremner


This enables support for hooks outside the database directory.
It relies strongly on configuration information being usable between
closing the database and destroying it.
---
 hooks.c            |   7 +-
 notmuch-client.h   |   2 +-
 notmuch-insert.c   |   7 +-
 notmuch-new.c      |  10 +--
 test/T400-hooks.sh | 197 +++++++++++++++++++++++++--------------------
 5 files changed, 120 insertions(+), 103 deletions(-)

diff --git a/hooks.c b/hooks.c
index 59c58070..ec89b22e 100644
--- a/hooks.c
+++ b/hooks.c
@@ -24,14 +24,15 @@
 #include <sys/wait.h>
 
 int
-notmuch_run_hook (const char *db_path, const char *hook)
+notmuch_run_hook (notmuch_database_t *notmuch, const char *hook)
 {
     char *hook_path;
     int status = 0;
     pid_t pid;
 
-    hook_path = talloc_asprintf (NULL, "%s/%s/%s/%s", db_path, ".notmuch",
-				 "hooks", hook);
+    hook_path = talloc_asprintf (notmuch, "%s/%s",
+				 notmuch_config_get (notmuch, NOTMUCH_CONFIG_HOOK_DIR),
+				 hook);
     if (hook_path == NULL) {
 	fprintf (stderr, "Out of memory\n");
 	return 1;
diff --git a/notmuch-client.h b/notmuch-client.h
index 9e09c36a..f60f5406 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -339,7 +339,7 @@ const char *
 _notmuch_config_get_path (notmuch_config_t *config);
 
 int
-notmuch_run_hook (const char *db_path, const char *hook);
+notmuch_run_hook (notmuch_database_t *notmuch, const char *hook);
 
 bool
 debugger_is_active (void);
diff --git a/notmuch-insert.c b/notmuch-insert.c
index e483b949..0f272e2e 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -481,7 +481,6 @@ notmuch_insert_command (unused(notmuch_config_t *config),notmuch_database_t *not
     notmuch_process_shared_options (argv[0]);
 
 
-    /* XXX TODO replace this use of DATABASE_PATH with something specific to hooks */
     db_path = notmuch_config_get (notmuch, NOTMUCH_CONFIG_DATABASE_PATH);
 
     if (! db_path)
@@ -570,7 +569,7 @@ notmuch_insert_command (unused(notmuch_config_t *config),notmuch_database_t *not
     status = add_file (notmuch, newpath, tag_ops, synchronize_flags, keep, indexing_cli_choices.opts);
 
     /* Commit changes. */
-    close_status = notmuch_database_destroy (notmuch);
+    close_status = notmuch_database_close (notmuch);
     if (close_status) {
 	/* Hold on to the first error, if any. */
 	if (! status)
@@ -595,9 +594,11 @@ notmuch_insert_command (unused(notmuch_config_t *config),notmuch_database_t *not
 
     if (hooks && status == NOTMUCH_STATUS_SUCCESS) {
 	/* Ignore hook failures. */
-	notmuch_run_hook (db_path, "post-insert");
+	notmuch_run_hook (notmuch, "post-insert");
     }
 
+    notmuch_database_destroy (notmuch);
+
     talloc_free (local);
 
     return status_to_exit (status);
diff --git a/notmuch-new.c b/notmuch-new.c
index 0f416939..21e66af1 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -1105,7 +1105,6 @@ notmuch_new_command (unused(notmuch_config_t *config), notmuch_database_t *notmu
     struct timeval tv_start;
     int ret = 0;
     const char *db_path;
-    char *dot_notmuch_path;
     struct sigaction action;
     _filename_node_t *f;
     int opt_index;
@@ -1167,13 +1166,11 @@ notmuch_new_command (unused(notmuch_config_t *config), notmuch_database_t *notmu
     }
 
     if (hooks) {
-	ret = notmuch_run_hook (db_path, "pre-new");
+	ret = notmuch_run_hook (notmuch, "pre-new");
 	if (ret)
 	    return EXIT_FAILURE;
     }
 
-    dot_notmuch_path = talloc_asprintf (notmuch, "%s/%s", db_path, ".notmuch");
-
     notmuch_exit_if_unmatched_db_uuid (notmuch);
 
     if (notmuch_database_get_revision (notmuch, NULL) == 0) {
@@ -1212,9 +1209,6 @@ notmuch_new_command (unused(notmuch_config_t *config), notmuch_database_t *notmu
     action.sa_flags = SA_RESTART;
     sigaction (SIGINT, &action, NULL);
 
-    talloc_free (dot_notmuch_path);
-    dot_notmuch_path = NULL;
-
     gettimeofday (&add_files_state.tv_start, NULL);
 
     add_files_state.removed_files = _filename_list_create (notmuch);
@@ -1284,7 +1278,7 @@ notmuch_new_command (unused(notmuch_config_t *config), notmuch_database_t *notmu
     notmuch_database_close (notmuch);
 
     if (hooks && ! ret && ! interrupted)
-	ret = notmuch_run_hook (db_path, "post-new");
+	ret = notmuch_run_hook (notmuch, "post-new");
 
     notmuch_database_destroy (notmuch);
 
diff --git a/test/T400-hooks.sh b/test/T400-hooks.sh
index 49c690eb..a3dd4c63 100755
--- a/test/T400-hooks.sh
+++ b/test/T400-hooks.sh
@@ -2,8 +2,6 @@
 test_description='hooks'
 . $(dirname "$0")/test-lib.sh || exit 1
 
-HOOK_DIR=${MAIL_DIR}/.notmuch/hooks
-
 create_echo_hook () {
     local TOKEN="${RANDOM}"
     mkdir -p ${HOOK_DIR}
@@ -16,6 +14,7 @@ EOF
 }
 
 create_failing_hook () {
+    local HOOK_DIR=${2}
     mkdir -p ${HOOK_DIR}
     cat <<EOF >"${HOOK_DIR}/${1}"
 #!/bin/sh
@@ -24,98 +23,120 @@ EOF
     chmod +x "${HOOK_DIR}/${1}"
 }
 
-rm_hooks () {
-    rm -rf ${HOOK_DIR}
-}
-
 # add a message to generate mail dir and database
 add_message
 # create maildir structure for notmuch-insert
 mkdir -p "$MAIL_DIR"/{cur,new,tmp}
 
-test_begin_subtest "pre-new is run"
-rm_hooks
-generate_message
-create_echo_hook "pre-new" expected output
-notmuch new > /dev/null
-test_expect_equal_file expected output
-
-test_begin_subtest "post-new is run"
-rm_hooks
-generate_message
-create_echo_hook "post-new" expected output
-notmuch new > /dev/null
-test_expect_equal_file expected output
-
-test_begin_subtest "post-insert hook is run"
-rm_hooks
-generate_message
-create_echo_hook "post-insert" expected output
-notmuch insert < "$gen_msg_filename"
-test_expect_equal_file expected output
-
-test_begin_subtest "pre-new is run before post-new"
-rm_hooks
-generate_message
-create_echo_hook "pre-new" pre-new.expected pre-new.output
-create_echo_hook "post-new" post-new.expected post-new.output
-notmuch new > /dev/null
-test_expect_equal_file post-new.expected post-new.output
-
-test_begin_subtest "pre-new non-zero exit status (hook status)"
-rm_hooks
-generate_message
-create_failing_hook "pre-new"
-output=`notmuch new 2>&1`
-test_expect_equal "$output" "Error: pre-new hook failed with status 13"
-
-# depends on the previous subtest leaving broken hook behind
-test_begin_subtest "pre-new non-zero exit status (notmuch status)"
-test_expect_code 1 "notmuch new"
-
-# depends on the previous subtests leaving 1 new message behind
-test_begin_subtest "pre-new non-zero exit status aborts new"
-rm_hooks
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-test_begin_subtest "post-new non-zero exit status (hook status)"
-rm_hooks
-generate_message
-create_failing_hook "post-new"
-NOTMUCH_NEW 2>output.stderr >output
-cat output.stderr >> output
-echo "Added 1 new message to the database." > expected
-echo "Error: post-new hook failed with status 13" >> expected
-test_expect_equal_file expected output
-
-# depends on the previous subtest leaving broken hook behind
-test_begin_subtest "post-new non-zero exit status (notmuch status)"
-test_expect_code 1 "notmuch new"
-
-test_begin_subtest "post-insert hook does not affect insert status"
-rm_hooks
-generate_message
-create_failing_hook "post-insert"
-test_expect_success "notmuch insert < \"$gen_msg_filename\" > /dev/null"
-
-test_begin_subtest "hook without executable permissions"
-rm_hooks
-mkdir -p ${HOOK_DIR}
-cat <<EOF >"${HOOK_DIR}/pre-new"
-#!/bin/sh
-echo foo
+for config in traditional profile explicit XDG; do
+    unset NOTMUCH_PROFILE
+    notmuch config set database.hook_dir
+    case $config in
+	traditional)
+	    HOOK_DIR=${MAIL_DIR}/.notmuch/hooks
+	    ;;
+	profile)
+	    dir=${HOME}/.config/notmuch/other
+	    mkdir -p ${dir}
+	    HOOK_DIR=${dir}/hooks
+	    cp ${NOTMUCH_CONFIG} ${dir}/config
+	    export NOTMUCH_PROFILE=other
+	    ;;
+	explicit)
+	    HOOK_DIR=${HOME}/.notmuch-hooks
+	    mkdir -p $HOOK_DIR
+	    notmuch config set database.hook_dir $HOOK_DIR
+	    ;;
+	XDG)
+	    HOOK_DIR=${HOME}/.config/notmuch/default/hooks
+	    ;;
+    esac
+
+    test_begin_subtest "pre-new is run [${config}]"
+    rm -rf ${HOOK_DIR}
+    generate_message
+    create_echo_hook "pre-new" expected output $HOOK_DIR
+    notmuch new > /dev/null
+    test_expect_equal_file expected output
+
+    test_begin_subtest "post-new is run [${config}]"
+    rm -rf ${HOOK_DIR}
+    generate_message
+    create_echo_hook "post-new" expected output $HOOK_DIR
+    notmuch new > /dev/null
+    test_expect_equal_file expected output
+
+    test_begin_subtest "post-insert hook is run [${config}]"
+    rm -rf ${HOOK_DIR}
+    generate_message
+    create_echo_hook "post-insert" expected output $HOOK_DIR
+    notmuch insert < "$gen_msg_filename"
+    test_expect_equal_file expected output
+
+    test_begin_subtest "pre-new is run before post-new [${config}]"
+    rm -rf ${HOOK_DIR}
+    generate_message
+    create_echo_hook "pre-new" pre-new.expected pre-new.output $HOOK_DIR
+    create_echo_hook "post-new" post-new.expected post-new.output $HOOK_DIR
+    notmuch new > /dev/null
+    test_expect_equal_file post-new.expected post-new.output
+
+    test_begin_subtest "pre-new non-zero exit status (hook status) [${config}]"
+    rm -rf ${HOOK_DIR}
+    generate_message
+    create_failing_hook "pre-new" $HOOK_DIR
+    output=`notmuch new 2>&1`
+    test_expect_equal "$output" "Error: pre-new hook failed with status 13"
+
+    # depends on the previous subtest leaving broken hook behind
+    test_begin_subtest "pre-new non-zero exit status (notmuch status) [${config}]"
+    test_expect_code 1 "notmuch new"
+
+    # depends on the previous subtests leaving 1 new message behind
+    test_begin_subtest "pre-new non-zero exit status aborts new [${config}]"
+    rm -rf ${HOOK_DIR}
+    output=$(NOTMUCH_NEW)
+    test_expect_equal "$output" "Added 1 new message to the database."
+
+    test_begin_subtest "post-new non-zero exit status (hook status) [${config}]"
+    rm -rf ${HOOK_DIR}
+    generate_message
+    create_failing_hook "post-new" $HOOK_DIR
+    NOTMUCH_NEW 2>output.stderr >output
+    cat output.stderr >> output
+    echo "Added 1 new message to the database." > expected
+    echo "Error: post-new hook failed with status 13" >> expected
+    test_expect_equal_file expected output
+
+    # depends on the previous subtest leaving broken hook behind
+    test_begin_subtest "post-new non-zero exit status (notmuch status) [${config}]"
+    test_expect_code 1 "notmuch new"
+
+    test_begin_subtest "post-insert hook does not affect insert status [${config}]"
+    rm -rf ${HOOK_DIR}
+    generate_message
+    create_failing_hook "post-insert" $HOOK_DIR
+    test_expect_success "notmuch insert < \"$gen_msg_filename\" > /dev/null"
+
+    test_begin_subtest "hook without executable permissions [${config}]"
+    rm -rf ${HOOK_DIR}
+    mkdir -p ${HOOK_DIR}
+    cat <<EOF >"${HOOK_DIR}/pre-new"
+    #!/bin/sh
+    echo foo
 EOF
-output=`notmuch new 2>&1`
-test_expect_code 1 "notmuch new"
-
-test_begin_subtest "hook execution failure"
-rm_hooks
-mkdir -p ${HOOK_DIR}
-cat <<EOF >"${HOOK_DIR}/pre-new"
-no hashbang, execl fails
+    output=`notmuch new 2>&1`
+    test_expect_code 1 "notmuch new"
+
+    test_begin_subtest "hook execution failure [${config}]"
+    rm -rf ${HOOK_DIR}
+    mkdir -p ${HOOK_DIR}
+    cat <<EOF >"${HOOK_DIR}/pre-new"
+    no hashbang, execl fails
 EOF
-chmod +x "${HOOK_DIR}/pre-new"
-test_expect_code 1 "notmuch new"
+    chmod +x "${HOOK_DIR}/pre-new"
+    test_expect_code 1 "notmuch new"
 
+    rm -rf ${HOOK_DIR}
+done
 test_done
-- 
2.30.0
_______________________________________________
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-leave@notmuchmail.org

Thread: