From: David Bremner Date: Sun, 9 Jan 2022 13:20:56 +0000 (-0400) Subject: Merge branch 'release' X-Git-Tag: 0.35_rc0~54 X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=commitdiff_plain;h=22e04ed01acc115b7fb25b60231014f585f11c4a;hp=9e7ea628e6bddbd7345d053a3daf14af74896cc2 Merge branch 'release' --- diff --git a/Makefile.global b/Makefile.global index fe79121d..7a7a3c6d 100644 --- a/Makefile.global +++ b/Makefile.global @@ -50,9 +50,9 @@ DETACHED_SIG_FILE=$(TAR_FILE).asc PV_FILE=bindings/python/notmuch/version.py # Smash together user's values with our extra values -FINAL_CFLAGS = -DNOTMUCH_VERSION=$(VERSION) $(CPPFLAGS) $(CFLAGS) $(WARN_CFLAGS) $(extra_cflags) $(CONFIGURE_CFLAGS) -FINAL_CXXFLAGS = $(CPPFLAGS) $(CXXFLAGS) $(WARN_CXXFLAGS) $(extra_cflags) $(extra_cxxflags) $(CONFIGURE_CXXFLAGS) -FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Lutil -lnotmuch_util -Llib -lnotmuch +FINAL_CFLAGS = -DNOTMUCH_VERSION=$(VERSION) $(WARN_CFLAGS) $(extra_cflags) $(CPPFLAGS) $(CONFIGURE_CFLAGS) $(CFLAGS) +FINAL_CXXFLAGS = $(WARN_CXXFLAGS) $(extra_cflags) $(extra_cxxflags) $(CPPFLAGS) $(CONFIGURE_CXXFLAGS) $(CXXFLAGS) +FINAL_NOTMUCH_LDFLAGS = -Lutil -lnotmuch_util -Llib -lnotmuch $(LDFLAGS) ifeq ($(LIBDIR_IN_LDCONFIG),0) FINAL_NOTMUCH_LDFLAGS += $(RPATH_LDFLAGS) endif diff --git a/Makefile.local b/Makefile.local index e12b94cd..10fb9908 100644 --- a/Makefile.local +++ b/Makefile.local @@ -54,7 +54,6 @@ update-versions: sed -i -e "s/^__VERSION__[[:blank:]]*=.*$$/__VERSION__ = \'${VERSION}\'/" \ -e "s/^SOVERSION[[:blank:]]*=.*$$/SOVERSION = \'${LIBNOTMUCH_VERSION_MAJOR}\'/" \ ${PV_FILE} - cp version.txt bindings/python-cffi # We invoke make recursively only to force ordering of our phony # targets in the case of parallel invocation of make (-j). diff --git a/bindings/Makefile.local b/bindings/Makefile.local index 3672e69f..7b10af08 100644 --- a/bindings/Makefile.local +++ b/bindings/Makefile.local @@ -3,21 +3,26 @@ dir := bindings # force the shared library to be built -ruby-bindings: lib/$(LINKER_NAME) +ruby-bindings: $(dir)/ruby.stamp + +$(dir)/ruby.stamp: lib/$(LINKER_NAME) ifeq ($(HAVE_RUBY_DEV),1) cd $(dir)/ruby && \ EXTRA_LDFLAGS="$(NO_UNDEFINED_LDFLAGS)" \ LIBNOTMUCH="../../lib/$(LINKER_NAME)" \ NOTMUCH_SRCDIR='$(NOTMUCH_SRCDIR)' \ $(RUBY) extconf.rb --vendor - $(MAKE) -C $(dir)/ruby CFLAGS="$(CFLAGS) -pipe -fno-plt -fPIC" + $(MAKE) -C $(dir)/ruby CFLAGS="$(CFLAGS) -pipe -fno-plt -fPIC" && touch $@ endif -python-cffi-bindings: lib/$(LINKER_NAME) +python-cffi-bindings: $(dir)/python-cffi.stamp + +$(dir)/python-cffi.stamp: lib/$(LINKER_NAME) ifeq ($(HAVE_PYTHON3_CFFI),1) cd $(dir)/python-cffi && \ ${PYTHON} setup.py build --build-lib build/stage && \ - mkdir -p build/stage/tests && cp tests/*.py build/stage/tests + mkdir -p build/stage/tests && cp tests/*.py build/stage/tests && \ + touch ../python-cffi.stamp endif CLEAN += $(patsubst %,$(dir)/ruby/%, \ @@ -26,6 +31,6 @@ CLEAN += $(patsubst %,$(dir)/ruby/%, \ init.o message.o messages.o mkmf.log notmuch.so query.o \ status.o tags.o thread.o threads.o) -CLEAN += bindings/ruby/.vendorarchdir.time +CLEAN += bindings/ruby/.vendorarchdir.time $(dir)/ruby.stamp -CLEAN += bindings/python-cffi/build +CLEAN += bindings/python-cffi/build $(dir)/python-cffi.stamp diff --git a/bindings/python-cffi/notmuch2/_build.py b/bindings/python-cffi/notmuch2/_build.py index f6184b97..45eb20c0 100644 --- a/bindings/python-cffi/notmuch2/_build.py +++ b/bindings/python-cffi/notmuch2/_build.py @@ -1,5 +1,5 @@ import cffi - +from _notmuch_config import * ffibuilder = cffi.FFI() ffibuilder.set_source( @@ -16,8 +16,8 @@ ffibuilder.set_source( #ERROR libnotmuch version < 5.1 not supported #endif """, - include_dirs=['../../lib'], - library_dirs=['../../lib'], + include_dirs=[NOTMUCH_INCLUDE_DIR], + library_dirs=[NOTMUCH_LIB_DIR], libraries=['notmuch'], ) ffibuilder.cdef( diff --git a/bindings/python-cffi/notmuch2/_message.py b/bindings/python-cffi/notmuch2/_message.py index b4f651fb..aa1cb875 100644 --- a/bindings/python-cffi/notmuch2/_message.py +++ b/bindings/python-cffi/notmuch2/_message.py @@ -205,6 +205,20 @@ class Message(base.NotmuchObject): self._msg_p, capi.lib.NOTMUCH_MESSAGE_FLAG_EXCLUDED) return bool(ret) + @property + def matched(self): + """Indicates whether this message was matched by the query. + + When a thread is created from a search, some of the + messages may not match the original query. This property + is set to *True* for those that do match. + + :raises ObjectDestroyedError: if used after destroyed. + """ + ret = capi.lib.notmuch_message_get_flag( + self._msg_p, capi.lib.NOTMUCH_MESSAGE_FLAG_MATCH) + return bool(ret) + @property def date(self): """The message date as an integer. diff --git a/bindings/python-cffi/setup.py b/bindings/python-cffi/setup.py index cda52338..55fb2d24 100644 --- a/bindings/python-cffi/setup.py +++ b/bindings/python-cffi/setup.py @@ -1,6 +1,7 @@ import setuptools +from _notmuch_config import * -with open('version.txt') as fp: +with open(NOTMUCH_VERSION_FILE) as fp: VERSION = fp.read().strip() setuptools.setup( diff --git a/bindings/python-cffi/tests/test_message.py b/bindings/python-cffi/tests/test_message.py index 532bf921..56701d05 100644 --- a/bindings/python-cffi/tests/test_message.py +++ b/bindings/python-cffi/tests/test_message.py @@ -97,6 +97,9 @@ class TestMessage: def test_ghost_no(self, msg): assert not msg.ghost + def test_matched_no(self,msg): + assert not msg.matched + def test_date(self, msg): # XXX Someone seems to treat things as local time instead of # UTC or the other way around. diff --git a/bindings/python-cffi/tests/test_thread.py b/bindings/python-cffi/tests/test_thread.py index 1f44b35d..fbef73ac 100644 --- a/bindings/python-cffi/tests/test_thread.py +++ b/bindings/python-cffi/tests/test_thread.py @@ -57,6 +57,13 @@ def test_iter(thread): def test_matched(thread): assert thread.matched == 1 +def test_matched_iter(thread): + count = 0 + msgs = list(iter(thread)) + for msg in msgs: + if msg.matched: + count += 1 + assert count == thread.matched def test_authors_type(thread): assert isinstance(thread.authors, notmuch2.BinString) diff --git a/bindings/python-cffi/version.txt b/bindings/python-cffi/version.txt deleted file mode 100644 index 3f8003cd..00000000 --- a/bindings/python-cffi/version.txt +++ /dev/null @@ -1 +0,0 @@ -0.34.2 diff --git a/completion/notmuch-completion.bash b/completion/notmuch-completion.bash index 15425697..0022b54b 100644 --- a/completion/notmuch-completion.bash +++ b/completion/notmuch-completion.bash @@ -103,12 +103,12 @@ _notmuch_search_terms() COMPREPLY=( $(compgen -P "from:" -W "`_notmuch_email ${cur}`" -- ${cur##from:}) ) ;; path:*) - local path=`notmuch config get database.path` + local path=`notmuch config get database.mail_root` compopt -o nospace COMPREPLY=( $(compgen -d "$path/${cur##path:}" | sed "s|^$path/||" ) ) ;; folder:*) - local path=`notmuch config get database.path` + local path=`notmuch config get database.mail_root` compopt -o nospace COMPREPLY=( $(compgen -d "$path/${cur##folder:}" | \ sed "s|^$path/||" | grep -v "\(^\|/\)\(cur\|new\|tmp\)$" ) ) @@ -281,7 +281,7 @@ _notmuch_insert() $split && case "${prev}" in --folder) - local path=`notmuch config get database.path` + local path=`notmuch config get database.mail_root` compopt -o nospace COMPREPLY=( $(compgen -d "$path/${cur}" | \ sed "s|^$path/||" | grep -v "\(^\|/\)\(cur\|new\|tmp\)$" ) ) diff --git a/completion/zsh/_notmuch b/completion/zsh/_notmuch index e920f10b..e207d90b 100644 --- a/completion/zsh/_notmuch +++ b/completion/zsh/_notmuch @@ -69,8 +69,8 @@ _notmuch_term_mimetype() { _notmuch_term_path() { local ret=1 expl - local maildir="$(notmuch config get database.path)" - [[ -d $maildir ]] || { _message -e "database.path not found" ; return $ret } + local maildir="$(notmuch config get database.mail_root)" + [[ -d $maildir ]] || { _message -e "database.mail_root not found" ; return $ret } _description notmuch-folder expl 'maildir folder' _files "$expl[@]" -W $maildir -/ && ret=0 @@ -79,8 +79,8 @@ _notmuch_term_path() { _notmuch_term_folder() { local ret=1 expl - local maildir="$(notmuch config get database.path)" - [[ -d $maildir ]] || { _message -e "database.path not found" ; return $ret } + local maildir="$(notmuch config get database.mail_root)" + [[ -d $maildir ]] || { _message -e "database.mail_root not found" ; return $ret } _description notmuch-folder expl 'maildir folder' local ignoredfolders=( '*/(cur|new|tmp)' ) diff --git a/configure b/configure index 9b692b3e..e7bb7edc 100755 --- a/configure +++ b/configure @@ -738,6 +738,7 @@ if command -v ${BASHCMD} > /dev/null; then printf "Yes (%s).\n" "$bash_absolute" else have_bash=0 + bash_absolute= printf "No. (%s not found)\n" "${BASHCMD}" fi @@ -748,6 +749,7 @@ if command -v ${PERL} > /dev/null; then printf "Yes (%s).\n" "$perl_absolute" else have_perl=0 + perl_absolute= printf "No. (%s not found)\n" "${PERL}" fi @@ -1584,6 +1586,14 @@ EOF printf "rsti_dir = '%s'\n" "$(cd emacs && pwd -P)" } > sphinx.config +cat > bindings/python-cffi/_notmuch_config.py <> $@ CLEAN := $(CLEAN) $(DOCBUILDDIR) $(DOCBUILDDIR)/.roff.stamp $(DOCBUILDDIR)/.texi.stamp -CLEAN := $(CLEAN) $(DOCBUILDDIR)/.html.stamp +CLEAN := $(CLEAN) $(DOCBUILDDIR)/.html.stamp $(DOCBUILDDIR)/.info.stamp CLEAN := $(CLEAN) $(MAN_GZIP_FILES) $(MAN_ROFF_FILES) $(dir)/conf.pyc $(dir)/config.dox diff --git a/doc/man1/notmuch-address.rst b/doc/man1/notmuch-address.rst index 7423b629..c70dde35 100644 --- a/doc/man1/notmuch-address.rst +++ b/doc/man1/notmuch-address.rst @@ -42,7 +42,7 @@ Supported options for **address** include neither ``--output=sender`` nor ``--output=recipients`` is given, ``--output=sender`` is implied. - **sender** + sender Output all addresses from the *From* header. Note: Searching for **sender** should be much faster than @@ -50,17 +50,17 @@ Supported options for **address** include cached directly in the database whereas other addresses need to be fetched from message files. - **recipients** + recipients Output all addresses from the *To*, *Cc* and *Bcc* headers. - **count** + count Print the count of how many times was the address encountered during search. Note: With this option, addresses are printed only after the whole search is finished. This may take long time. - **address** + address Output only the email addresses instead of the full mailboxes with names and email addresses. This option has no effect on the JSON or S-Expression output formats. @@ -69,17 +69,17 @@ Supported options for **address** include Control the deduplication of results. - **no** + no Output all occurrences of addresses in the matching messages. This is not applicable with ``--output=count``. - **mailbox** + mailbox Deduplicate addresses based on the full, case sensitive name and email address, or mailbox. This is effectively the same as piping the ``--deduplicate=no`` output to **sort | uniq**, except for the order of results. This is the default. - **address** + address Deduplicate addresses based on the case insensitive address part of the mailbox. Of all the variants (with different name or case), print the one occurring most frequently among the diff --git a/doc/man1/notmuch-config.rst b/doc/man1/notmuch-config.rst index 36e57ea6..ed188a25 100644 --- a/doc/man1/notmuch-config.rst +++ b/doc/man1/notmuch-config.rst @@ -55,14 +55,14 @@ The available configuration items are described below. Non-absolute paths are presumed relative to `$HOME` for items in section **database**. -**database.path** +database.path Notmuch will store its database here, (in sub-directory named ``.notmuch`` if **database.mail\_root** is unset). Default: see :ref:`database` -**database.mail_root** +database.mail_root The top-level directory where your mail currently exists and to where mail will be delivered in the future. Files should be individual email messages. @@ -72,7 +72,7 @@ paths are presumed relative to `$HOME` for items in section Default: For compatibility with older configurations, the value of database.path is used if **database.mail\_root** is unset. -**database.backup_dir** +database.backup_dir Directory to store tag dumps when upgrading database. History: this configuration value was introduced in notmuch 0.32. @@ -80,7 +80,7 @@ paths are presumed relative to `$HOME` for items in section Default: A sibling directory of the Xapian database called `backups`. -**database.hook_dir** +database.hook_dir Directory containing hooks run by notmuch commands. See :any:`notmuch-hooks(5)`. @@ -88,7 +88,7 @@ paths are presumed relative to `$HOME` for items in section Default: See HOOKS, below. -**database.autocommit** +database.autocommit How often to commit transactions to disk. `0` means wait until command completes, otherwise an integer `n` specifies to commit to @@ -96,30 +96,30 @@ paths are presumed relative to `$HOME` for items in section History: this configuration value was introduced in notmuch 0.33. -**user.name** +user.name Your full name. Default: ``$NAME`` variable if set, otherwise read from ``/etc/passwd``. -**user.primary\_email** +user.primary\_email Your primary email address. Default: ``$EMAIL`` variable if set, otherwise constructed from the username and hostname of the current machine. -**user.other\_email** +user.other\_email A list of other email addresses at which you receive email. Default: not set. -**new.tags** +new.tags A list of tags that will be added to all messages incorporated by **notmuch new**. Default: ``unread;inbox``. -**new.ignore** +new.ignore A list to specify files and directories that will not be searched for messages by :any:`notmuch-new(1)`. Each entry in the list is either: @@ -137,7 +137,7 @@ paths are presumed relative to `$HOME` for items in section Default: empty list. -**search.exclude\_tags** +search.exclude\_tags A list of tags that will be excluded from search results by default. Using an excluded tag in a query will override that exclusion. @@ -145,7 +145,7 @@ paths are presumed relative to `$HOME` for items in section Default: empty list. Note that :any:`notmuch-setup(1)` puts ``deleted;spam`` here when creating new configuration file. -**maildir.synchronize\_flags** +maildir.synchronize\_flags If true, then the following maildir flags (in message filenames) will be synchronized with the corresponding notmuch tags: @@ -178,7 +178,7 @@ paths are presumed relative to `$HOME` for items in section Default: ``true``. -**index.decrypt** +index.decrypt Policy for decrypting encrypted messages during indexing. Must be one of: ``false``, ``auto``, ``nostash``, or ``true``. @@ -231,7 +231,7 @@ paths are presumed relative to `$HOME` for items in section Default: ``auto``. -**index.header.** +index.header. Define the query prefix , based on a mail header. For example ``index.header.List=List-Id`` will add a probabilistic prefix ``List:`` that searches the ``List-Id`` field. User @@ -240,18 +240,18 @@ paths are presumed relative to `$HOME` for items in section supported. See :any:`notmuch-search-terms(7)` for a list of existing prefixes, and an explanation of probabilistic prefixes. -**built_with.** +built_with. Compile time feature . Current possibilities include "retry_lock" (configure option, included by default). (since notmuch 0.30, "compact" and "field_processor" are always included.) -**query.** +query. Expansion for named query called . See :any:`notmuch-search-terms(7)` for more information about named queries. -**squery.** +squery. Expansion for named query called , using s-expression syntax. See :any:`notmuch-sexp-queries(7)` for more information about s-expression queries. diff --git a/doc/man1/notmuch-count.rst b/doc/man1/notmuch-count.rst index 9a7e4bac..4c9c9a1c 100644 --- a/doc/man1/notmuch-count.rst +++ b/doc/man1/notmuch-count.rst @@ -28,13 +28,13 @@ Supported options for **count** include .. option:: --output=(messages|threads|files) - **messages** + messages Output the number of matching messages. This is the default. - **threads** + threads Output the number of matching threads. - **files** + files Output the number of files associated with matching messages. This may be bigger than the number of matching messages due to duplicates (i.e. multiple files having the diff --git a/doc/man1/notmuch-dump.rst b/doc/man1/notmuch-dump.rst index 4319c5c3..a7ca39d0 100644 --- a/doc/man1/notmuch-dump.rst +++ b/doc/man1/notmuch-dump.rst @@ -39,7 +39,7 @@ Supported options for **dump** include Notmuch restore supports two plain text dump formats, both with one message-id per line, followed by a list of tags. - **batch-tag** + batch-tag The default **batch-tag** dump format is intended to more robust against malformed message-ids and tags containing whitespace or non-\ :manpage:`ascii(7)` characters. Each line @@ -58,7 +58,7 @@ Supported options for **dump** include :any:`notmuch-tag(1)`; note that the single message-id query is mandatory for :any:`notmuch-restore(1)`. - **sup** + sup The **sup** dump file format is specifically chosen to be compatible with the format of files produced by :manpage:`sup-dump(1)`. So if you've previously been using sup @@ -77,18 +77,18 @@ Supported options for **dump** include Control what kind of metadata is included in the output. - **config** + config Output configuration data stored in the database. Each line starts with "#@ ", followed by a space separated key-value pair. Both key and value are hex encoded if needed. - **properties** + properties Output per-message (key,value) metadata. Each line starts with "#= ", followed by a message id, and a space separated list of key=value pairs. Ids, keys and values are hex encoded if needed. See :any:`notmuch-properties(7)` for more details. - **tags** + tags Output per-message boolean metadata, namely tags. See *format* above for description of the output. diff --git a/doc/man1/notmuch-insert.rst b/doc/man1/notmuch-insert.rst index 82c4a7a0..da9ca791 100644 --- a/doc/man1/notmuch-insert.rst +++ b/doc/man1/notmuch-insert.rst @@ -14,7 +14,7 @@ DESCRIPTION **notmuch insert** reads a message from standard input and delivers it into the maildir directory given by configuration option -**database.path**, then incorporates the message into the notmuch +**database.mail_root**, then incorporates the message into the notmuch database. It is an alternative to using a separate tool to deliver the message then running :any:`notmuch-new(1)` afterwards. @@ -38,7 +38,7 @@ Supported options for **insert** include .. option:: --folder= Deliver the message to the specified folder, relative to the - top-level directory given by the value of **database.path**. The + top-level directory given by the value of **database.mail_root**. The default is the empty string, which means delivering to the top-level directory. diff --git a/doc/man1/notmuch-reply.rst b/doc/man1/notmuch-reply.rst index 4a78a90b..fa0371f9 100644 --- a/doc/man1/notmuch-reply.rst +++ b/doc/man1/notmuch-reply.rst @@ -40,22 +40,22 @@ Supported options for **reply** include .. option:: --format=(default|json|sexp|headers-only) - **default** + default Includes subject and quoted message body as an RFC 2822 message. - **json** + json Produces JSON output containing headers for a reply message and the contents of the original message. This output can be used by a client to create a reply message intelligently. - **sexp** + sexp Produces S-Expression output containing headers for a reply message and the contents of the original message. This output can be used by a client to create a reply message intelligently. - **headers-only** + headers-only Only produces In-Reply-To, References, To, Cc, and Bcc headers. @@ -67,10 +67,10 @@ Supported options for **reply** include .. option:: --reply-to=(all|sender) - **all** (default) + all (default) Replies to all addresses. - **sender** + sender Replies only to the sender. If replying to user's own message (Reply-to: or From: header is one of the user's configured email addresses), try To:, Cc:, and Bcc: headers in this diff --git a/doc/man1/notmuch-restore.rst b/doc/man1/notmuch-restore.rst index bd452475..ac6b4245 100644 --- a/doc/man1/notmuch-restore.rst +++ b/doc/man1/notmuch-restore.rst @@ -32,14 +32,14 @@ Supported options for **restore** include line specifying a message-id and a set of tags. For details of the actual formats, see :any:`notmuch-dump(1)`. - **sup** + sup The **sup** dump file format is specifically chosen to be compatible with the format of files produced by sup-dump. So if you've previously been using sup for mail, then the **notmuch restore** command provides you a way to import all of your tags (or labels as sup calls them). - **batch-tag** + batch-tag The **batch-tag** dump format is intended to more robust against malformed message-ids and tags containing whitespace or non-\ **ascii(7)** characters. See :any:`notmuch-dump(1)` for @@ -49,7 +49,7 @@ Supported options for **restore** include changes if the **maildir.synchronize\_flags** configuration option is enabled. See :any:`notmuch-config(1)` for details. - **auto** + auto This option (the default) tries to guess the format from the input. For correctly formed input in either supported format, this heuristic, based the fact that batch-tag format contains @@ -59,18 +59,18 @@ Supported options for **restore** include Control what kind of metadata is restored. - **config** + config Restore configuration data to the database. Each configuration line starts with "#@ ", followed by a space separated key-value pair. Both key and value are hex encoded if needed. - **properties** + properties Restore per-message (key,value) metadata. Each line starts with "#= ", followed by a message id, and a space separated list of key=value pairs. Ids, keys and values are hex encoded if needed. See :any:`notmuch-properties(7)` for more details. - **tags** + tags Restore per-message metadata, namely tags. See *format* above for more details. diff --git a/doc/man1/notmuch-search.rst b/doc/man1/notmuch-search.rst index 2d9ca2d5..ad305efd 100644 --- a/doc/man1/notmuch-search.rst +++ b/doc/man1/notmuch-search.rst @@ -43,7 +43,7 @@ Supported options for **search** include .. option:: --output=(summary|threads|messages|files|tags) - **summary** + summary Output a summary of each thread with any message matching the search terms. The summary includes the thread ID, date, the number of messages in the thread (both the number matched and @@ -52,19 +52,19 @@ Supported options for **search** include for some messages, the total number of files is printed in parentheses (see below for an example). - **threads** + threads Output the thread IDs of all threads with any message matching the search terms, either one per line (``--format=text``), separated by null characters (``--format=text0``), as a JSON array (``--format=json``), or an S-Expression list (``--format=sexp``). - **messages** + messages Output the message IDs of all messages matching the search terms, either one per line (``--format=text``), separated by null characters (``--format=text0``), as a JSON array (``--format=json``), or as an S-Expression list (``--format=sexp``). - **files** + files Output the filenames of all messages matching the search terms, either one per line (``--format=text``), separated by null characters (``--format=text0``), as a JSON array (``--format=json``), @@ -78,7 +78,7 @@ Supported options for **search** include in other directories that are included in the output, although these files alone would not match the search. - **tags** + tags Output all tags that appear on any message matching the search terms, either one per line (``--format=text``), separated by null characters (``--format=text0``), as a JSON array (``--format=json``), @@ -115,20 +115,20 @@ Supported options for **search** include terms. This option specifies whether to omit excluded messages in the search process. - **true** (default) + true (default) Prevent excluded messages from matching the search terms. - **all** + all Additionally prevent excluded messages from appearing in displayed results, in effect behaving as though the excluded messages do not exist. - **false** + false Allow excluded messages to match search terms and appear in displayed results. Excluded messages are still marked in the relevant outputs. - **flag** + flag Only has an effect when ``--output=summary``. The output is almost identical to **false**, but the "match count" is the number of matching non-excluded messages in the thread, rather diff --git a/doc/man1/notmuch-show.rst b/doc/man1/notmuch-show.rst index 64639174..3d2a2c41 100644 --- a/doc/man1/notmuch-show.rst +++ b/doc/man1/notmuch-show.rst @@ -36,7 +36,7 @@ Supported options for **show** include .. option:: --format=(text|json|sexp|mbox|raw) - **text** (default for messages) + text (default for messages) The default plain-text format has all text-content MIME parts decoded. Various components in the output, (**message**, **header**, **body**, **attachment**, and MIME **part**), will @@ -46,7 +46,7 @@ Supported options for **show** include '}'), to either open or close the component. For a multipart MIME message, these parts will be nested. - **json** + json The output is formatted with Javascript Object Notation (JSON). This format is more robust than the text format for automated processing. The nested structure of multipart MIME @@ -58,7 +58,7 @@ Supported options for **show** include as UTF-8 and any message content included in the output will be charset-converted to UTF-8. - **sexp** + sexp The output is formatted as the Lisp s-expression (sexp) equivalent of the JSON format above. Objects are formatted as property lists whose keys are keywords (symbols preceded by a @@ -66,7 +66,7 @@ Supported options for **show** include formatted as ``nil``. As for JSON, the s-expression output is always encoded as UTF-8. - **mbox** + mbox All matching messages are output in the traditional, Unix mbox format with each message being prefixed by a line beginning with "From " and a blank line separating each message. Lines @@ -77,7 +77,7 @@ Supported options for **show** include http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/mail-mbox-formats.html - **raw** (default if ``--part`` is given) + raw (default if ``--part`` is given) Write the raw bytes of the given MIME part of a message to standard out. For this format, it is an error to specify a query that matches more than one message. diff --git a/doc/man5/notmuch-hooks.rst b/doc/man5/notmuch-hooks.rst index 268917cd..0ab5efbc 100644 --- a/doc/man5/notmuch-hooks.rst +++ b/doc/man5/notmuch-hooks.rst @@ -19,7 +19,7 @@ must have executable permissions. The currently available hooks are described below. -**pre-new** +pre-new This hook is invoked by the :any:`notmuch-new(1)` command before scanning or importing new messages into the database. If this hook exits with a non-zero status, notmuch will abort further @@ -28,7 +28,7 @@ The currently available hooks are described below. Typically this hook is used for fetching or delivering new mail to be imported into the database. -**post-new** +post-new This hook is invoked by the :any:`notmuch-new(1)` command after new messages have been imported into the database and initial tags have been applied. The hook will not be run if there have been any @@ -37,7 +37,7 @@ The currently available hooks are described below. Typically this hook is used to perform additional query-based tagging on the imported messages. -**post-insert** +post-insert This hook is invoked by the :any:`notmuch-insert(1)` command after the message has been delivered, added to the database, and initial tags have been applied. The hook will not be run if there have diff --git a/doc/man7/notmuch-properties.rst b/doc/man7/notmuch-properties.rst index 7f128b5c..ff79f4c2 100644 --- a/doc/man7/notmuch-properties.rst +++ b/doc/man7/notmuch-properties.rst @@ -55,7 +55,7 @@ MESSAGE PROPERTIES The following properties are set by notmuch internally in the course of its normal activity. -**index.decryption** +index.decryption If a message contains encrypted content, and notmuch tries to decrypt that content during indexing, it will add the property ``index.decryption=success`` when the cleartext was successfully @@ -75,8 +75,7 @@ of its normal activity. :any:`notmuch-config(1)`), then this property will not be set on that message. -**session-key** - +session-key When :any:`notmuch-show(1)` or :any:`notmuch-reply(1)` encounters a message with an encrypted part, if notmuch finds a ``session-key`` property associated with the message, it will try @@ -111,8 +110,7 @@ of its normal activity. example, an AES-128 key might be stashed in a notmuch property as: ``session-key=7:14B16AF65536C28AF209828DFE34C9E0``. -**index.repaired** - +index.repaired Some messages arrive in forms that are confusing to view; they can be mangled by mail transport agents, or the sending mail user agent may structure them in a way that is confusing. If notmuch diff --git a/doc/man7/notmuch-sexp-queries.rst b/doc/man7/notmuch-sexp-queries.rst index 019d15f0..3c33232f 100644 --- a/doc/man7/notmuch-sexp-queries.rst +++ b/doc/man7/notmuch-sexp-queries.rst @@ -21,7 +21,7 @@ build of notmuch supports it with :: - $ notmuch config get built_with.sexpr_query + $ notmuch config get built_with.sexp_queries S-EXPRESSIONS @@ -31,10 +31,12 @@ An *s-expression* is either an atom, or list of whitespace delimited s-expressions inside parentheses. Atoms are either *basic value* + A basic value is an unquoted string containing no whitespace, double quotes, or parentheses. *quoted string* + Double quotes (") delimit strings possibly containing whitespace or parentheses. These can contain double quote characters by escaping with backslash. E.g. ``"this is a quote \""``. @@ -48,9 +50,11 @@ a *field*, *logical operation*, or *modifier*, and 0 or more subqueries. ``*`` + "*" matches any non-empty string in the current field. ``()`` + The empty list matches all messages *term* @@ -62,19 +66,23 @@ subqueries. phrase splitting see :any:`fields`. ``(`` *field* |q1| |q2| ... |qn| ``)`` + Restrict the queries |q1| to |qn| to *field*, and combine with *and* (for most fields) or *or*. See :any:`fields` for more information. ``(`` *operator* |q1| |q2| ... |qn| ``)`` + Combine queries |q1| to |qn|. Currently supported operators are ``and``, ``or``, and ``not``. ``(not`` |q1| ... |qn| ``)`` is equivalent to ``(and (not`` |q1| ``) ... (not`` |qn| ``))``. ``(`` *modifier* |q1| |q2| ... |qn| ``)`` + Combine queries |q1| to |qn|, and reinterpret the result (e.g. as a regular expression). See :any:`modifiers` for more information. ``(macro (`` |p1| ... |pn| ``) body)`` + Define saved query with parameter substitution. The syntax is recognized only in saved s-expression queries (see ``squery.*`` in :any:`notmuch-config(1)`). Parameter names in ``body`` must be @@ -164,26 +172,31 @@ MODIFIERS that are neither operators nor fields. ``(infix`` *atom* ``)`` + Interpret *atom* as an infix notmuch query (see :any:`notmuch-search-terms(7)`). Not supported inside fields. ``(matching`` |q1| |q2| ... |qn| ``)`` ``(of`` |q1| |q2| ... |qn| ``)`` + Match all messages have the same values of the current field as those matching all of |q1| ... |qn|. Supported in most term [#not-path]_ or phrase fields. Most commonly used in the ``thread`` field. ``(query`` *atom* ``)`` + Expand to the saved query named by *atom*. See :any:`notmuch-config(1)` for more. Note that the saved query must be in infix syntax (:any:`notmuch-search-terms(7)`). Not supported inside fields. ``(regex`` *atom* ``)`` ``(rx`` *atom* ``)`` + Interpret *atom* as a POSIX.2 regular expression (see :manpage:`regex(7)`). This applies in term fields and a subset [#not-phrase]_ of phrase fields (see :any:`field-table`). ``(starts-with`` *subword* ``)`` + Matches any term starting with *subword*. This applies in either phrase or term :any:`fields `, or outside of fields [#not-body]_. Note that a ``starts-with`` query cannot be part of a phrase. The @@ -193,63 +206,80 @@ EXAMPLES ======== ``Wizard`` + Match all messages containing the word "wizard", ignoring case. ``added`` + Match all messages containing "added", but also those containing "add", "additional", "Additional", "adds", etc... via stemming. ``(and Bob Marley)`` + Match messages containing words "Bob" and "Marley", or their stems The words need not be adjacent. ``(not Bob Marley)`` + Match messages containing neither "Bob" nor "Marley", nor their stems, ``"quick fox"`` ``quick-fox`` ``quick@fox`` + Match the *phrase* "quick" followed by "fox" in phrase fields (or outside a field). Match the literal string in a term field. ``(folder (of (id 1234@invalid)))`` + Match any message in the same folder as the one with Message-Id "1234@invalid" ``(id 1234@invalid blah@test)`` + Matches Message-Id "1234@invalid" *or* Message-Id "blah@test" ``(and (infix "date:2009-11-18..2009-11-18") (tag unread))`` + Match messages in the given date range with tag unread. ``(starts-with prelim)`` + Match any words starting with "prelim". ``(subject quick "brown fox")`` + Match messages whose subject contains "quick" (anywhere, stemmed) and the phrase "brown fox". ``(subject (starts-with prelim))`` + Matches any word starting with "prelim", inside a message subject. ``(subject (starts-wih quick) "brown fox")`` + Match messages whose subject contains "quick brown fox", but also "brown fox quicksand". ``(thread (of (id 1234@invalid)))`` + Match any message in the same thread as the one with Message-Id "1234@invalid" ``(thread (matching (from bob@example.com) (to bob@example.com)))`` + Match any (messages in) a thread containing a message from "bob@example.com" and a (possibly distinct) message to "bob at example.com") ``(to (or bob@example.com mallory@example.org))`` ``(or (to bob@example.com) (to mallory@example.org))`` + Match in the "To" or "Cc" headers, "bob@example.com", "mallory@example.org", and also "bob@example.com.au" since it contains the adjacent triple "bob", "example", "com". ``(not (to *))`` + Match messages with an empty or invalid 'To' and 'Cc' field. ``(List *)`` + Match messages with a non-empty List-Id header, assuming configuration ``index.header.List=List-Id`` diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst index 12ee25e5..22aee340 100644 --- a/doc/notmuch-emacs.rst +++ b/doc/notmuch-emacs.rst @@ -56,7 +56,7 @@ notmuch-hello key bindings ```` Move to the next widget (button or text entry field) -```` +```` Move to the previous widget. ```` diff --git a/emacs/Makefile.local b/emacs/Makefile.local index d1b320c3..0f1f0eb2 100644 --- a/emacs/Makefile.local +++ b/emacs/Makefile.local @@ -42,7 +42,7 @@ emacs_mua := $(dir)/notmuch-emacs-mua emacs_mua_desktop := $(dir)/notmuch-emacs-mua.desktop emacs_images := \ - $(srcdir)/$(dir)/notmuch-logo.png + $(srcdir)/$(dir)/notmuch-logo.svg emacs_bytecode = $(emacs_sources:.el=.elc) emacs_docstrings = $(emacs_sources:.el=.rsti) diff --git a/emacs/coolj.el b/emacs/coolj.el index d820525b..79d2a1b7 100644 --- a/emacs/coolj.el +++ b/emacs/coolj.el @@ -45,7 +45,7 @@ Otherwise respect `fill-column'." :group 'coolj :type 'boolean) -(defcustom coolj-line-prefix-regexp "^\\(>+ \\)*" +(defcustom coolj-line-prefix-regexp "^\\(>+ ?\\)*" "Regular expression that matches line prefixes." :group 'coolj :type 'regexp) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 71487bd9..fc007c4c 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -198,7 +198,7 @@ fields of the search." (defvar notmuch-hello-indent 4 "How much to indent non-headers.") -(defimage notmuch-hello-logo ((:type png :file "notmuch-logo.png"))) +(defimage notmuch-hello-logo ((:type svg :file "notmuch-logo.svg"))) (defcustom notmuch-show-logo t "Should the notmuch logo be shown?" @@ -702,7 +702,6 @@ with `notmuch-hello-query-counts'." ;; that when we modify map it does not modify widget-keymap). (let ((map (make-composed-keymap (list (make-sparse-keymap) widget-keymap)))) (set-keymap-parent map notmuch-common-keymap) - (define-key map (kbd "") 'widget-backward) map) "Keymap for \"notmuch hello\" buffers.") diff --git a/emacs/notmuch-logo.svg b/emacs/notmuch-logo.svg new file mode 100644 index 00000000..2c65a73b --- /dev/null +++ b/emacs/notmuch-logo.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el index 536315e9..145f309f 100644 --- a/emacs/notmuch-tag.el +++ b/emacs/notmuch-tag.el @@ -429,17 +429,9 @@ initial input in the minibuffer." (set-keymap-parent map crm-local-completion-map) (define-key map " " 'self-insert-command) map))) - (delete "" (completing-read-multiple - prompt - ;; Append the separator to each completion so when the - ;; user completes a tag they can immediately begin - ;; entering another. `completing-read-multiple' - ;; ultimately splits the input on crm-separator, so we - ;; don't need to strip this back off (we just need to - ;; delete "empty" entries caused by trailing spaces). - (mapcar (lambda (tag-op) (concat tag-op crm-separator)) tag-list) - nil nil initial-input - 'notmuch-read-tag-changes-history)))) + (completing-read-multiple prompt tag-list + nil nil initial-input + 'notmuch-read-tag-changes-history))) ;;; Tagging diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el index 001a367d..d7486904 100644 --- a/emacs/notmuch-tree.el +++ b/emacs/notmuch-tree.el @@ -179,7 +179,7 @@ Note that the author string should not contain whitespace (:foreground "dark blue")) (t (:bold t))) - "Face used in tree mode for the date in messages matching the query." + "Face used in tree mode for the author in messages matching the query." :group 'notmuch-tree :group 'notmuch-faces) @@ -236,7 +236,7 @@ Note that the author string should not contain whitespace (defface notmuch-tree-no-match-author-face nil - "Face used in tree mode for the date in messages matching the query." + "Face used in tree mode for non-matching authors." :group 'notmuch-tree :group 'notmuch-faces) @@ -1206,6 +1206,9 @@ The arguments are: (defun notmuch-unthreaded (&optional query query-context target buffer-name open-target) + "Display threads matching QUERY in unthreaded view. + +See function NOTMUCH-TREE for documentation of the arguments" (interactive) (notmuch-tree query query-context target buffer-name open-target t)) diff --git a/emacs/notmuch.el b/emacs/notmuch.el index 2ef67c0e..85a54706 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -535,12 +535,12 @@ thread." (message "End of search results.")))) (defun notmuch-tree-from-search-current-query () - "Call notmuch tree with the current query." + "Tree view of current query." (interactive) (notmuch-tree notmuch-search-query-string)) (defun notmuch-unthreaded-from-search-current-query () - "Call notmuch tree with the current query." + "Unthreaded view of current query." (interactive) (notmuch-unthreaded notmuch-search-query-string)) @@ -880,6 +880,14 @@ sets the :orig-tag property." (setq notmuch-search-target-thread "found") (goto-char pos)))) +(defvar-local notmuch--search-hook-run nil + "Flag used to ensure the notmuch-search-hook is only run once per buffer") + +(defun notmuch--search-hook-wrapper () + (unless notmuch--search-hook-run + (setq notmuch--search-hook-run t) + (run-hooks 'notmuch-search-hook))) + (defun notmuch-search-process-filter (proc string) "Process and filter the output of \"notmuch search\"." (let ((results-buf (process-buffer proc)) @@ -892,7 +900,9 @@ sets the :orig-tag property." (goto-char (point-max)) (insert string)) (notmuch-sexp-parse-partial-list 'notmuch-search-append-result - results-buf))))) + results-buf)) + (with-current-buffer results-buf + (notmuch--search-hook-wrapper))))) ;;; Commands (and some helper functions used by them) @@ -1036,8 +1046,7 @@ the configured default sort order." (process-put proc 'parse-buf (generate-new-buffer " *notmuch search parse*")) (set-process-filter proc 'notmuch-search-process-filter) - (set-process-query-on-exit-flag proc nil)))) - (run-hooks 'notmuch-search-hook))) + (set-process-query-on-exit-flag proc nil)))))) (defun notmuch-search-refresh-view () "Refresh the current view. diff --git a/lib/built-with.c b/lib/built-with.c index 89958e12..275e72b8 100644 --- a/lib/built-with.c +++ b/lib/built-with.c @@ -32,7 +32,7 @@ notmuch_built_with (const char *name) return HAVE_XAPIAN_DB_RETRY_LOCK; } else if (STRNCMP_LITERAL (name, "session_key") == 0) { return true; - } else if (STRNCMP_LITERAL (name, "sexpr_query") == 0) { + } else if (STRNCMP_LITERAL (name, "sexp_queries") == 0) { return HAVE_SFSEXP; } else { return false; diff --git a/lib/config.cc b/lib/config.cc index e502858d..7a2882de 100644 --- a/lib/config.cc +++ b/lib/config.cc @@ -435,7 +435,7 @@ _notmuch_config_load_from_file (notmuch_database_t *notmuch, for (gchar **keys_p = keys; *keys_p; keys_p++) { char *absolute_key = talloc_asprintf (notmuch, "%s.%s", *grp, *keys_p); char *normalized_val; - val = g_key_file_get_value (file, *grp, *keys_p, NULL); + val = g_key_file_get_string (file, *grp, *keys_p, NULL); if (! val) { status = NOTMUCH_STATUS_FILE_ERROR; goto DONE; diff --git a/lib/database-private.h b/lib/database-private.h index 8dd77281..8133e364 100644 --- a/lib/database-private.h +++ b/lib/database-private.h @@ -160,7 +160,7 @@ operator&= (_notmuch_features &a, _notmuch_features b) /* * Configuration options for xapian database fields */ -typedef enum notmuch_field_flags { +typedef enum { NOTMUCH_FIELD_NO_FLAGS = 0, NOTMUCH_FIELD_EXTERNAL = 1 << 0, NOTMUCH_FIELD_PROBABILISTIC = 1 << 1, diff --git a/lib/database.cc b/lib/database.cc index 7eb0de79..6ef56d56 100644 --- a/lib/database.cc +++ b/lib/database.cc @@ -590,10 +590,12 @@ notmuch_database_compact (const char *path, notmuch_database_t *notmuch = NULL; char *message = NULL; - ret = notmuch_database_open_verbose (path, - NOTMUCH_DATABASE_MODE_READ_WRITE, - ¬much, - &message); + ret = notmuch_database_open_with_config (path, + NOTMUCH_DATABASE_MODE_READ_WRITE, + "", + NULL, + ¬much, + &message); if (ret) { if (status_cb) status_cb (message, closure); return ret; diff --git a/lib/indexopts.c b/lib/indexopts.c index 4a860858..2ffd1942 100644 --- a/lib/indexopts.c +++ b/lib/indexopts.c @@ -20,6 +20,10 @@ #include "notmuch-private.h" +struct _notmuch_indexopts { + _notmuch_crypto_t crypto; +}; + notmuch_indexopts_t * notmuch_database_get_default_indexopts (notmuch_database_t *db) { diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index 093c29b1..3cc79bc4 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -121,7 +121,7 @@ typedef enum { */ #define NOTMUCH_MESSAGE_ID_MAX (200 - sizeof (NOTMUCH_METADATA_THREAD_ID_PREFIX)) -typedef enum _notmuch_private_status { +typedef enum { /* First, copy all the public status values. */ NOTMUCH_PRIVATE_STATUS_SUCCESS = NOTMUCH_STATUS_SUCCESS, NOTMUCH_PRIVATE_STATUS_OUT_OF_MEMORY = NOTMUCH_STATUS_OUT_OF_MEMORY, @@ -173,7 +173,7 @@ typedef enum _notmuch_private_status { (notmuch_status_t) private_status) /* Flags shared by various lookup functions. */ -typedef enum _notmuch_find_flags { +typedef enum { /* Lookup without creating any documents. This is the default * behavior. */ NOTMUCH_FIND_LOOKUP = 0, @@ -711,9 +711,7 @@ _notmuch_thread_create (void *ctx, /* indexopts.c */ -struct _notmuch_indexopts { - _notmuch_crypto_t crypto; -}; +struct _notmuch_indexopts; #define CONFIG_HEADER_PREFIX "index.header." diff --git a/lib/notmuch.h b/lib/notmuch.h index 5c5a024e..1b2bdf3f 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -112,7 +112,7 @@ typedef int notmuch_bool_t; * A zero value (NOTMUCH_STATUS_SUCCESS) indicates that the function * completed without error. Any other value indicates an error. */ -typedef enum _notmuch_status { +typedef enum { /** * No error occurred. */ @@ -323,7 +323,7 @@ typedef enum { * config_path="" and error_message=NULL * @deprecated Deprecated as of libnotmuch 5.4 (notmuch 0.32) */ -/* NOTMUCH_DEPRECATED(5, 4) */ +NOTMUCH_DEPRECATED(5, 4) notmuch_status_t notmuch_database_open (const char *path, notmuch_database_mode_t mode, @@ -335,7 +335,7 @@ notmuch_database_open (const char *path, * @deprecated Deprecated as of libnotmuch 5.4 (notmuch 0.32) * */ -/* NOTMUCH_DEPRECATED(5, 4) */ +NOTMUCH_DEPRECATED(5, 4) notmuch_status_t notmuch_database_open_verbose (const char *path, notmuch_database_mode_t mode, @@ -1686,7 +1686,7 @@ notmuch_message_reindex (notmuch_message_t *message, /** * Message flags. */ -typedef enum _notmuch_message_flag { +typedef enum { NOTMUCH_MESSAGE_FLAG_MATCH, NOTMUCH_MESSAGE_FLAG_EXCLUDED, @@ -2532,7 +2532,7 @@ notmuch_config_list_destroy (notmuch_config_list_t *config_list); /** * Configuration keys known to libnotmuch */ -typedef enum _notmuch_config_key { +typedef enum { NOTMUCH_CONFIG_FIRST, NOTMUCH_CONFIG_DATABASE_PATH = NOTMUCH_CONFIG_FIRST, NOTMUCH_CONFIG_MAIL_ROOT, diff --git a/lib/open.cc b/lib/open.cc index 4dd62a9f..54510eac 100644 --- a/lib/open.cc +++ b/lib/open.cc @@ -19,9 +19,8 @@ notmuch_database_open (const char *path, char *status_string = NULL; notmuch_status_t status; - status = notmuch_database_open_verbose (path, mode, database, - &status_string); - + status = notmuch_database_open_with_config (path, mode, "", NULL, + database, &status_string); if (status_string) { fputs (status_string, stderr); free (status_string); @@ -199,7 +198,7 @@ _choose_database_path (void *ctx, } if (! *database_path && key_file) { - char *path = g_key_file_get_value (key_file, "database", "path", NULL); + char *path = g_key_file_get_string (key_file, "database", "path", NULL); if (path) { if (path[0] == '/') *database_path = talloc_strdup (ctx, path); @@ -643,7 +642,7 @@ notmuch_database_create_with_config (const char *database_path, if (key_file && ! split) { char *mail_root = notmuch_canonicalize_file_name ( - g_key_file_get_value (key_file, "database", "mail_root", NULL)); + g_key_file_get_string (key_file, "database", "mail_root", NULL)); char *db_path = notmuch_canonicalize_file_name (database_path); split = (mail_root && (0 != strcmp (mail_root, db_path))); diff --git a/notmuch-client.h b/notmuch-client.h index 96d81166..de318e1f 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -426,13 +426,13 @@ mime_node_seek_dfs (mime_node_t *node, int n); const _notmuch_message_crypto_t * mime_node_get_message_crypto_status (mime_node_t *node); -typedef enum dump_formats { +typedef enum { DUMP_FORMAT_AUTO, DUMP_FORMAT_BATCH_TAG, DUMP_FORMAT_SUP } dump_format_t; -typedef enum dump_includes { +typedef enum { DUMP_INCLUDE_TAGS = 1, DUMP_INCLUDE_CONFIG = 2, DUMP_INCLUDE_PROPERTIES = 4 @@ -499,11 +499,10 @@ int notmuch_minimal_options (const char *subcommand_name, struct _notmuch_client_indexing_cli_choices { int decrypt_policy; bool decrypt_policy_set; - notmuch_indexopts_t *opts; }; extern struct _notmuch_client_indexing_cli_choices indexing_cli_choices; extern const notmuch_opt_desc_t notmuch_shared_indexing_options []; notmuch_status_t -notmuch_process_shared_indexing_options (notmuch_database_t *notmuch); +notmuch_process_shared_indexing_options (notmuch_indexopts_t *opts); #endif diff --git a/notmuch-config.c b/notmuch-config.c index db00a26c..11d8d68b 100644 --- a/notmuch-config.c +++ b/notmuch-config.c @@ -680,9 +680,9 @@ _notmuch_config_list_built_with () printf ("%sretry_lock=%s\n", BUILT_WITH_PREFIX, notmuch_built_with ("retry_lock") ? "true" : "false"); - printf ("%ssexpr_query=%s\n", + printf ("%ssexp_queries=%s\n", BUILT_WITH_PREFIX, - notmuch_built_with ("sexpr_query") ? "true" : "false"); + notmuch_built_with ("sexp_queries") ? "true" : "false"); } static int diff --git a/notmuch-insert.c b/notmuch-insert.c index 72e2e35f..214d4d03 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -461,6 +461,8 @@ notmuch_insert_command (notmuch_database_t *notmuch, int argc, char *argv[]) char *maildir; char *newpath; int opt_index; + notmuch_indexopts_t *indexopts = notmuch_database_get_default_indexopts (notmuch); + void *local = talloc_new (NULL); notmuch_opt_desc_t options[] = { @@ -550,7 +552,7 @@ notmuch_insert_command (notmuch_database_t *notmuch, int argc, char *argv[]) return EXIT_FAILURE; } - status = notmuch_process_shared_indexing_options (notmuch); + status = notmuch_process_shared_indexing_options (indexopts); if (status != NOTMUCH_STATUS_SUCCESS) { fprintf (stderr, "Error: Failed to process index options. (%s)\n", notmuch_status_to_string (status)); @@ -558,7 +560,7 @@ notmuch_insert_command (notmuch_database_t *notmuch, int argc, char *argv[]) } /* Index the message. */ - status = add_file (notmuch, newpath, tag_ops, synchronize_flags, keep, indexing_cli_choices.opts); + status = add_file (notmuch, newpath, tag_ops, synchronize_flags, keep, indexopts); /* Commit changes. */ close_status = notmuch_database_close (notmuch); diff --git a/notmuch-new.c b/notmuch-new.c index b7a5f2ea..5b8fa340 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -45,6 +45,7 @@ typedef struct { const char *db_path; const char *mail_root; + notmuch_indexopts_t *indexopts; int output_is_a_tty; enum verbosity verbosity; bool debug; @@ -376,7 +377,7 @@ add_file (notmuch_database_t *notmuch, const char *filename, if (status) goto DONE; - status = notmuch_database_index_file (notmuch, filename, indexing_cli_choices.opts, &message); + status = notmuch_database_index_file (notmuch, filename, state->indexopts, &message); switch (status) { /* Success. */ case NOTMUCH_STATUS_SUCCESS: @@ -1150,6 +1151,8 @@ notmuch_new_command (notmuch_database_t *notmuch, int argc, char *argv[]) else if (verbose) add_files_state.verbosity = VERBOSITY_VERBOSE; + add_files_state.indexopts = notmuch_database_get_default_indexopts (notmuch); + add_files_state.new_tags = notmuch_config_get_values (notmuch, NOTMUCH_CONFIG_NEW_TAGS); if (print_status_database ( @@ -1217,7 +1220,7 @@ notmuch_new_command (notmuch_database_t *notmuch, int argc, char *argv[]) if (notmuch == NULL) return EXIT_FAILURE; - status = notmuch_process_shared_indexing_options (notmuch); + status = notmuch_process_shared_indexing_options (add_files_state.indexopts); if (status != NOTMUCH_STATUS_SUCCESS) { fprintf (stderr, "Error: Failed to process index options. (%s)\n", notmuch_status_to_string (status)); diff --git a/notmuch-reindex.c b/notmuch-reindex.c index 49eacd47..e9a65456 100644 --- a/notmuch-reindex.c +++ b/notmuch-reindex.c @@ -90,6 +90,7 @@ notmuch_reindex_command (notmuch_database_t *notmuch, int argc, char *argv[]) int opt_index; int ret; notmuch_status_t status; + notmuch_indexopts_t *indexopts = notmuch_database_get_default_indexopts (notmuch); /* Set up our handler for SIGINT */ memset (&action, 0, sizeof (struct sigaction)); @@ -110,7 +111,7 @@ notmuch_reindex_command (notmuch_database_t *notmuch, int argc, char *argv[]) notmuch_process_shared_options (notmuch, argv[0]); - status = notmuch_process_shared_indexing_options (notmuch); + status = notmuch_process_shared_indexing_options (indexopts); if (status != NOTMUCH_STATUS_SUCCESS) { fprintf (stderr, "Error: Failed to process index options. (%s)\n", notmuch_status_to_string (status)); @@ -128,7 +129,7 @@ notmuch_reindex_command (notmuch_database_t *notmuch, int argc, char *argv[]) return EXIT_FAILURE; } - ret = reindex_query (notmuch, query_string, indexing_cli_choices.opts); + ret = reindex_query (notmuch, query_string, indexopts); notmuch_database_destroy (notmuch); diff --git a/notmuch.c b/notmuch.c index 3fb58bf2..ac25ae18 100644 --- a/notmuch.c +++ b/notmuch.c @@ -141,21 +141,18 @@ const notmuch_opt_desc_t notmuch_shared_indexing_options [] = { notmuch_status_t -notmuch_process_shared_indexing_options (notmuch_database_t *notmuch) +notmuch_process_shared_indexing_options (notmuch_indexopts_t *opts) { - if (indexing_cli_choices.opts == NULL) - indexing_cli_choices.opts = notmuch_database_get_default_indexopts (notmuch); + if (opts == NULL) + return NOTMUCH_STATUS_NULL_POINTER; + if (indexing_cli_choices.decrypt_policy_set) { notmuch_status_t status; - if (indexing_cli_choices.opts == NULL) - return NOTMUCH_STATUS_OUT_OF_MEMORY; - status = notmuch_indexopts_set_decrypt_policy (indexing_cli_choices.opts, + status = notmuch_indexopts_set_decrypt_policy (opts, indexing_cli_choices.decrypt_policy); if (status != NOTMUCH_STATUS_SUCCESS) { fprintf (stderr, "Error: Failed to set index decryption policy to %d. (%s)\n", indexing_cli_choices.decrypt_policy, notmuch_status_to_string (status)); - notmuch_indexopts_destroy (indexing_cli_choices.opts); - indexing_cli_choices.opts = NULL; return status; } } diff --git a/test/T030-config.sh b/test/T030-config.sh index 3a585d1b..43bbce31 100755 --- a/test/T030-config.sh +++ b/test/T030-config.sh @@ -51,7 +51,7 @@ cat < EXPECTED built_with.compact=something built_with.field_processor=something built_with.retry_lock=something -built_with.sexpr_query=something +built_with.sexp_queries=something database.autocommit=8000 database.mail_root=MAIL_DIR database.path=MAIL_DIR @@ -67,6 +67,35 @@ user.primary_email=test_suite@notmuchmail.org EOF test_expect_equal_file EXPECTED OUTPUT +test_begin_subtest "Round trip config item with leading spaces" +test_subtest_known_broken +notmuch config set foo.bar " thing" +output=$(notmuch config get foo.bar) +test_expect_equal "${output}" " thing" + +test_begin_subtest "Round trip config item with leading tab" +test_subtest_known_broken +notmuch config set foo.bar " thing" +output=$(notmuch config get foo.bar) +test_expect_equal "${output}" " thing" + +test_begin_subtest "Round trip config item with embedded tab" +notmuch config set foo.bar "thing other" +output=$(notmuch config get foo.bar) +test_expect_equal "${output}" "thing other" + +test_begin_subtest "Round trip config item with embedded backslash" +notmuch config set foo.bar 'thing\other' +output=$(notmuch config get foo.bar) +test_expect_equal "${output}" "thing\other" + +test_begin_subtest "Round trip config item with embedded NL/CR" +notmuch config set foo.bar 'thing + other' +output=$(notmuch config get foo.bar) +test_expect_equal "${output}" "thing + other" + test_begin_subtest "Top level --config=FILE option" cp "${NOTMUCH_CONFIG}" alt-config notmuch --config=alt-config config set user.name "Another Name" diff --git a/test/T050-new.sh b/test/T050-new.sh index 1141c1e3..7ea127d3 100755 --- a/test/T050-new.sh +++ b/test/T050-new.sh @@ -329,6 +329,18 @@ notmuch config set new.tags "foo;;bar" output=$(NOTMUCH_NEW --quiet 2>&1) test_expect_equal "$output" "" +test_begin_subtest "leading/trailing whitespace in new.tags is ignored" +# avoid complications with leading spaces and "notmuch config" +sed -i 's/^tags=.*$/tags= fu bar ; ; bar /' notmuch-config +add_message +NOTMUCH_NEW --quiet +notmuch dump id:$gen_msg_id | sed 's/ --.*$//' > OUTPUT +cat <EXPECTED +#notmuch-dump batch-tag:3 config,properties,tags ++bar +fu%20bar +EOF +test_expect_equal_file EXPECTED OUTPUT + test_begin_subtest "Tags starting with '-' in new.tags are forbidden" notmuch config set new.tags "-foo;bar" output=$(NOTMUCH_NEW --debug 2>&1) @@ -368,31 +380,26 @@ chmod u+w ${MAIL_DIR}/.notmuch/xapian/*.* test_expect_equal "$output" "A Xapian exception occurred opening database" -test_begin_subtest "Handle files vanishing between scandir and add_file" +make_shim dif-shim< -# A file for scandir to find. It won't get indexed, so can be empty. -touch ${MAIL_DIR}/vanish +WRAP_DLFUNC(notmuch_status_t, notmuch_database_index_file, \ + (notmuch_database_t *database, const char *filename, notmuch_indexopts_t *indexopts, notmuch_message_t **message)) -# Breakpoint to remove the file before indexing -cat < notmuch-new-vanish.gdb -set breakpoint pending on -set logging file notmuch-new-vanish-gdb.log -set logging on -break notmuch_database_index_file -commands -shell rm -f ${MAIL_DIR}/vanish -continue -end -run + if (unlink ("${MAIL_DIR}/vanish")) { + fprintf (stderr, "unlink failed\n"); + exit (42); + } + return notmuch_database_index_file_orig (database, filename, indexopts, message); +} EOF -${TEST_GDB} --batch-silent --return-child-result -x notmuch-new-vanish.gdb \ - --args notmuch new 2>OUTPUT 1>/dev/null -echo "exit status: $?" >> OUTPUT - -# Clean up the file in case gdb isn't available. -rm -f ${MAIL_DIR}/vanish +test_begin_subtest "Handle files vanishing between scandir and add_file" +# A file for scandir to find. It won't get indexed, so can be empty. +touch ${MAIL_DIR}/vanish +notmuch_with_shim dif-shim new 2>OUTPUT 1>/dev/null +echo "exit status: $?" >> OUTPUT cat < EXPECTED Unexpected error with file ${MAIL_DIR}/vanish add_file: Something went wrong trying to read or write a file diff --git a/test/T051-new-renames.sh b/test/T051-new-renames.sh new file mode 100755 index 00000000..ebd06be1 --- /dev/null +++ b/test/T051-new-renames.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +test_description='"notmuch new" with directory renames' +. $(dirname "$0")/test-lib.sh || exit 1 + +for loop in {1..10}; do + +rm -rf ${MAIL_DIR} + +for i in {1..10}; do + generate_message '[dir]=foo' '[subject]="Message foo $i"' +done + +for i in {1..10}; do + generate_message '[dir]=bar' '[subject]="Message bar $i"' +done + +test_begin_subtest "Index the messages, round $loop" +output=$(NOTMUCH_NEW) +test_expect_equal "$output" "Added 20 new messages to the database." + +all_files=$(notmuch search --output=files \*) +count_foo=$(notmuch count folder:foo) + +test_begin_subtest "Rename folder" +mv ${MAIL_DIR}/foo ${MAIL_DIR}/baz +output=$(NOTMUCH_NEW) +test_expect_equal "$output" "No new mail. Detected $count_foo file renames." + +test_begin_subtest "Rename folder back" +mv ${MAIL_DIR}/baz ${MAIL_DIR}/foo +output=$(NOTMUCH_NEW) +test_expect_equal "$output" "No new mail. Detected $count_foo file renames." + +test_begin_subtest "Files remain the same" +output=$(notmuch search --output=files \*) +test_expect_equal "$output" "$all_files" + +done + +test_done diff --git a/test/T055-path-config.sh b/test/T055-path-config.sh index b910e28e..1df240dd 100755 --- a/test/T055-path-config.sh +++ b/test/T055-path-config.sh @@ -277,7 +277,7 @@ EOF built_with.compact=something built_with.field_processor=something built_with.retry_lock=something -built_with.sexpr_query=something +built_with.sexp_queries=something database.autocommit=8000 database.backup_dir database.hook_dir diff --git a/test/T060-count.sh b/test/T060-count.sh index 6ad80df9..48146706 100755 --- a/test/T060-count.sh +++ b/test/T060-count.sh @@ -102,22 +102,25 @@ output=$(sed 's/^\(A Xapian exception [^:]*\):.*$/\1/' OUTPUT) test_expect_equal "${output}" "A Xapian exception occurred opening database" restore_database -cat < count-files.gdb -set breakpoint pending on -set logging file count-files-gdb.log -set logging on -break count_files -commands -shell cp /dev/null ${MAIL_DIR}/.notmuch/xapian/postlist.* -continue -end -run +make_shim qsm-shim< + +WRAP_DLFUNC (notmuch_status_t, notmuch_query_search_messages, (notmuch_query_t *query, notmuch_messages_t **messages)) + + /* XXX WARNING THIS CORRUPTS THE DATABASE */ + int fd = open ("target_postlist", O_WRONLY|O_TRUNC); + if (fd < 0) + exit (8); + close (fd); + + return notmuch_query_search_messages_orig(query, messages); +} EOF backup_database test_begin_subtest "error message from query_search_messages" -${TEST_GDB} --batch-silent --return-child-result -x count-files.gdb \ - --args notmuch count --output=files '*' 2>OUTPUT 1>/dev/null +ln -s ${MAIL_DIR}/.notmuch/xapian/postlist.* target_postlist +notmuch_with_shim qsm-shim count --output=files '*' 2>OUTPUT 1>/dev/null cat < EXPECTED notmuch count: A Xapian exception occurred A Xapian exception occurred performing query diff --git a/test/T070-insert.sh b/test/T070-insert.sh index 208deb1c..ec170b30 100755 --- a/test/T070-insert.sh +++ b/test/T070-insert.sh @@ -234,6 +234,18 @@ output=$(notmuch show --format=json id:$gen_msg_id) test_json_nodes <<<"$output" \ 'new_tags:[0][0][0]["tags"] = ["bar", "foo"]' +test_begin_subtest "leading/trailing whitespace in new.tags is ignored" +# avoid complications with leading spaces and "notmuch config" +sed -i 's/^tags=.*$/tags= fu bar ; ; bar /' notmuch-config +gen_insert_msg +notmuch insert < $gen_msg_filename +notmuch dump id:$gen_msg_id | sed 's/ --.*$//' > OUTPUT +cat <EXPECTED +#notmuch-dump batch-tag:3 config,properties,tags ++bar +fu%20bar +EOF +test_expect_equal_file EXPECTED OUTPUT + test_begin_subtest "Tags starting with '-' in new.tags are forbidden" notmuch config set new.tags "-foo;bar" gen_insert_msg diff --git a/test/T450-emacs-show.sh b/test/T450-emacs-show.sh index 4b5f5fde..057ad37e 100755 --- a/test/T450-emacs-show.sh +++ b/test/T450-emacs-show.sh @@ -220,7 +220,9 @@ test_emacs '(notmuch-show "id:basic-encrypted@crypto.notmuchmail.org") test_expect_equal_file $EXPECTED/notmuch-show-decrypted-message OUTPUT test_begin_subtest "show encrypted rfc822 message" -test_subtest_known_broken +if ${TEST_EMACS} --quick --batch --eval '(kill-emacs (if (version< emacs-version "28") 0 1))'; then + test_subtest_known_broken +fi test_emacs '(notmuch-show "id:encrypted-rfc822-attachment@crypto.notmuchmail.org") (test-visible-output)' test_expect_code 1 'fgrep "!!!" OUTPUT' diff --git a/test/T562-lib-database.sh b/test/T562-lib-database.sh index 769fe86e..2314efd2 100755 --- a/test/T562-lib-database.sh +++ b/test/T562-lib-database.sh @@ -9,10 +9,8 @@ test_begin_subtest "building database" test_expect_success "NOTMUCH_NEW" cat < c_head -#include -#include #include -#include + int main (int argc, char** argv) { notmuch_database_t *db; @@ -82,7 +80,7 @@ cat < EXPECTED == stdout == 0 == stderr == -A Xapian exception occurred at lib/database.cc:XXX: Database has been closed +A Xapian exception occurred at database.cc:XXX: Database has been closed EOF test_expect_equal_file EXPECTED OUTPUT @@ -147,7 +145,7 @@ cat < EXPECTED == stdout == 1 == stderr == -A Xapian exception occurred at lib/database.cc:XXX: Database has been closed +A Xapian exception occurred at database.cc:XXX: Database has been closed EOF test_expect_equal_file EXPECTED OUTPUT diff --git a/test/T563-lib-directory.sh b/test/T563-lib-directory.sh index 28325ff2..ebd7fcb2 100755 --- a/test/T563-lib-directory.sh +++ b/test/T563-lib-directory.sh @@ -9,10 +9,8 @@ test_begin_subtest "building database" test_expect_success "NOTMUCH_NEW" cat < c_head -#include -#include #include -#include + int main (int argc, char** argv) { notmuch_database_t *db; @@ -53,7 +51,7 @@ cat < EXPECTED == stdout == 1 == stderr == -A Xapian exception occurred at lib/directory.cc:XXX: Database has been closed +A Xapian exception occurred at directory.cc:XXX: Database has been closed EOF test_expect_equal_file EXPECTED OUTPUT @@ -70,7 +68,7 @@ cat < EXPECTED == stdout == 1 == stderr == -A Xapian exception occurred at lib/directory.cc:XXX: Database has been closed +A Xapian exception occurred at directory.cc:XXX: Database has been closed EOF test_expect_equal_file EXPECTED OUTPUT diff --git a/test/T564-lib-query.sh b/test/T564-lib-query.sh index 50b0a88e..ff1d4984 100755 --- a/test/T564-lib-query.sh +++ b/test/T564-lib-query.sh @@ -9,10 +9,8 @@ test_begin_subtest "building database" test_expect_success "NOTMUCH_NEW" cat < c_head -#include -#include #include -#include + int main (int argc, char** argv) { notmuch_database_t *db; diff --git a/test/T566-lib-message.sh b/test/T566-lib-message.sh index ee55ef29..8b61d182 100755 --- a/test/T566-lib-message.sh +++ b/test/T566-lib-message.sh @@ -19,9 +19,8 @@ cat <<'EOF' > c_tail EOF cat < c_head0 -#include -#include #include + int main (int argc, char** argv) { notmuch_database_t *db; diff --git a/test/T568-lib-thread.sh b/test/T568-lib-thread.sh index 088e66dd..b45836cd 100755 --- a/test/T568-lib-thread.sh +++ b/test/T568-lib-thread.sh @@ -24,9 +24,8 @@ cat <<'EOF' > c_tail EOF cat < c_head -#include -#include #include + int main (int argc, char** argv) { notmuch_database_t *db; diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh index 9fa51fc0..eb303444 100755 --- a/test/T590-libconfig.sh +++ b/test/T590-libconfig.sh @@ -23,8 +23,6 @@ EOF } cat < c_head -#include -#include #include int main (int argc, char** argv) @@ -272,6 +270,29 @@ EOF test_expect_equal_file EXPECTED OUTPUT restore_database +test_begin_subtest "notmuch_config_get_values (ignore leading/trailing whitespace)" +cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL% +{ + notmuch_config_values_t *values; + EXPECT0(notmuch_config_set (db, NOTMUCH_CONFIG_NEW_TAGS, " a ; b c ; d ")); + for (values = notmuch_config_get_values (db, NOTMUCH_CONFIG_NEW_TAGS); + notmuch_config_values_valid (values); + notmuch_config_values_move_to_next (values)) + { + puts (notmuch_config_values_get (values)); + } +} +EOF +cat <<'EOF' >EXPECTED +== stdout == +a +b c +d +== stderr == +EOF +test_expect_equal_file EXPECTED OUTPUT +restore_database + test_begin_subtest "notmuch_config_get_values_string" cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL% { @@ -616,8 +637,6 @@ cp notmuch-config.bak notmuch-config test_expect_equal_file EXPECTED OUTPUT cat < c_head2 -#include -#include #include int main (int argc, char** argv) diff --git a/test/T595-reopen.sh b/test/T595-reopen.sh index 7375e2ac..1a517423 100755 --- a/test/T595-reopen.sh +++ b/test/T595-reopen.sh @@ -6,8 +6,6 @@ test_description="library reopen API" add_email_corpus cat < c_head -#include -#include #include int main (int argc, char** argv) diff --git a/test/T610-message-property.sh b/test/T610-message-property.sh index d0e52f4a..4ec85474 100755 --- a/test/T610-message-property.sh +++ b/test/T610-message-property.sh @@ -6,10 +6,6 @@ test_description="message property API" add_email_corpus cat < c_head -#include -#include -#include -#include #include void print_properties (notmuch_message_t *message, const char *prefix, notmuch_bool_t exact) { diff --git a/test/T620-lock.sh b/test/T620-lock.sh index 7aaaff2a..8f4c380f 100755 --- a/test/T620-lock.sh +++ b/test/T620-lock.sh @@ -9,9 +9,6 @@ if [ $NOTMUCH_HAVE_XAPIAN_DB_RETRY_LOCK -ne 1 ]; then test_subtest_known_broken fi test_C ${MAIL_DIR} <<'EOF' -#include -#include -#include #include void diff --git a/test/T640-database-modified.sh b/test/T640-database-modified.sh index 274105c7..636b20c7 100755 --- a/test/T640-database-modified.sh +++ b/test/T640-database-modified.sh @@ -10,11 +10,8 @@ test_begin_subtest "catching DatabaseModifiedError in _notmuch_message_ensure_me first_id=$(notmuch search --output=messages '*'| head -1 | sed s/^id://) test_C ${MAIL_DIR} < -#include #include -#include -#include + int main (int argc, char **argv) { diff --git a/test/notmuch-test.h b/test/notmuch-test.h index 34dbb8e0..ed713099 100644 --- a/test/notmuch-test.h +++ b/test/notmuch-test.h @@ -1,7 +1,21 @@ #ifndef _NOTMUCH_TEST_H #define _NOTMUCH_TEST_H +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include #include #include +#include +#include +#include +#include +#include +#include + #include inline static void @@ -14,4 +28,23 @@ expect0 (int line, notmuch_status_t ret) } #define EXPECT0(v) expect0 (__LINE__, v); + +inline static void * +dlsym_next (const char *symbol) +{ + void *sym = dlsym (RTLD_NEXT, symbol); + char *str = dlerror (); + + if (str != NULL) { + fprintf (stderr, "finding symbol '%s' failed: %s", symbol, str); + exit (77); + } + return sym; +} + +#define WRAP_DLFUNC(_rtype, _func, _args) \ + _rtype _func _args; \ + _rtype _func _args { \ + static _rtype (*_func##_orig) _args = NULL; \ + if (! _func##_orig ) *(void **) (&_func##_orig) = dlsym_next (#_func); #endif diff --git a/test/test-lib.sh b/test/test-lib.sh index e476a69b..6bc0b723 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -529,7 +529,7 @@ notmuch_debug_sanitize () { } notmuch_exception_sanitize () { - perl -pe 's/(A Xapian exception occurred at .*[.]cc?):([0-9]*)/\1:XXX/' + perl -pe 's,(A Xapian exception occurred at) .*?([^/]*[.]cc?):([0-9]*),\1 \2:XXX,' } notmuch_search_sanitize () { diff --git a/util/hex-escape.h b/util/hex-escape.h index 8703334c..83a4c6f1 100644 --- a/util/hex-escape.h +++ b/util/hex-escape.h @@ -5,7 +5,7 @@ extern "C" { #endif -typedef enum hex_status { +typedef enum { HEX_SUCCESS = 0, HEX_SYNTAX_ERROR, HEX_OUT_OF_MEMORY diff --git a/util/string-util.c b/util/string-util.c index 9c46a81a..03d7648d 100644 --- a/util/string-util.c +++ b/util/string-util.c @@ -42,13 +42,15 @@ const char * strsplit_len (const char *s, char delim, size_t *len) { bool escaping = false; - size_t count = 0; + size_t count = 0, last_nonspace = 0; - /* Skip initial unescaped delimiters */ - while (*s && *s == delim) + /* Skip initial unescaped delimiters and whitespace */ + while (*s && (*s == delim || isspace (*s))) s++; while (s[count] && (escaping || s[count] != delim)) { + if (! isspace (s[count])) + last_nonspace = count; escaping = (s[count] == '\\'); count++; } @@ -56,7 +58,7 @@ strsplit_len (const char *s, char delim, size_t *len) if (count == 0) return NULL; - *len = count; + *len = last_nonspace + 1; return s; }