mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-28 13:44:12 +01:00
a352d9ceaa
The code to skip multiple slashes in _notmuch_database_split_path()
skips back one character too much. This is compensated by a +1 in the
length parameter to the strndup() call. Mostly this works fine, but if
the path is to a file under a top level directory with one character
long name, the directory part is mistaken to be part of the file name
(slash == path in code). The returned directory name will be the empty
string and the basename will be the full path, breaking the indexing
logic in notmuch new.
Fix the multiple slash skipping to keep the slash variable pointing at
the last slash, and adjust strndup() accordingly.
The bug was introduced in
commit e890b0cf40
Author: Carl Worth <cworth@cworth.org>
Date: Sat Dec 19 13:20:26 2009 -0800
database: Store the parent ID for each directory document.
just a little over two months after the initial commit in the Notmuch
code history, making this the longest living bug in Notmuch to date.
301 lines
9.9 KiB
Bash
Executable file
301 lines
9.9 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
test_description='"notmuch new" in several variations'
|
|
. ./test-lib.sh || exit 1
|
|
|
|
test_begin_subtest "No new messages"
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "No new mail."
|
|
|
|
|
|
test_begin_subtest "Single new message"
|
|
generate_message
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "Added 1 new message to the database."
|
|
|
|
|
|
test_begin_subtest "Multiple new messages"
|
|
generate_message
|
|
generate_message
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "Added 2 new messages to the database."
|
|
|
|
|
|
test_begin_subtest "No new messages (non-empty DB)"
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "No new mail."
|
|
|
|
|
|
test_begin_subtest "New directories"
|
|
rm -rf "${MAIL_DIR}"/* "${MAIL_DIR}"/.notmuch
|
|
mkdir "${MAIL_DIR}"/def
|
|
mkdir "${MAIL_DIR}"/ghi
|
|
generate_message [dir]=def
|
|
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "Added 1 new message to the database."
|
|
|
|
|
|
test_begin_subtest "Alternate inode order"
|
|
|
|
rm -rf "${MAIL_DIR}"/.notmuch
|
|
mv "${MAIL_DIR}"/ghi "${MAIL_DIR}"/abc
|
|
rm "${MAIL_DIR}"/def/*
|
|
generate_message [dir]=abc
|
|
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "Added 1 new message to the database."
|
|
|
|
|
|
test_begin_subtest "Message moved in"
|
|
rm -rf "${MAIL_DIR}"/* "${MAIL_DIR}"/.notmuch
|
|
generate_message
|
|
tmp_msg_filename=tmp/"$gen_msg_filename"
|
|
mkdir -p "$(dirname "$tmp_msg_filename")"
|
|
mv "$gen_msg_filename" "$tmp_msg_filename"
|
|
notmuch new > /dev/null
|
|
mv "$tmp_msg_filename" "$gen_msg_filename"
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "Added 1 new message to the database."
|
|
|
|
|
|
test_begin_subtest "Renamed message"
|
|
|
|
generate_message
|
|
notmuch new > /dev/null
|
|
mv "$gen_msg_filename" "${gen_msg_filename}"-renamed
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "(D) add_files, pass 2: queuing passed file ${gen_msg_filename} for deletion from database
|
|
No new mail. Detected 1 file rename."
|
|
|
|
|
|
test_begin_subtest "Deleted message"
|
|
|
|
rm "${gen_msg_filename}"-renamed
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "(D) add_files, pass 3: queuing leftover file ${gen_msg_filename}-renamed for deletion from database
|
|
No new mail. Removed 1 message."
|
|
|
|
|
|
|
|
test_begin_subtest "Renamed directory"
|
|
|
|
generate_message [dir]=dir
|
|
generate_message [dir]=dir
|
|
generate_message [dir]=dir
|
|
|
|
notmuch new > /dev/null
|
|
|
|
mv "${MAIL_DIR}"/dir "${MAIL_DIR}"/dir-renamed
|
|
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "(D) add_files, pass 2: queuing passed directory ${MAIL_DIR}/dir for deletion from database
|
|
No new mail. Detected 3 file renames."
|
|
|
|
|
|
test_begin_subtest "Deleted directory"
|
|
rm -rf "${MAIL_DIR}"/dir-renamed
|
|
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "(D) add_files, pass 2: queuing passed directory ${MAIL_DIR}/dir-renamed for deletion from database
|
|
No new mail. Removed 3 messages."
|
|
|
|
|
|
test_begin_subtest "New directory (at end of list)"
|
|
|
|
generate_message [dir]=zzz
|
|
generate_message [dir]=zzz
|
|
generate_message [dir]=zzz
|
|
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "Added 3 new messages to the database."
|
|
|
|
|
|
test_begin_subtest "Deleted directory (end of list)"
|
|
|
|
rm -rf "${MAIL_DIR}"/zzz
|
|
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "(D) add_files, pass 3: queuing leftover directory ${MAIL_DIR}/zzz for deletion from database
|
|
No new mail. Removed 3 messages."
|
|
|
|
|
|
test_begin_subtest "New symlink to directory"
|
|
|
|
rm -rf "${MAIL_DIR}"/.notmuch
|
|
mv "${MAIL_DIR}" "${TMP_DIRECTORY}"/actual_maildir
|
|
|
|
mkdir "${MAIL_DIR}"
|
|
ln -s "${TMP_DIRECTORY}"/actual_maildir "${MAIL_DIR}"/symlink
|
|
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "Added 1 new message to the database."
|
|
|
|
|
|
test_begin_subtest "New symlink to a file"
|
|
generate_message
|
|
external_msg_filename="${TMP_DIRECTORY}"/external/"$(basename "$gen_msg_filename")"
|
|
mkdir -p "$(dirname "$external_msg_filename")"
|
|
mv "$gen_msg_filename" "$external_msg_filename"
|
|
ln -s "$external_msg_filename" "$gen_msg_filename"
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "Added 1 new message to the database."
|
|
|
|
|
|
test_begin_subtest "Broken symlink aborts"
|
|
ln -s does-not-exist "${MAIL_DIR}/broken"
|
|
output=$(NOTMUCH_NEW --debug 2>&1)
|
|
test_expect_equal "$output" \
|
|
"Error reading file ${MAIL_DIR}/broken: No such file or directory
|
|
Note: A fatal error was encountered: Something went wrong trying to read or write a file
|
|
No new mail."
|
|
rm "${MAIL_DIR}/broken"
|
|
|
|
|
|
test_begin_subtest "New two-level directory"
|
|
|
|
generate_message [dir]=two/levels
|
|
generate_message [dir]=two/levels
|
|
generate_message [dir]=two/levels
|
|
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "Added 3 new messages to the database."
|
|
|
|
|
|
test_begin_subtest "Deleted two-level directory"
|
|
|
|
rm -rf "${MAIL_DIR}"/two
|
|
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "(D) add_files, pass 3: queuing leftover directory ${MAIL_DIR}/two for deletion from database
|
|
No new mail. Removed 3 messages."
|
|
|
|
test_begin_subtest "One character directory at top level"
|
|
|
|
generate_message [dir]=A
|
|
generate_message [dir]=A/B
|
|
generate_message [dir]=A/B/C
|
|
|
|
output=$(NOTMUCH_NEW --debug)
|
|
test_expect_equal "$output" "Added 3 new messages to the database."
|
|
|
|
test_begin_subtest "Support single-message mbox"
|
|
cat > "${MAIL_DIR}"/mbox_file1 <<EOF
|
|
From test_suite@notmuchmail.org Fri Jan 5 15:43:57 2001
|
|
From: Notmuch Test Suite <test_suite@notmuchmail.org>
|
|
To: Notmuch Test Suite <test_suite@notmuchmail.org>
|
|
Subject: Test mbox message 1
|
|
|
|
Body.
|
|
EOF
|
|
output=$(NOTMUCH_NEW --debug 2>&1)
|
|
test_expect_equal "$output" "Added 1 new message to the database."
|
|
|
|
# This test requires that notmuch new has been run at least once.
|
|
test_begin_subtest "Skip and report non-mail files"
|
|
generate_message
|
|
mkdir -p "${MAIL_DIR}"/.git && touch "${MAIL_DIR}"/.git/config
|
|
touch "${MAIL_DIR}"/ignored_file
|
|
touch "${MAIL_DIR}"/.ignored_hidden_file
|
|
cat > "${MAIL_DIR}"/mbox_file <<EOF
|
|
From test_suite@notmuchmail.org Fri Jan 5 15:43:57 2001
|
|
From: Notmuch Test Suite <test_suite@notmuchmail.org>
|
|
To: Notmuch Test Suite <test_suite@notmuchmail.org>
|
|
Subject: Test mbox message 1
|
|
|
|
Body.
|
|
|
|
From test_suite@notmuchmail.org Fri Jan 5 15:43:57 2001
|
|
From: Notmuch Test Suite <test_suite@notmuchmail.org>
|
|
To: Notmuch Test Suite <test_suite@notmuchmail.org>
|
|
Subject: Test mbox message 2
|
|
|
|
Body 2.
|
|
EOF
|
|
output=$(NOTMUCH_NEW --debug 2>&1)
|
|
test_expect_equal "$output" \
|
|
"Note: Ignoring non-mail file: ${MAIL_DIR}/.git/config
|
|
Note: Ignoring non-mail file: ${MAIL_DIR}/.ignored_hidden_file
|
|
Note: Ignoring non-mail file: ${MAIL_DIR}/ignored_file
|
|
Note: Ignoring non-mail file: ${MAIL_DIR}/mbox_file
|
|
Added 1 new message to the database."
|
|
rm "${MAIL_DIR}"/mbox_file
|
|
|
|
test_begin_subtest "Ignore files and directories specified in new.ignore"
|
|
generate_message
|
|
notmuch config set new.ignore .git ignored_file .ignored_hidden_file
|
|
touch "${MAIL_DIR}"/.git # change .git's mtime for notmuch new to rescan.
|
|
output=$(NOTMUCH_NEW 2>&1)
|
|
test_expect_equal "$output" "Added 1 new message to the database."
|
|
|
|
test_begin_subtest "Ignore files and directories specified in new.ignore (multiple occurrences)"
|
|
notmuch config set new.ignore .git ignored_file .ignored_hidden_file
|
|
notmuch new > /dev/null # ensure that files/folders will be printed in ASCII order.
|
|
touch "${MAIL_DIR}"/.git # change .git's mtime for notmuch new to rescan.
|
|
touch "${MAIL_DIR}" # likewise for MAIL_DIR
|
|
mkdir -p "${MAIL_DIR}"/one/two/three/.git
|
|
touch "${MAIL_DIR}"/{one,one/two,one/two/three}/ignored_file
|
|
output=$(NOTMUCH_NEW --debug 2>&1 | sort)
|
|
test_expect_equal "$output" \
|
|
"(D) add_files, pass 1: explicitly ignoring ${MAIL_DIR}/.git
|
|
(D) add_files, pass 1: explicitly ignoring ${MAIL_DIR}/.ignored_hidden_file
|
|
(D) add_files, pass 1: explicitly ignoring ${MAIL_DIR}/ignored_file
|
|
(D) add_files, pass 1: explicitly ignoring ${MAIL_DIR}/one/ignored_file
|
|
(D) add_files, pass 1: explicitly ignoring ${MAIL_DIR}/one/two/ignored_file
|
|
(D) add_files, pass 1: explicitly ignoring ${MAIL_DIR}/one/two/three/.git
|
|
(D) add_files, pass 1: explicitly ignoring ${MAIL_DIR}/one/two/three/ignored_file
|
|
(D) add_files, pass 2: explicitly ignoring ${MAIL_DIR}/.git
|
|
(D) add_files, pass 2: explicitly ignoring ${MAIL_DIR}/.ignored_hidden_file
|
|
(D) add_files, pass 2: explicitly ignoring ${MAIL_DIR}/ignored_file
|
|
(D) add_files, pass 2: explicitly ignoring ${MAIL_DIR}/one/ignored_file
|
|
(D) add_files, pass 2: explicitly ignoring ${MAIL_DIR}/one/two/ignored_file
|
|
(D) add_files, pass 2: explicitly ignoring ${MAIL_DIR}/one/two/three/.git
|
|
(D) add_files, pass 2: explicitly ignoring ${MAIL_DIR}/one/two/three/ignored_file
|
|
No new mail."
|
|
|
|
|
|
test_begin_subtest "Don't stop for ignored broken symlinks"
|
|
notmuch config set new.ignore .git ignored_file .ignored_hidden_file broken_link
|
|
ln -s i_do_not_exist "${MAIL_DIR}"/broken_link
|
|
output=$(NOTMUCH_NEW 2>&1)
|
|
test_expect_equal "$output" "No new mail."
|
|
|
|
test_begin_subtest "Quiet: No new mail."
|
|
output=$(NOTMUCH_NEW --quiet)
|
|
test_expect_equal "$output" ""
|
|
|
|
test_begin_subtest "Quiet: new, removed and renamed messages."
|
|
# new
|
|
generate_message
|
|
# deleted
|
|
notmuch search --format=text0 --output=files --limit=1 '*' | xargs -0 rm
|
|
# moved
|
|
mkdir "${MAIL_DIR}"/moved_messages
|
|
notmuch search --format=text0 --output=files --offset=1 --limit=1 '*' | xargs -0 -I {} mv {} "${MAIL_DIR}"/moved_messages
|
|
output=$(NOTMUCH_NEW --quiet)
|
|
test_expect_equal "$output" ""
|
|
|
|
OLDCONFIG=$(notmuch config get new.tags)
|
|
|
|
test_begin_subtest "Empty tags in new.tags are forbidden"
|
|
notmuch config set new.tags "foo;;bar"
|
|
output=$(NOTMUCH_NEW --debug 2>&1)
|
|
test_expect_equal "$output" "Error: tag '' in new.tags: empty tag forbidden"
|
|
|
|
test_begin_subtest "Tags starting with '-' in new.tags are forbidden"
|
|
notmuch config set new.tags "-foo;bar"
|
|
output=$(NOTMUCH_NEW --debug 2>&1)
|
|
test_expect_equal "$output" "Error: tag '-foo' in new.tags: tag starting with '-' forbidden"
|
|
|
|
test_expect_code 1 "Invalid tags set exit code" \
|
|
"NOTMUCH_NEW --debug 2>&1"
|
|
|
|
notmuch config set new.tags $OLDCONFIG
|
|
|
|
|
|
test_begin_subtest "Xapian exception: read only files"
|
|
chmod u-w ${MAIL_DIR}/.notmuch/xapian/*.${db_ending}
|
|
output=$(NOTMUCH_NEW --debug 2>&1 | sed 's/: .*$//' )
|
|
chmod u+w ${MAIL_DIR}/.notmuch/xapian/*.${db_ending}
|
|
test_expect_equal "$output" "A Xapian exception occurred opening database"
|
|
|
|
test_done
|