mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-25 12:28:09 +01:00
CLI: use configured hook directory
This enables support for hooks outside the database directory. It relies strongly on configuration information being usable between closing the database and destroying it.
This commit is contained in:
parent
0345bc57a0
commit
f61d88c6f4
5 changed files with 109 additions and 92 deletions
7
hooks.c
7
hooks.c
|
@ -24,14 +24,15 @@
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
notmuch_run_hook (const char *db_path, const char *hook)
|
notmuch_run_hook (notmuch_database_t *notmuch, const char *hook)
|
||||||
{
|
{
|
||||||
char *hook_path;
|
char *hook_path;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
hook_path = talloc_asprintf (NULL, "%s/%s/%s/%s", db_path, ".notmuch",
|
hook_path = talloc_asprintf (notmuch, "%s/%s",
|
||||||
"hooks", hook);
|
notmuch_config_get (notmuch, NOTMUCH_CONFIG_HOOK_DIR),
|
||||||
|
hook);
|
||||||
if (hook_path == NULL) {
|
if (hook_path == NULL) {
|
||||||
fprintf (stderr, "Out of memory\n");
|
fprintf (stderr, "Out of memory\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -339,7 +339,7 @@ const char *
|
||||||
_notmuch_config_get_path (notmuch_config_t *config);
|
_notmuch_config_get_path (notmuch_config_t *config);
|
||||||
|
|
||||||
int
|
int
|
||||||
notmuch_run_hook (const char *db_path, const char *hook);
|
notmuch_run_hook (notmuch_database_t *notmuch, const char *hook);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
debugger_is_active (void);
|
debugger_is_active (void);
|
||||||
|
|
|
@ -481,7 +481,6 @@ notmuch_insert_command (unused(notmuch_config_t *config),notmuch_database_t *not
|
||||||
notmuch_process_shared_options (argv[0]);
|
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);
|
db_path = notmuch_config_get (notmuch, NOTMUCH_CONFIG_DATABASE_PATH);
|
||||||
|
|
||||||
if (! db_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);
|
status = add_file (notmuch, newpath, tag_ops, synchronize_flags, keep, indexing_cli_choices.opts);
|
||||||
|
|
||||||
/* Commit changes. */
|
/* Commit changes. */
|
||||||
close_status = notmuch_database_destroy (notmuch);
|
close_status = notmuch_database_close (notmuch);
|
||||||
if (close_status) {
|
if (close_status) {
|
||||||
/* Hold on to the first error, if any. */
|
/* Hold on to the first error, if any. */
|
||||||
if (! status)
|
if (! status)
|
||||||
|
@ -595,9 +594,11 @@ notmuch_insert_command (unused(notmuch_config_t *config),notmuch_database_t *not
|
||||||
|
|
||||||
if (hooks && status == NOTMUCH_STATUS_SUCCESS) {
|
if (hooks && status == NOTMUCH_STATUS_SUCCESS) {
|
||||||
/* Ignore hook failures. */
|
/* Ignore hook failures. */
|
||||||
notmuch_run_hook (db_path, "post-insert");
|
notmuch_run_hook (notmuch, "post-insert");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notmuch_database_destroy (notmuch);
|
||||||
|
|
||||||
talloc_free (local);
|
talloc_free (local);
|
||||||
|
|
||||||
return status_to_exit (status);
|
return status_to_exit (status);
|
||||||
|
|
|
@ -1105,7 +1105,6 @@ notmuch_new_command (unused(notmuch_config_t *config), notmuch_database_t *notmu
|
||||||
struct timeval tv_start;
|
struct timeval tv_start;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
const char *db_path;
|
const char *db_path;
|
||||||
char *dot_notmuch_path;
|
|
||||||
struct sigaction action;
|
struct sigaction action;
|
||||||
_filename_node_t *f;
|
_filename_node_t *f;
|
||||||
int opt_index;
|
int opt_index;
|
||||||
|
@ -1167,13 +1166,11 @@ notmuch_new_command (unused(notmuch_config_t *config), notmuch_database_t *notmu
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hooks) {
|
if (hooks) {
|
||||||
ret = notmuch_run_hook (db_path, "pre-new");
|
ret = notmuch_run_hook (notmuch, "pre-new");
|
||||||
if (ret)
|
if (ret)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
dot_notmuch_path = talloc_asprintf (notmuch, "%s/%s", db_path, ".notmuch");
|
|
||||||
|
|
||||||
notmuch_exit_if_unmatched_db_uuid (notmuch);
|
notmuch_exit_if_unmatched_db_uuid (notmuch);
|
||||||
|
|
||||||
if (notmuch_database_get_revision (notmuch, NULL) == 0) {
|
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;
|
action.sa_flags = SA_RESTART;
|
||||||
sigaction (SIGINT, &action, NULL);
|
sigaction (SIGINT, &action, NULL);
|
||||||
|
|
||||||
talloc_free (dot_notmuch_path);
|
|
||||||
dot_notmuch_path = NULL;
|
|
||||||
|
|
||||||
gettimeofday (&add_files_state.tv_start, NULL);
|
gettimeofday (&add_files_state.tv_start, NULL);
|
||||||
|
|
||||||
add_files_state.removed_files = _filename_list_create (notmuch);
|
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);
|
notmuch_database_close (notmuch);
|
||||||
|
|
||||||
if (hooks && ! ret && ! interrupted)
|
if (hooks && ! ret && ! interrupted)
|
||||||
ret = notmuch_run_hook (db_path, "post-new");
|
ret = notmuch_run_hook (notmuch, "post-new");
|
||||||
|
|
||||||
notmuch_database_destroy (notmuch);
|
notmuch_database_destroy (notmuch);
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
test_description='hooks'
|
test_description='hooks'
|
||||||
. $(dirname "$0")/test-lib.sh || exit 1
|
. $(dirname "$0")/test-lib.sh || exit 1
|
||||||
|
|
||||||
HOOK_DIR=${MAIL_DIR}/.notmuch/hooks
|
|
||||||
|
|
||||||
create_echo_hook () {
|
create_echo_hook () {
|
||||||
local TOKEN="${RANDOM}"
|
local TOKEN="${RANDOM}"
|
||||||
mkdir -p ${HOOK_DIR}
|
mkdir -p ${HOOK_DIR}
|
||||||
|
@ -16,6 +14,7 @@ EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
create_failing_hook () {
|
create_failing_hook () {
|
||||||
|
local HOOK_DIR=${2}
|
||||||
mkdir -p ${HOOK_DIR}
|
mkdir -p ${HOOK_DIR}
|
||||||
cat <<EOF >"${HOOK_DIR}/${1}"
|
cat <<EOF >"${HOOK_DIR}/${1}"
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
@ -24,98 +23,120 @@ EOF
|
||||||
chmod +x "${HOOK_DIR}/${1}"
|
chmod +x "${HOOK_DIR}/${1}"
|
||||||
}
|
}
|
||||||
|
|
||||||
rm_hooks () {
|
|
||||||
rm -rf ${HOOK_DIR}
|
|
||||||
}
|
|
||||||
|
|
||||||
# add a message to generate mail dir and database
|
# add a message to generate mail dir and database
|
||||||
add_message
|
add_message
|
||||||
# create maildir structure for notmuch-insert
|
# create maildir structure for notmuch-insert
|
||||||
mkdir -p "$MAIL_DIR"/{cur,new,tmp}
|
mkdir -p "$MAIL_DIR"/{cur,new,tmp}
|
||||||
|
|
||||||
test_begin_subtest "pre-new is run"
|
for config in traditional profile explicit XDG; do
|
||||||
rm_hooks
|
unset NOTMUCH_PROFILE
|
||||||
generate_message
|
notmuch config set database.hook_dir
|
||||||
create_echo_hook "pre-new" expected output
|
case $config in
|
||||||
notmuch new > /dev/null
|
traditional)
|
||||||
test_expect_equal_file expected output
|
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 "post-new is run"
|
test_begin_subtest "pre-new is run [${config}]"
|
||||||
rm_hooks
|
rm -rf ${HOOK_DIR}
|
||||||
generate_message
|
generate_message
|
||||||
create_echo_hook "post-new" expected output
|
create_echo_hook "pre-new" expected output $HOOK_DIR
|
||||||
notmuch new > /dev/null
|
notmuch new > /dev/null
|
||||||
test_expect_equal_file expected output
|
test_expect_equal_file expected output
|
||||||
|
|
||||||
test_begin_subtest "post-insert hook is run"
|
test_begin_subtest "post-new is run [${config}]"
|
||||||
rm_hooks
|
rm -rf ${HOOK_DIR}
|
||||||
generate_message
|
generate_message
|
||||||
create_echo_hook "post-insert" expected output
|
create_echo_hook "post-new" expected output $HOOK_DIR
|
||||||
notmuch insert < "$gen_msg_filename"
|
notmuch new > /dev/null
|
||||||
test_expect_equal_file expected output
|
test_expect_equal_file expected output
|
||||||
|
|
||||||
test_begin_subtest "pre-new is run before post-new"
|
test_begin_subtest "post-insert hook is run [${config}]"
|
||||||
rm_hooks
|
rm -rf ${HOOK_DIR}
|
||||||
generate_message
|
generate_message
|
||||||
create_echo_hook "pre-new" pre-new.expected pre-new.output
|
create_echo_hook "post-insert" expected output $HOOK_DIR
|
||||||
create_echo_hook "post-new" post-new.expected post-new.output
|
notmuch insert < "$gen_msg_filename"
|
||||||
notmuch new > /dev/null
|
test_expect_equal_file expected output
|
||||||
test_expect_equal_file post-new.expected post-new.output
|
|
||||||
|
|
||||||
test_begin_subtest "pre-new non-zero exit status (hook status)"
|
test_begin_subtest "pre-new is run before post-new [${config}]"
|
||||||
rm_hooks
|
rm -rf ${HOOK_DIR}
|
||||||
generate_message
|
generate_message
|
||||||
create_failing_hook "pre-new"
|
create_echo_hook "pre-new" pre-new.expected pre-new.output $HOOK_DIR
|
||||||
output=`notmuch new 2>&1`
|
create_echo_hook "post-new" post-new.expected post-new.output $HOOK_DIR
|
||||||
test_expect_equal "$output" "Error: pre-new hook failed with status 13"
|
notmuch new > /dev/null
|
||||||
|
test_expect_equal_file post-new.expected post-new.output
|
||||||
|
|
||||||
# depends on the previous subtest leaving broken hook behind
|
test_begin_subtest "pre-new non-zero exit status (hook status) [${config}]"
|
||||||
test_begin_subtest "pre-new non-zero exit status (notmuch status)"
|
rm -rf ${HOOK_DIR}
|
||||||
test_expect_code 1 "notmuch new"
|
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 subtests leaving 1 new message behind
|
# depends on the previous subtest leaving broken hook behind
|
||||||
test_begin_subtest "pre-new non-zero exit status aborts new"
|
test_begin_subtest "pre-new non-zero exit status (notmuch status) [${config}]"
|
||||||
rm_hooks
|
test_expect_code 1 "notmuch new"
|
||||||
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)"
|
# depends on the previous subtests leaving 1 new message behind
|
||||||
rm_hooks
|
test_begin_subtest "pre-new non-zero exit status aborts new [${config}]"
|
||||||
generate_message
|
rm -rf ${HOOK_DIR}
|
||||||
create_failing_hook "post-new"
|
output=$(NOTMUCH_NEW)
|
||||||
NOTMUCH_NEW 2>output.stderr >output
|
test_expect_equal "$output" "Added 1 new message to the database."
|
||||||
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 (hook status) [${config}]"
|
||||||
test_begin_subtest "post-new non-zero exit status (notmuch status)"
|
rm -rf ${HOOK_DIR}
|
||||||
test_expect_code 1 "notmuch new"
|
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
|
||||||
|
|
||||||
test_begin_subtest "post-insert hook does not affect insert status"
|
# depends on the previous subtest leaving broken hook behind
|
||||||
rm_hooks
|
test_begin_subtest "post-new non-zero exit status (notmuch status) [${config}]"
|
||||||
generate_message
|
test_expect_code 1 "notmuch new"
|
||||||
create_failing_hook "post-insert"
|
|
||||||
test_expect_success "notmuch insert < \"$gen_msg_filename\" > /dev/null"
|
|
||||||
|
|
||||||
test_begin_subtest "hook without executable permissions"
|
test_begin_subtest "post-insert hook does not affect insert status [${config}]"
|
||||||
rm_hooks
|
rm -rf ${HOOK_DIR}
|
||||||
mkdir -p ${HOOK_DIR}
|
generate_message
|
||||||
cat <<EOF >"${HOOK_DIR}/pre-new"
|
create_failing_hook "post-insert" $HOOK_DIR
|
||||||
#!/bin/sh
|
test_expect_success "notmuch insert < \"$gen_msg_filename\" > /dev/null"
|
||||||
echo foo
|
|
||||||
|
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
|
EOF
|
||||||
output=`notmuch new 2>&1`
|
output=`notmuch new 2>&1`
|
||||||
test_expect_code 1 "notmuch new"
|
test_expect_code 1 "notmuch new"
|
||||||
|
|
||||||
test_begin_subtest "hook execution failure"
|
test_begin_subtest "hook execution failure [${config}]"
|
||||||
rm_hooks
|
rm -rf ${HOOK_DIR}
|
||||||
mkdir -p ${HOOK_DIR}
|
mkdir -p ${HOOK_DIR}
|
||||||
cat <<EOF >"${HOOK_DIR}/pre-new"
|
cat <<EOF >"${HOOK_DIR}/pre-new"
|
||||||
no hashbang, execl fails
|
no hashbang, execl fails
|
||||||
EOF
|
EOF
|
||||||
chmod +x "${HOOK_DIR}/pre-new"
|
chmod +x "${HOOK_DIR}/pre-new"
|
||||||
test_expect_code 1 "notmuch new"
|
test_expect_code 1 "notmuch new"
|
||||||
|
|
||||||
|
rm -rf ${HOOK_DIR}
|
||||||
|
done
|
||||||
test_done
|
test_done
|
||||||
|
|
Loading…
Reference in a new issue