mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-29 14:14:12 +01:00
notmuch 0.35 release
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEkiyHYXwaY0SiY6fqA0U5G1WqFSEFAmIAAxEACgkQA0U5G1Wq FSGIdw//aytmkD3YaI0jT9Q7JjvkChMjGYzP0KeVlJrSIjNu+tkIoMSFayPzR1Zg f6nQ6K/c8NDJROQYFsjDBltnY2cwC1DxWMN9infr80bJhHYQlrACzeBKrGGIho44 QceWgPW054GqYHsKozGNxZVlgKLeDImj2dX3E0scNYtVuhsyVO9x4Eb2xi6oDRze HvnpiKoE8zkwObK9REjwNG1n1dVmvSZ+H25akcb3siiwKFLNIwcPAYIMiSFaBsNe vwwJaUhZP6TnE+54QX03ssLFT5Dlm/d+YOT4EPAujRwGaLlaUsK04KHbyT/wWbgK wW5AUsOL8zTjQz5sg8+v90DRFlamRg8SK8piTJo+Dx5Lsjpqk5PgLG7DJ0WeTaxJ 35Bph1/5mnUWwi2dsNeJ11rK0vamouSsatF+VFScWxesLhsUhzFFt20VfiiYXxVQ t4mqH/aHitbbzqy3y0vwIj+USdIfskJyncgXKjNkwEMJuh25Sg815ilnvNXMWbv+ 7byXnxNpaDaLNO1h/2KYYbz+WGFU8fsLUp/O3WtITzIZms3gddnP2GNk55/B8Jfq 9zcNuljrUNlY3zJvXgiRj/7jCWiLevF0AMOpc1EmFmp0LLISkH+VdIVXIyLb06Y/ bj5QDYTtXLZViZ9T6rw5QlLtNAv25ZTmbV0nOK97c3Jfwt6QRdA= =7kSG -----END PGP SIGNATURE----- Merge tag '0.35' into debian/bullseye-backports notmuch 0.35 release
This commit is contained in:
commit
f1b2ab70c3
110 changed files with 1580 additions and 405 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -16,5 +16,6 @@
|
||||||
/sh.config
|
/sh.config
|
||||||
/sphinx.config
|
/sphinx.config
|
||||||
/version.stamp
|
/version.stamp
|
||||||
|
/bindings/python-cffi/_notmuch_config.py
|
||||||
TAGS
|
TAGS
|
||||||
tags
|
tags
|
||||||
|
|
|
@ -50,9 +50,9 @@ DETACHED_SIG_FILE=$(TAR_FILE).asc
|
||||||
PV_FILE=bindings/python/notmuch/version.py
|
PV_FILE=bindings/python/notmuch/version.py
|
||||||
|
|
||||||
# Smash together user's values with our extra values
|
# Smash together user's values with our extra values
|
||||||
FINAL_CFLAGS = -DNOTMUCH_VERSION=$(VERSION) $(CPPFLAGS) $(CFLAGS) $(WARN_CFLAGS) $(extra_cflags) $(CONFIGURE_CFLAGS)
|
FINAL_CFLAGS = -DNOTMUCH_VERSION=$(VERSION) $(WARN_CFLAGS) $(extra_cflags) $(CPPFLAGS) $(CONFIGURE_CFLAGS) $(CFLAGS)
|
||||||
FINAL_CXXFLAGS = $(CPPFLAGS) $(CXXFLAGS) $(WARN_CXXFLAGS) $(extra_cflags) $(extra_cxxflags) $(CONFIGURE_CXXFLAGS)
|
FINAL_CXXFLAGS = $(WARN_CXXFLAGS) $(extra_cflags) $(extra_cxxflags) $(CPPFLAGS) $(CONFIGURE_CXXFLAGS) $(CXXFLAGS)
|
||||||
FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Lutil -lnotmuch_util -Llib -lnotmuch
|
FINAL_NOTMUCH_LDFLAGS = -Lutil -lnotmuch_util -Llib -lnotmuch $(LDFLAGS)
|
||||||
ifeq ($(LIBDIR_IN_LDCONFIG),0)
|
ifeq ($(LIBDIR_IN_LDCONFIG),0)
|
||||||
FINAL_NOTMUCH_LDFLAGS += $(RPATH_LDFLAGS)
|
FINAL_NOTMUCH_LDFLAGS += $(RPATH_LDFLAGS)
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -54,7 +54,6 @@ update-versions:
|
||||||
sed -i -e "s/^__VERSION__[[:blank:]]*=.*$$/__VERSION__ = \'${VERSION}\'/" \
|
sed -i -e "s/^__VERSION__[[:blank:]]*=.*$$/__VERSION__ = \'${VERSION}\'/" \
|
||||||
-e "s/^SOVERSION[[:blank:]]*=.*$$/SOVERSION = \'${LIBNOTMUCH_VERSION_MAJOR}\'/" \
|
-e "s/^SOVERSION[[:blank:]]*=.*$$/SOVERSION = \'${LIBNOTMUCH_VERSION_MAJOR}\'/" \
|
||||||
${PV_FILE}
|
${PV_FILE}
|
||||||
cp version.txt bindings/python-cffi
|
|
||||||
|
|
||||||
# We invoke make recursively only to force ordering of our phony
|
# We invoke make recursively only to force ordering of our phony
|
||||||
# targets in the case of parallel invocation of make (-j).
|
# targets in the case of parallel invocation of make (-j).
|
||||||
|
|
106
NEWS
106
NEWS
|
@ -1,3 +1,109 @@
|
||||||
|
Notmuch 0.35 (2022-02-06)
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Library
|
||||||
|
-------
|
||||||
|
|
||||||
|
Implement the `date` and `lastmod` fields in the S-expression parser.
|
||||||
|
|
||||||
|
Ignore trailing `/` for pathnames in both query parsers.
|
||||||
|
|
||||||
|
Rename configuration option `built_with.sexpr_query` to
|
||||||
|
`built_with.sexp_queries`.
|
||||||
|
|
||||||
|
Do not assume a default mail root in split (e.g. XDG) configurations.
|
||||||
|
|
||||||
|
Fix some small memory leaks in `notmuch_database_open_with_config`.
|
||||||
|
|
||||||
|
CLI
|
||||||
|
---
|
||||||
|
|
||||||
|
Improve handling of leading/trailing punctation and space for
|
||||||
|
configuration lists.
|
||||||
|
|
||||||
|
Only ignore `.notmuch` at the top level in `notmuch new`.
|
||||||
|
|
||||||
|
Optionally show extra headers in `notmuch show`. See
|
||||||
|
`show.extra_headers` in notmuch-config(1).
|
||||||
|
|
||||||
|
Emacs
|
||||||
|
-----
|
||||||
|
|
||||||
|
Drop `C-TAB` binding in hello mode, document `backtab`.
|
||||||
|
|
||||||
|
Fix visual glitch in search mode by running `notmuch-search-hook`
|
||||||
|
lazily.
|
||||||
|
|
||||||
|
Don't add space to completion candidates, improves compatibility with
|
||||||
|
third party completion frameworks.
|
||||||
|
|
||||||
|
Make citation formating more robust against whitespace.
|
||||||
|
|
||||||
|
Use `--excludes=false` when generating the 'All tags' section.
|
||||||
|
|
||||||
|
Use cached copy of message body for `Fcc`, avoiding variant bodies for
|
||||||
|
signed and/or encrypted messages.
|
||||||
|
|
||||||
|
Add notmuch-logo.svg and use it in notmuch-hello view, replacing
|
||||||
|
the .png version.
|
||||||
|
|
||||||
|
Make header line in show buffers optional.
|
||||||
|
|
||||||
|
Add customizable names for search buffers.
|
||||||
|
|
||||||
|
Build
|
||||||
|
-----
|
||||||
|
|
||||||
|
Fix out-of-tree build for `python-cffi` bindings.
|
||||||
|
|
||||||
|
Rearrange position of {C,CXX,CPP,LD}FLAGS, prevent some clashes with
|
||||||
|
installed version of notmuch.
|
||||||
|
|
||||||
|
Ignore more configure options.
|
||||||
|
|
||||||
|
Test Suite
|
||||||
|
----------
|
||||||
|
|
||||||
|
Replace some uses of `gdb` in the test suite with `LD_PRELOAD` based
|
||||||
|
shims.
|
||||||
|
|
||||||
|
Use `--with-colons` for gpgsm, fix compatibility with newer gnupg.
|
||||||
|
|
||||||
|
Python bindings
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Add `matched` property to message objects.
|
||||||
|
|
||||||
|
Users are reminded that the old python bindings in bindings/python are
|
||||||
|
deprecated; this will probably be the last major release that ships
|
||||||
|
them.
|
||||||
|
|
||||||
|
Completion
|
||||||
|
----------
|
||||||
|
|
||||||
|
Use `database.mail_root` for path completion in bash/zsh.
|
||||||
|
|
||||||
|
Notmuch 0.34.3 (2022-01-09)
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Library
|
||||||
|
-------
|
||||||
|
|
||||||
|
Do not crash when presented with a .notmuch directory without a
|
||||||
|
xapian/ subdirectory.
|
||||||
|
|
||||||
|
Python Bindings (notmuch2)
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Database constructor now searches for configuration by default. Pass
|
||||||
|
`config=Database.CONFIG.EMPTY` to disable.
|
||||||
|
|
||||||
|
The `Message.replies()` method now returns OwnedMessage objects, to
|
||||||
|
prevent certain memory de-allocation errors.
|
||||||
|
|
||||||
|
Fix for importing `notmuch2` module when building bindings
|
||||||
|
documentation.
|
||||||
|
|
||||||
Notmuch 0.34.2 (2021-12-09)
|
Notmuch 0.34.2 (2021-12-09)
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
|
|
@ -3,21 +3,26 @@
|
||||||
dir := bindings
|
dir := bindings
|
||||||
|
|
||||||
# force the shared library to be built
|
# 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)
|
ifeq ($(HAVE_RUBY_DEV),1)
|
||||||
cd $(dir)/ruby && \
|
cd $(dir)/ruby && \
|
||||||
EXTRA_LDFLAGS="$(NO_UNDEFINED_LDFLAGS)" \
|
EXTRA_LDFLAGS="$(NO_UNDEFINED_LDFLAGS)" \
|
||||||
LIBNOTMUCH="../../lib/$(LINKER_NAME)" \
|
LIBNOTMUCH="../../lib/$(LINKER_NAME)" \
|
||||||
NOTMUCH_SRCDIR='$(NOTMUCH_SRCDIR)' \
|
NOTMUCH_SRCDIR='$(NOTMUCH_SRCDIR)' \
|
||||||
$(RUBY) extconf.rb --vendor
|
$(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
|
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)
|
ifeq ($(HAVE_PYTHON3_CFFI),1)
|
||||||
cd $(dir)/python-cffi && \
|
cd $(dir)/python-cffi && \
|
||||||
${PYTHON} setup.py build --build-lib build/stage && \
|
${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
|
endif
|
||||||
|
|
||||||
CLEAN += $(patsubst %,$(dir)/ruby/%, \
|
CLEAN += $(patsubst %,$(dir)/ruby/%, \
|
||||||
|
@ -26,6 +31,6 @@ CLEAN += $(patsubst %,$(dir)/ruby/%, \
|
||||||
init.o message.o messages.o mkmf.log notmuch.so query.o \
|
init.o message.o messages.o mkmf.log notmuch.so query.o \
|
||||||
status.o tags.o thread.o threads.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
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import cffi
|
import cffi
|
||||||
|
from _notmuch_config import *
|
||||||
|
|
||||||
ffibuilder = cffi.FFI()
|
ffibuilder = cffi.FFI()
|
||||||
ffibuilder.set_source(
|
ffibuilder.set_source(
|
||||||
|
@ -16,8 +16,8 @@ ffibuilder.set_source(
|
||||||
#ERROR libnotmuch version < 5.1 not supported
|
#ERROR libnotmuch version < 5.1 not supported
|
||||||
#endif
|
#endif
|
||||||
""",
|
""",
|
||||||
include_dirs=['../../lib'],
|
include_dirs=[NOTMUCH_INCLUDE_DIR],
|
||||||
library_dirs=['../../lib'],
|
library_dirs=[NOTMUCH_LIB_DIR],
|
||||||
libraries=['notmuch'],
|
libraries=['notmuch'],
|
||||||
)
|
)
|
||||||
ffibuilder.cdef(
|
ffibuilder.cdef(
|
||||||
|
@ -54,6 +54,7 @@ ffibuilder.cdef(
|
||||||
NOTMUCH_STATUS_NO_DATABASE,
|
NOTMUCH_STATUS_NO_DATABASE,
|
||||||
NOTMUCH_STATUS_DATABASE_EXISTS,
|
NOTMUCH_STATUS_DATABASE_EXISTS,
|
||||||
NOTMUCH_STATUS_BAD_QUERY_SYNTAX,
|
NOTMUCH_STATUS_BAD_QUERY_SYNTAX,
|
||||||
|
NOTMUCH_STATUS_NO_MAIL_ROOT,
|
||||||
NOTMUCH_STATUS_LAST_STATUS
|
NOTMUCH_STATUS_LAST_STATUS
|
||||||
} notmuch_status_t;
|
} notmuch_status_t;
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -139,7 +139,7 @@ class Database(base.NotmuchObject):
|
||||||
path = os.fsencode(path)
|
path = os.fsencode(path)
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def __init__(self, path=None, mode=MODE.READ_ONLY, config=CONFIG.EMPTY):
|
def __init__(self, path=None, mode=MODE.READ_ONLY, config=CONFIG.SEARCH):
|
||||||
if isinstance(mode, str):
|
if isinstance(mode, str):
|
||||||
mode = self.STR_MODE_MAP[mode]
|
mode = self.STR_MODE_MAP[mode]
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
|
|
|
@ -205,6 +205,20 @@ class Message(base.NotmuchObject):
|
||||||
self._msg_p, capi.lib.NOTMUCH_MESSAGE_FLAG_EXCLUDED)
|
self._msg_p, capi.lib.NOTMUCH_MESSAGE_FLAG_EXCLUDED)
|
||||||
return bool(ret)
|
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
|
@property
|
||||||
def date(self):
|
def date(self):
|
||||||
"""The message date as an integer.
|
"""The message date as an integer.
|
||||||
|
@ -357,14 +371,14 @@ class Message(base.NotmuchObject):
|
||||||
This method will only work if the message was created from a
|
This method will only work if the message was created from a
|
||||||
thread. Otherwise it will yield no results.
|
thread. Otherwise it will yield no results.
|
||||||
|
|
||||||
:returns: An iterator yielding :class:`Message` instances.
|
:returns: An iterator yielding :class:`OwnedMessage` instances.
|
||||||
:rtype: MessageIter
|
:rtype: MessageIter
|
||||||
"""
|
"""
|
||||||
# The notmuch_messages_valid call accepts NULL and this will
|
# The notmuch_messages_valid call accepts NULL and this will
|
||||||
# become an empty iterator, raising StopIteration immediately.
|
# become an empty iterator, raising StopIteration immediately.
|
||||||
# Hence no return value checking here.
|
# Hence no return value checking here.
|
||||||
msgs_p = capi.lib.notmuch_message_get_replies(self._msg_p)
|
msgs_p = capi.lib.notmuch_message_get_replies(self._msg_p)
|
||||||
return MessageIter(self, msgs_p, db=self._db)
|
return MessageIter(self, msgs_p, db=self._db, msg_cls=OwnedMessage)
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self.messageid)
|
return hash(self.messageid)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import setuptools
|
import setuptools
|
||||||
|
from _notmuch_config import *
|
||||||
|
|
||||||
with open('version.txt') as fp:
|
with open(NOTMUCH_VERSION_FILE) as fp:
|
||||||
VERSION = fp.read().strip()
|
VERSION = fp.read().strip()
|
||||||
|
|
||||||
setuptools.setup(
|
setuptools.setup(
|
||||||
|
|
|
@ -23,9 +23,9 @@ class TestIter:
|
||||||
|
|
||||||
def test_set_get(self, maildir):
|
def test_set_get(self, maildir):
|
||||||
# Ensure get-set works from different db objects
|
# Ensure get-set works from different db objects
|
||||||
with dbmod.Database.create(maildir.path) as db0:
|
with dbmod.Database.create(maildir.path, config=dbmod.Database.CONFIG.EMPTY) as db0:
|
||||||
db0.config['spam'] = 'ham'
|
db0.config['spam'] = 'ham'
|
||||||
with dbmod.Database(maildir.path) as db1:
|
with dbmod.Database(maildir.path, config=dbmod.Database.CONFIG.EMPTY) as db1:
|
||||||
assert db1.config['spam'] == 'ham'
|
assert db1.config['spam'] == 'ham'
|
||||||
|
|
||||||
def test_get_keyerror(self, db):
|
def test_get_keyerror(self, db):
|
||||||
|
|
|
@ -13,7 +13,7 @@ import notmuch2._message as message
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def db(maildir):
|
def db(maildir):
|
||||||
with dbmod.Database.create(maildir.path) as db:
|
with dbmod.Database.create(maildir.path, config=notmuch2.Database.CONFIG.EMPTY) as db:
|
||||||
yield db
|
yield db
|
||||||
|
|
||||||
|
|
||||||
|
@ -293,7 +293,7 @@ class TestQuery:
|
||||||
maildir.deliver(body='baz',
|
maildir.deliver(body='baz',
|
||||||
headers=[('In-Reply-To', '<{}>'.format(msgid))])
|
headers=[('In-Reply-To', '<{}>'.format(msgid))])
|
||||||
notmuch('new')
|
notmuch('new')
|
||||||
with dbmod.Database(maildir.path, 'rw') as db:
|
with dbmod.Database(maildir.path, 'rw', config=notmuch2.Database.CONFIG.EMPTY) as db:
|
||||||
yield db
|
yield db
|
||||||
|
|
||||||
def test_count_messages(self, db):
|
def test_count_messages(self, db):
|
||||||
|
|
|
@ -97,6 +97,9 @@ class TestMessage:
|
||||||
def test_ghost_no(self, msg):
|
def test_ghost_no(self, msg):
|
||||||
assert not msg.ghost
|
assert not msg.ghost
|
||||||
|
|
||||||
|
def test_matched_no(self,msg):
|
||||||
|
assert not msg.matched
|
||||||
|
|
||||||
def test_date(self, msg):
|
def test_date(self, msg):
|
||||||
# XXX Someone seems to treat things as local time instead of
|
# XXX Someone seems to treat things as local time instead of
|
||||||
# UTC or the other way around.
|
# UTC or the other way around.
|
||||||
|
|
|
@ -23,7 +23,7 @@ class TestImmutable:
|
||||||
"""
|
"""
|
||||||
maildir.deliver()
|
maildir.deliver()
|
||||||
notmuch('new')
|
notmuch('new')
|
||||||
with database.Database(maildir.path) as db:
|
with database.Database(maildir.path, config=database.Database.CONFIG.EMPTY) as db:
|
||||||
yield db.tags
|
yield db.tags
|
||||||
|
|
||||||
def test_type(self, tagset):
|
def test_type(self, tagset):
|
||||||
|
@ -33,7 +33,7 @@ class TestImmutable:
|
||||||
def test_hash(self, tagset, maildir, notmuch):
|
def test_hash(self, tagset, maildir, notmuch):
|
||||||
h0 = hash(tagset)
|
h0 = hash(tagset)
|
||||||
notmuch('tag', '+foo', '*')
|
notmuch('tag', '+foo', '*')
|
||||||
with database.Database(maildir.path) as db:
|
with database.Database(maildir.path, config=database.Database.CONFIG.EMPTY) as db:
|
||||||
h1 = hash(db.tags)
|
h1 = hash(db.tags)
|
||||||
assert h0 != h1
|
assert h0 != h1
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ class TestImmutable:
|
||||||
|
|
||||||
def test_neq(self, tagset, maildir, notmuch):
|
def test_neq(self, tagset, maildir, notmuch):
|
||||||
notmuch('tag', '+foo', '*')
|
notmuch('tag', '+foo', '*')
|
||||||
with database.Database(maildir.path) as db:
|
with database.Database(maildir.path, config=database.Database.CONFIG.EMPTY) as db:
|
||||||
assert tagset != db.tags
|
assert tagset != db.tags
|
||||||
|
|
||||||
def test_contains(self, tagset):
|
def test_contains(self, tagset):
|
||||||
|
@ -159,7 +159,8 @@ class TestMutableTagset:
|
||||||
_, pathname = maildir.deliver()
|
_, pathname = maildir.deliver()
|
||||||
notmuch('new')
|
notmuch('new')
|
||||||
with database.Database(maildir.path,
|
with database.Database(maildir.path,
|
||||||
mode=database.Mode.READ_WRITE) as db:
|
mode=database.Mode.READ_WRITE,
|
||||||
|
config=database.Database.CONFIG.EMPTY) as db:
|
||||||
msg = db.get(pathname)
|
msg = db.get(pathname)
|
||||||
yield msg.tags
|
yield msg.tags
|
||||||
|
|
||||||
|
@ -195,7 +196,8 @@ class TestMutableTagset:
|
||||||
_, pathname = maildir.deliver(flagged=True)
|
_, pathname = maildir.deliver(flagged=True)
|
||||||
notmuch('new')
|
notmuch('new')
|
||||||
with database.Database(maildir.path,
|
with database.Database(maildir.path,
|
||||||
mode=database.Mode.READ_WRITE) as db:
|
mode=database.Mode.READ_WRITE,
|
||||||
|
config=database.Database.CONFIG.EMPTY) as db:
|
||||||
msg = db.get(pathname)
|
msg = db.get(pathname)
|
||||||
msg.tags.discard('flagged')
|
msg.tags.discard('flagged')
|
||||||
msg.tags.from_maildir_flags()
|
msg.tags.from_maildir_flags()
|
||||||
|
@ -205,7 +207,8 @@ class TestMutableTagset:
|
||||||
_, pathname = maildir.deliver(flagged=True)
|
_, pathname = maildir.deliver(flagged=True)
|
||||||
notmuch('new')
|
notmuch('new')
|
||||||
with database.Database(maildir.path,
|
with database.Database(maildir.path,
|
||||||
mode=database.Mode.READ_WRITE) as db:
|
mode=database.Mode.READ_WRITE,
|
||||||
|
config=database.Database.CONFIG.EMPTY) as db:
|
||||||
msg = db.get(pathname)
|
msg = db.get(pathname)
|
||||||
flags = msg.path.name.split(',')[-1]
|
flags = msg.path.name.split(',')[-1]
|
||||||
assert 'F' in flags
|
assert 'F' in flags
|
||||||
|
|
|
@ -13,7 +13,7 @@ def thread(maildir, notmuch):
|
||||||
maildir.deliver(body='bar',
|
maildir.deliver(body='bar',
|
||||||
headers=[('In-Reply-To', '<{}>'.format(msgid))])
|
headers=[('In-Reply-To', '<{}>'.format(msgid))])
|
||||||
notmuch('new')
|
notmuch('new')
|
||||||
with notmuch2.Database(maildir.path) as db:
|
with notmuch2.Database(maildir.path, config=notmuch2.Database.CONFIG.EMPTY) as db:
|
||||||
yield next(db.threads('foo'))
|
yield next(db.threads('foo'))
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,6 +57,13 @@ def test_iter(thread):
|
||||||
def test_matched(thread):
|
def test_matched(thread):
|
||||||
assert thread.matched == 1
|
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):
|
def test_authors_type(thread):
|
||||||
assert isinstance(thread.authors, notmuch2.BinString)
|
assert isinstance(thread.authors, notmuch2.BinString)
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
0.34.2
|
|
|
@ -1,3 +1,3 @@
|
||||||
# this file should be kept in sync with ../../../version
|
# this file should be kept in sync with ../../../version
|
||||||
__VERSION__ = '0.34.2'
|
__VERSION__ = '0.35'
|
||||||
SOVERSION = '5'
|
SOVERSION = '5'
|
||||||
|
|
|
@ -103,12 +103,12 @@ _notmuch_search_terms()
|
||||||
COMPREPLY=( $(compgen -P "from:" -W "`_notmuch_email ${cur}`" -- ${cur##from:}) )
|
COMPREPLY=( $(compgen -P "from:" -W "`_notmuch_email ${cur}`" -- ${cur##from:}) )
|
||||||
;;
|
;;
|
||||||
path:*)
|
path:*)
|
||||||
local path=`notmuch config get database.path`
|
local path=`notmuch config get database.mail_root`
|
||||||
compopt -o nospace
|
compopt -o nospace
|
||||||
COMPREPLY=( $(compgen -d "$path/${cur##path:}" | sed "s|^$path/||" ) )
|
COMPREPLY=( $(compgen -d "$path/${cur##path:}" | sed "s|^$path/||" ) )
|
||||||
;;
|
;;
|
||||||
folder:*)
|
folder:*)
|
||||||
local path=`notmuch config get database.path`
|
local path=`notmuch config get database.mail_root`
|
||||||
compopt -o nospace
|
compopt -o nospace
|
||||||
COMPREPLY=( $(compgen -d "$path/${cur##folder:}" | \
|
COMPREPLY=( $(compgen -d "$path/${cur##folder:}" | \
|
||||||
sed "s|^$path/||" | grep -v "\(^\|/\)\(cur\|new\|tmp\)$" ) )
|
sed "s|^$path/||" | grep -v "\(^\|/\)\(cur\|new\|tmp\)$" ) )
|
||||||
|
@ -281,7 +281,7 @@ _notmuch_insert()
|
||||||
$split &&
|
$split &&
|
||||||
case "${prev}" in
|
case "${prev}" in
|
||||||
--folder)
|
--folder)
|
||||||
local path=`notmuch config get database.path`
|
local path=`notmuch config get database.mail_root`
|
||||||
compopt -o nospace
|
compopt -o nospace
|
||||||
COMPREPLY=( $(compgen -d "$path/${cur}" | \
|
COMPREPLY=( $(compgen -d "$path/${cur}" | \
|
||||||
sed "s|^$path/||" | grep -v "\(^\|/\)\(cur\|new\|tmp\)$" ) )
|
sed "s|^$path/||" | grep -v "\(^\|/\)\(cur\|new\|tmp\)$" ) )
|
||||||
|
|
|
@ -69,8 +69,8 @@ _notmuch_term_mimetype() {
|
||||||
|
|
||||||
_notmuch_term_path() {
|
_notmuch_term_path() {
|
||||||
local ret=1 expl
|
local ret=1 expl
|
||||||
local maildir="$(notmuch config get database.path)"
|
local maildir="$(notmuch config get database.mail_root)"
|
||||||
[[ -d $maildir ]] || { _message -e "database.path not found" ; return $ret }
|
[[ -d $maildir ]] || { _message -e "database.mail_root not found" ; return $ret }
|
||||||
|
|
||||||
_description notmuch-folder expl 'maildir folder'
|
_description notmuch-folder expl 'maildir folder'
|
||||||
_files "$expl[@]" -W $maildir -/ && ret=0
|
_files "$expl[@]" -W $maildir -/ && ret=0
|
||||||
|
@ -79,8 +79,8 @@ _notmuch_term_path() {
|
||||||
|
|
||||||
_notmuch_term_folder() {
|
_notmuch_term_folder() {
|
||||||
local ret=1 expl
|
local ret=1 expl
|
||||||
local maildir="$(notmuch config get database.path)"
|
local maildir="$(notmuch config get database.mail_root)"
|
||||||
[[ -d $maildir ]] || { _message -e "database.path not found" ; return $ret }
|
[[ -d $maildir ]] || { _message -e "database.mail_root not found" ; return $ret }
|
||||||
|
|
||||||
_description notmuch-folder expl 'maildir folder'
|
_description notmuch-folder expl 'maildir folder'
|
||||||
local ignoredfolders=( '*/(cur|new|tmp)' )
|
local ignoredfolders=( '*/(cur|new|tmp)' )
|
||||||
|
|
40
configure
vendored
40
configure
vendored
|
@ -55,6 +55,8 @@ subdirs="${subdirs} bindings"
|
||||||
# the directory structure and copy Makefiles.
|
# the directory structure and copy Makefiles.
|
||||||
if [ "$srcdir" != "." ]; then
|
if [ "$srcdir" != "." ]; then
|
||||||
|
|
||||||
|
NOTMUCH_BUILDDIR=$PWD
|
||||||
|
|
||||||
for dir in . ${subdirs}; do
|
for dir in . ${subdirs}; do
|
||||||
mkdir -p "$dir"
|
mkdir -p "$dir"
|
||||||
cp "$srcdir"/"$dir"/Makefile.local "$dir"
|
cp "$srcdir"/"$dir"/Makefile.local "$dir"
|
||||||
|
@ -78,6 +80,8 @@ if [ "$srcdir" != "." ]; then
|
||||||
"$srcdir"/bindings/python-cffi/notmuch2 \
|
"$srcdir"/bindings/python-cffi/notmuch2 \
|
||||||
"$srcdir"/bindings/python-cffi/setup.py \
|
"$srcdir"/bindings/python-cffi/setup.py \
|
||||||
bindings/python-cffi/
|
bindings/python-cffi/
|
||||||
|
else
|
||||||
|
NOTMUCH_BUILDDIR=$NOTMUCH_SRCDIR
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Set several defaults (optionally specified by the user in
|
# Set several defaults (optionally specified by the user in
|
||||||
|
@ -308,12 +312,22 @@ for option; do
|
||||||
true
|
true
|
||||||
elif [ "${option%%=*}" = '--host' ] ; then
|
elif [ "${option%%=*}" = '--host' ] ; then
|
||||||
true
|
true
|
||||||
|
elif [ "${option%%=*}" = '--bindir' ] ; then
|
||||||
|
true
|
||||||
|
elif [ "${option%%=*}" = '--sbindir' ] ; then
|
||||||
|
true
|
||||||
elif [ "${option%%=*}" = '--datadir' ] ; then
|
elif [ "${option%%=*}" = '--datadir' ] ; then
|
||||||
true
|
true
|
||||||
elif [ "${option%%=*}" = '--localstatedir' ] ; then
|
elif [ "${option%%=*}" = '--localstatedir' ] ; then
|
||||||
true
|
true
|
||||||
|
elif [ "${option%%=*}" = '--sharedstatedir' ] ; then
|
||||||
|
true
|
||||||
elif [ "${option%%=*}" = '--libexecdir' ] ; then
|
elif [ "${option%%=*}" = '--libexecdir' ] ; then
|
||||||
true
|
true
|
||||||
|
elif [ "${option%%=*}" = '--exec-prefix' ] ; then
|
||||||
|
true
|
||||||
|
elif [ "${option%%=*}" = '--program-prefix' ] ; then
|
||||||
|
true
|
||||||
elif [ "${option}" = '--disable-maintainer-mode' ] ; then
|
elif [ "${option}" = '--disable-maintainer-mode' ] ; then
|
||||||
true
|
true
|
||||||
elif [ "${option}" = '--disable-dependency-tracking' ] ; then
|
elif [ "${option}" = '--disable-dependency-tracking' ] ; then
|
||||||
|
@ -396,6 +410,18 @@ EOF
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
printf "C compiler supports address sanitizer... "
|
||||||
|
test_cmdline="${CC} ${CFLAGS} ${CPPFLAGS} -fsanitize=address minimal.c ${LDFLAGS} -o minimal"
|
||||||
|
if ${test_cmdline} >/dev/null 2>&1 && ./minimal
|
||||||
|
then
|
||||||
|
printf "Yes.\n"
|
||||||
|
have_asan=1
|
||||||
|
else
|
||||||
|
printf "Nope, skipping those tests.\n"
|
||||||
|
have_asan=0
|
||||||
|
fi
|
||||||
|
unset test_cmdline
|
||||||
|
|
||||||
printf "Reading libnotmuch version from source... "
|
printf "Reading libnotmuch version from source... "
|
||||||
cat > _libversion.c <<EOF
|
cat > _libversion.c <<EOF
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -734,6 +760,7 @@ if command -v ${BASHCMD} > /dev/null; then
|
||||||
printf "Yes (%s).\n" "$bash_absolute"
|
printf "Yes (%s).\n" "$bash_absolute"
|
||||||
else
|
else
|
||||||
have_bash=0
|
have_bash=0
|
||||||
|
bash_absolute=
|
||||||
printf "No. (%s not found)\n" "${BASHCMD}"
|
printf "No. (%s not found)\n" "${BASHCMD}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -744,6 +771,7 @@ if command -v ${PERL} > /dev/null; then
|
||||||
printf "Yes (%s).\n" "$perl_absolute"
|
printf "Yes (%s).\n" "$perl_absolute"
|
||||||
else
|
else
|
||||||
have_perl=0
|
have_perl=0
|
||||||
|
perl_absolute=
|
||||||
printf "No. (%s not found)\n" "${PERL}"
|
printf "No. (%s not found)\n" "${PERL}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -1245,6 +1273,7 @@ cat > Makefile.config <<EOF
|
||||||
# directory (the current directory at the time configure was run).
|
# directory (the current directory at the time configure was run).
|
||||||
srcdir = ${srcdir}
|
srcdir = ${srcdir}
|
||||||
NOTMUCH_SRCDIR = ${NOTMUCH_SRCDIR}
|
NOTMUCH_SRCDIR = ${NOTMUCH_SRCDIR}
|
||||||
|
NOTMUCH_BUILDDIR = ${NOTMUCH_BUILDDIR}
|
||||||
|
|
||||||
# subdirectories to build
|
# subdirectories to build
|
||||||
subdirs = ${subdirs}
|
subdirs = ${subdirs}
|
||||||
|
@ -1531,6 +1560,9 @@ NOTMUCH_GMIME_X509_CERT_VALIDITY=${gmime_x509_cert_validity}
|
||||||
# Whether GMime can verify signatures when decrypting with a session key:
|
# Whether GMime can verify signatures when decrypting with a session key:
|
||||||
NOTMUCH_GMIME_VERIFY_WITH_SESSION_KEY=${gmime_verify_with_session_key}
|
NOTMUCH_GMIME_VERIFY_WITH_SESSION_KEY=${gmime_verify_with_session_key}
|
||||||
|
|
||||||
|
# Does the C compiler support the address sanitizer
|
||||||
|
NOTMUCH_HAVE_ASAN=${have_asan}
|
||||||
|
|
||||||
# do we have man pages?
|
# do we have man pages?
|
||||||
NOTMUCH_HAVE_MAN=$((have_sphinx))
|
NOTMUCH_HAVE_MAN=$((have_sphinx))
|
||||||
|
|
||||||
|
@ -1579,6 +1611,14 @@ EOF
|
||||||
printf "rsti_dir = '%s'\n" "$(cd emacs && pwd -P)"
|
printf "rsti_dir = '%s'\n" "$(cd emacs && pwd -P)"
|
||||||
} > sphinx.config
|
} > sphinx.config
|
||||||
|
|
||||||
|
cat > bindings/python-cffi/_notmuch_config.py <<EOF
|
||||||
|
# _notmuch_config.py was automatically generated by the configure
|
||||||
|
# script in the root of the notmuch source tree.
|
||||||
|
NOTMUCH_VERSION_FILE='${NOTMUCH_SRCDIR}/version.txt'
|
||||||
|
NOTMUCH_INCLUDE_DIR='${NOTMUCH_SRCDIR}/lib'
|
||||||
|
NOTMUCH_LIB_DIR='${NOTMUCH_SRCDIR}/lib'
|
||||||
|
EOF
|
||||||
|
|
||||||
# Finally, after everything configured, inform the user how to continue.
|
# Finally, after everything configured, inform the user how to continue.
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
|
|
||||||
|
|
31
debian/changelog
vendored
31
debian/changelog
vendored
|
@ -1,3 +1,34 @@
|
||||||
|
notmuch (0.35-1~bpo11+1) bullseye-backports; urgency=medium
|
||||||
|
|
||||||
|
* Rebuild for bullseye-backports.
|
||||||
|
|
||||||
|
-- David Bremner <bremner@debian.org> Tue, 15 Feb 2022 20:54:43 -0400
|
||||||
|
|
||||||
|
notmuch (0.35-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release
|
||||||
|
|
||||||
|
-- David Bremner <bremner@debian.org> Sun, 06 Feb 2022 12:15:19 -0400
|
||||||
|
|
||||||
|
notmuch (0.35~rc0-2) experimental; urgency=medium
|
||||||
|
|
||||||
|
* Reupload with binaries
|
||||||
|
|
||||||
|
-- David Bremner <bremner@debian.org> Sat, 29 Jan 2022 21:53:29 -0400
|
||||||
|
|
||||||
|
notmuch (0.35~rc0-1) experimental; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release candidate
|
||||||
|
|
||||||
|
-- David Bremner <bremner@debian.org> Sat, 29 Jan 2022 18:14:57 -0400
|
||||||
|
|
||||||
|
notmuch (0.34.3-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* New upstream bugfix release, with several fixes for the notmuch2
|
||||||
|
python module.
|
||||||
|
|
||||||
|
-- David Bremner <bremner@debian.org> Sun, 09 Jan 2022 15:30:38 -0400
|
||||||
|
|
||||||
notmuch (0.34.2-1~bpo11+1) bullseye-backports; urgency=medium
|
notmuch (0.34.2-1~bpo11+1) bullseye-backports; urgency=medium
|
||||||
|
|
||||||
* Rebuild for bullseye-backports.
|
* Rebuild for bullseye-backports.
|
||||||
|
|
18
debian/control
vendored
18
debian/control
vendored
|
@ -56,7 +56,8 @@ Recommends:
|
||||||
gnupg-agent,
|
gnupg-agent,
|
||||||
gpgsm,
|
gpgsm,
|
||||||
Suggests:
|
Suggests:
|
||||||
mailscripts
|
mailscripts,
|
||||||
|
notmuch-doc,
|
||||||
Description: thread-based email index, search and tagging
|
Description: thread-based email index, search and tagging
|
||||||
Notmuch is a system for indexing, searching, reading, and tagging
|
Notmuch is a system for indexing, searching, reading, and tagging
|
||||||
large collections of email messages in maildir or mh format. It uses
|
large collections of email messages in maildir or mh format. It uses
|
||||||
|
@ -65,6 +66,21 @@ Description: thread-based email index, search and tagging
|
||||||
.
|
.
|
||||||
This package contains the notmuch command-line interface
|
This package contains the notmuch command-line interface
|
||||||
|
|
||||||
|
Package: notmuch-doc
|
||||||
|
Architecture: all
|
||||||
|
Depends:
|
||||||
|
${misc:Depends},
|
||||||
|
${sphinxdoc:Depends},
|
||||||
|
Suggests:
|
||||||
|
notmuch
|
||||||
|
Description: thread-based email index, search and tagging
|
||||||
|
Notmuch is a system for indexing, searching, reading, and tagging
|
||||||
|
large collections of email messages in maildir or mh format. It uses
|
||||||
|
the Xapian library to provide fast, full-text search with a very
|
||||||
|
convenient search syntax.
|
||||||
|
.
|
||||||
|
This package contains the HTML documentation
|
||||||
|
|
||||||
Package: libnotmuch5
|
Package: libnotmuch5
|
||||||
Section: libs
|
Section: libs
|
||||||
Architecture: any
|
Architecture: any
|
||||||
|
|
2
debian/elpa-notmuch.elpa
vendored
2
debian/elpa-notmuch.elpa
vendored
|
@ -1,3 +1,3 @@
|
||||||
debian/tmp/usr/share/emacs/site-lisp/*.el
|
debian/tmp/usr/share/emacs/site-lisp/*.el
|
||||||
debian/tmp/usr/share/emacs/site-lisp/notmuch-logo.png
|
debian/tmp/usr/share/emacs/site-lisp/notmuch-logo.svg
|
||||||
emacs/notmuch-pkg.el
|
emacs/notmuch-pkg.el
|
||||||
|
|
1
debian/notmuch-doc.install
vendored
Normal file
1
debian/notmuch-doc.install
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
doc/_build/html usr/share/doc/notmuch
|
4
debian/rules
vendored
4
debian/rules
vendored
|
@ -3,7 +3,7 @@
|
||||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||||
|
|
||||||
%:
|
%:
|
||||||
dh $@ --with python3,elpa
|
dh $@ --with python3,elpa,sphinxdoc
|
||||||
|
|
||||||
override_dh_auto_configure:
|
override_dh_auto_configure:
|
||||||
BASHCMD=/bin/bash ./configure --prefix=/usr \
|
BASHCMD=/bin/bash ./configure --prefix=/usr \
|
||||||
|
@ -19,7 +19,7 @@ override_dh_auto_test:
|
||||||
dh_auto_test -- V=1
|
dh_auto_test -- V=1
|
||||||
|
|
||||||
override_dh_auto_build:
|
override_dh_auto_build:
|
||||||
dh_auto_build -- V=1
|
dh_auto_build -- V=1 all sphinx-html
|
||||||
PYBUILD_NAME=notmuch dh_auto_build --buildsystem=pybuild --sourcedirectory bindings/python
|
PYBUILD_NAME=notmuch dh_auto_build --buildsystem=pybuild --sourcedirectory bindings/python
|
||||||
PYBUILD_NAME=notmuch2 dh_auto_build --buildsystem=pybuild --sourcedirectory bindings/python-cffi
|
PYBUILD_NAME=notmuch2 dh_auto_build --buildsystem=pybuild --sourcedirectory bindings/python-cffi
|
||||||
$(MAKE) -C contrib/notmuch-mutt
|
$(MAKE) -C contrib/notmuch-mutt
|
||||||
|
|
|
@ -145,9 +145,11 @@ headers = {
|
||||||
Cc?: string,
|
Cc?: string,
|
||||||
Bcc?: string,
|
Bcc?: string,
|
||||||
Reply-To?: string,
|
Reply-To?: string,
|
||||||
Date: string
|
Date: string,
|
||||||
|
extra_header_pair*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extra_header_pair= (header_name: string)
|
||||||
# Encryption status (format_part_sprinter)
|
# Encryption status (format_part_sprinter)
|
||||||
encstatus = [{status: "good"|"bad"}]
|
encstatus = [{status: "good"|"bad"}]
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ endif
|
||||||
|
|
||||||
INFO_INFO_FILES := $(INFO_TEXI_FILES:.texi=.info)
|
INFO_INFO_FILES := $(INFO_TEXI_FILES:.texi=.info)
|
||||||
|
|
||||||
.PHONY: sphinx-html sphinx-texinfo sphinx-info doc-prereqs
|
.PHONY: sphinx-html sphinx-texinfo sphinx-info
|
||||||
|
|
||||||
.PHONY: install-man build-man apidocs install-apidocs
|
.PHONY: install-man build-man apidocs install-apidocs
|
||||||
|
|
||||||
|
@ -47,23 +47,28 @@ $(DOCBUILDDIR)/.roff.stamp $(DOCBUILDDIR)/.html.stamp $(DOCBUILDDIR)/.texi.stamp
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(HAVE_PYTHON3_CFFI),1)
|
ifeq ($(HAVE_PYTHON3_CFFI),1)
|
||||||
doc-prereqs: python-cffi-bindings
|
DOC_PREREQS=bindings/python-cffi.stamp
|
||||||
|
else
|
||||||
|
DOC_PREREQS=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
sphinx-html: $(DOCBUILDDIR)/.html.stamp
|
sphinx-html: $(DOCBUILDDIR)/.html.stamp
|
||||||
|
|
||||||
$(DOCBUILDDIR)/.html.stamp: $(ALL_RST_FILES) doc-prereqs
|
$(DOCBUILDDIR)/.html.stamp: $(ALL_RST_FILES) $(DOC_PREREQS)
|
||||||
$(SPHINXBUILD) -b html -d $(DOCBUILDDIR)/html_doctrees $(ALLSPHINXOPTS) $(DOCBUILDDIR)/html
|
$(SPHINXBUILD) -b html -d $(DOCBUILDDIR)/html_doctrees $(ALLSPHINXOPTS) $(DOCBUILDDIR)/html
|
||||||
touch $@
|
touch $@
|
||||||
|
|
||||||
sphinx-texinfo: $(DOCBUILDDIR)/.texi.stamp
|
sphinx-texinfo: $(DOCBUILDDIR)/.texi.stamp
|
||||||
|
|
||||||
$(DOCBUILDDIR)/.texi.stamp: $(ALL_RST_FILES) doc-prereqs
|
$(DOCBUILDDIR)/.texi.stamp: $(ALL_RST_FILES) $(DOC_PREREQS)
|
||||||
$(SPHINXBUILD) -b texinfo -d $(DOCBUILDDIR)/texinfo_doctrees $(ALLSPHINXOPTS) $(DOCBUILDDIR)/texinfo
|
$(SPHINXBUILD) -b texinfo -d $(DOCBUILDDIR)/texinfo_doctrees $(ALLSPHINXOPTS) $(DOCBUILDDIR)/texinfo
|
||||||
touch $@
|
touch $@
|
||||||
|
|
||||||
sphinx-info: sphinx-texinfo
|
sphinx-info: $(DOCBUILDDIR)/.info.stamp
|
||||||
|
|
||||||
|
$(DOCBUILDDIR)/.info.stamp: $(DOCBUILDDIR)/.texi.stamp $(DOC_PREREQS)
|
||||||
$(MAKE) -C $(DOCBUILDDIR)/texinfo info
|
$(MAKE) -C $(DOCBUILDDIR)/texinfo info
|
||||||
|
touch $@
|
||||||
|
|
||||||
# Use the man page converter that is available. We should never depend
|
# Use the man page converter that is available. We should never depend
|
||||||
# on MAN_ROFF_FILES if a converter is not available.
|
# on MAN_ROFF_FILES if a converter is not available.
|
||||||
|
@ -112,6 +117,11 @@ build-man:
|
||||||
install-man:
|
install-man:
|
||||||
@echo "No sphinx, will not install man pages."
|
@echo "No sphinx, will not install man pages."
|
||||||
else
|
else
|
||||||
|
|
||||||
|
# it should be safe to depend on the stamp file, because it is created
|
||||||
|
# after all roff files are moved into place.
|
||||||
|
${MAN_GZIP_FILES}: ${DOCBUILDDIR}/.roff.stamp
|
||||||
|
|
||||||
build-man: ${MAN_GZIP_FILES}
|
build-man: ${MAN_GZIP_FILES}
|
||||||
install-man: ${MAN_GZIP_FILES}
|
install-man: ${MAN_GZIP_FILES}
|
||||||
mkdir -m0755 -p "$(DESTDIR)$(mandir)/man1"
|
mkdir -m0755 -p "$(DESTDIR)$(mandir)/man1"
|
||||||
|
@ -127,7 +137,7 @@ ifneq ($(HAVE_SPHINX)$(HAVE_MAKEINFO),11)
|
||||||
build-info:
|
build-info:
|
||||||
@echo "Missing sphinx or makeinfo, not building info pages"
|
@echo "Missing sphinx or makeinfo, not building info pages"
|
||||||
else
|
else
|
||||||
build-info: sphinx-info
|
build-info: $(DOCBUILDDIR)/.info.stamp
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(HAVE_SPHINX)$(HAVE_MAKEINFO)$(HAVE_INSTALL_INFO),111)
|
ifneq ($(HAVE_SPHINX)$(HAVE_MAKEINFO)$(HAVE_INSTALL_INFO),111)
|
||||||
|
@ -145,5 +155,5 @@ $(dir)/config.dox: version.stamp
|
||||||
echo "INPUT=${srcdir}/lib/notmuch.h" >> $@
|
echo "INPUT=${srcdir}/lib/notmuch.h" >> $@
|
||||||
|
|
||||||
CLEAN := $(CLEAN) $(DOCBUILDDIR) $(DOCBUILDDIR)/.roff.stamp $(DOCBUILDDIR)/.texi.stamp
|
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
|
CLEAN := $(CLEAN) $(MAN_GZIP_FILES) $(MAN_ROFF_FILES) $(dir)/conf.pyc $(dir)/config.dox
|
||||||
|
|
|
@ -14,7 +14,7 @@ master_doc = 'index'
|
||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u'notmuch'
|
project = u'notmuch'
|
||||||
copyright = u'2009-2021, Carl Worth and many others'
|
copyright = u'2009-2022, Carl Worth and many others'
|
||||||
|
|
||||||
location = os.path.dirname(__file__)
|
location = os.path.dirname(__file__)
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ Supported options for **address** include
|
||||||
neither ``--output=sender`` nor ``--output=recipients`` is
|
neither ``--output=sender`` nor ``--output=recipients`` is
|
||||||
given, ``--output=sender`` is implied.
|
given, ``--output=sender`` is implied.
|
||||||
|
|
||||||
**sender**
|
sender
|
||||||
Output all addresses from the *From* header.
|
Output all addresses from the *From* header.
|
||||||
|
|
||||||
Note: Searching for **sender** should be much faster than
|
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
|
cached directly in the database whereas other addresses need
|
||||||
to be fetched from message files.
|
to be fetched from message files.
|
||||||
|
|
||||||
**recipients**
|
recipients
|
||||||
Output all addresses from the *To*, *Cc* and *Bcc* headers.
|
Output all addresses from the *To*, *Cc* and *Bcc* headers.
|
||||||
|
|
||||||
**count**
|
count
|
||||||
Print the count of how many times was the address encountered
|
Print the count of how many times was the address encountered
|
||||||
during search.
|
during search.
|
||||||
|
|
||||||
Note: With this option, addresses are printed only after the
|
Note: With this option, addresses are printed only after the
|
||||||
whole search is finished. This may take long time.
|
whole search is finished. This may take long time.
|
||||||
|
|
||||||
**address**
|
address
|
||||||
Output only the email addresses instead of the full mailboxes
|
Output only the email addresses instead of the full mailboxes
|
||||||
with names and email addresses. This option has no effect on
|
with names and email addresses. This option has no effect on
|
||||||
the JSON or S-Expression output formats.
|
the JSON or S-Expression output formats.
|
||||||
|
@ -69,17 +69,17 @@ Supported options for **address** include
|
||||||
|
|
||||||
Control the deduplication of results.
|
Control the deduplication of results.
|
||||||
|
|
||||||
**no**
|
no
|
||||||
Output all occurrences of addresses in the matching
|
Output all occurrences of addresses in the matching
|
||||||
messages. This is not applicable with ``--output=count``.
|
messages. This is not applicable with ``--output=count``.
|
||||||
|
|
||||||
**mailbox**
|
mailbox
|
||||||
Deduplicate addresses based on the full, case sensitive name
|
Deduplicate addresses based on the full, case sensitive name
|
||||||
and email address, or mailbox. This is effectively the same as
|
and email address, or mailbox. This is effectively the same as
|
||||||
piping the ``--deduplicate=no`` output to **sort | uniq**, except
|
piping the ``--deduplicate=no`` output to **sort | uniq**, except
|
||||||
for the order of results. This is the default.
|
for the order of results. This is the default.
|
||||||
|
|
||||||
**address**
|
address
|
||||||
Deduplicate addresses based on the case insensitive address
|
Deduplicate addresses based on the case insensitive address
|
||||||
part of the mailbox. Of all the variants (with different name
|
part of the mailbox. Of all the variants (with different name
|
||||||
or case), print the one occurring most frequently among the
|
or case), print the one occurring most frequently among the
|
||||||
|
|
|
@ -55,14 +55,14 @@ The available configuration items are described below. Non-absolute
|
||||||
paths are presumed relative to `$HOME` for items in section
|
paths are presumed relative to `$HOME` for items in section
|
||||||
**database**.
|
**database**.
|
||||||
|
|
||||||
**database.path**
|
database.path
|
||||||
Notmuch will store its database here, (in
|
Notmuch will store its database here, (in
|
||||||
sub-directory named ``.notmuch`` if **database.mail\_root**
|
sub-directory named ``.notmuch`` if **database.mail\_root**
|
||||||
is unset).
|
is unset).
|
||||||
|
|
||||||
Default: see :ref:`database`
|
Default: see :ref:`database`
|
||||||
|
|
||||||
**database.mail_root**
|
database.mail_root
|
||||||
The top-level directory where your mail currently exists and to
|
The top-level directory where your mail currently exists and to
|
||||||
where mail will be delivered in the future. Files should be
|
where mail will be delivered in the future. Files should be
|
||||||
individual email messages.
|
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
|
Default: For compatibility with older configurations, the value of
|
||||||
database.path is used if **database.mail\_root** is unset.
|
database.path is used if **database.mail\_root** is unset.
|
||||||
|
|
||||||
**database.backup_dir**
|
database.backup_dir
|
||||||
Directory to store tag dumps when upgrading database.
|
Directory to store tag dumps when upgrading database.
|
||||||
|
|
||||||
History: this configuration value was introduced in notmuch 0.32.
|
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
|
Default: A sibling directory of the Xapian database called
|
||||||
`backups`.
|
`backups`.
|
||||||
|
|
||||||
**database.hook_dir**
|
database.hook_dir
|
||||||
Directory containing hooks run by notmuch commands. See
|
Directory containing hooks run by notmuch commands. See
|
||||||
:any:`notmuch-hooks(5)`.
|
:any:`notmuch-hooks(5)`.
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ paths are presumed relative to `$HOME` for items in section
|
||||||
|
|
||||||
Default: See HOOKS, below.
|
Default: See HOOKS, below.
|
||||||
|
|
||||||
**database.autocommit**
|
database.autocommit
|
||||||
|
|
||||||
How often to commit transactions to disk. `0` means wait until
|
How often to commit transactions to disk. `0` means wait until
|
||||||
command completes, otherwise an integer `n` specifies to commit to
|
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.
|
History: this configuration value was introduced in notmuch 0.33.
|
||||||
|
|
||||||
**user.name**
|
user.name
|
||||||
Your full name.
|
Your full name.
|
||||||
|
|
||||||
Default: ``$NAME`` variable if set, otherwise read from
|
Default: ``$NAME`` variable if set, otherwise read from
|
||||||
``/etc/passwd``.
|
``/etc/passwd``.
|
||||||
|
|
||||||
**user.primary\_email**
|
user.primary\_email
|
||||||
Your primary email address.
|
Your primary email address.
|
||||||
|
|
||||||
Default: ``$EMAIL`` variable if set, otherwise constructed from
|
Default: ``$EMAIL`` variable if set, otherwise constructed from
|
||||||
the username and hostname of the current machine.
|
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.
|
A list of other email addresses at which you receive email.
|
||||||
|
|
||||||
Default: not set.
|
Default: not set.
|
||||||
|
|
||||||
**new.tags**
|
new.tags
|
||||||
A list of tags that will be added to all messages incorporated by
|
A list of tags that will be added to all messages incorporated by
|
||||||
**notmuch new**.
|
**notmuch new**.
|
||||||
|
|
||||||
Default: ``unread;inbox``.
|
Default: ``unread;inbox``.
|
||||||
|
|
||||||
**new.ignore**
|
new.ignore
|
||||||
A list to specify files and directories that will not be searched
|
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:
|
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.
|
Default: empty list.
|
||||||
|
|
||||||
**search.exclude\_tags**
|
search.exclude\_tags
|
||||||
A list of tags that will be excluded from search results by
|
A list of tags that will be excluded from search results by
|
||||||
default. Using an excluded tag in a query will override that
|
default. Using an excluded tag in a query will override that
|
||||||
exclusion.
|
exclusion.
|
||||||
|
@ -145,7 +145,21 @@ paths are presumed relative to `$HOME` for items in section
|
||||||
Default: empty list. Note that :any:`notmuch-setup(1)` puts
|
Default: empty list. Note that :any:`notmuch-setup(1)` puts
|
||||||
``deleted;spam`` here when creating new configuration file.
|
``deleted;spam`` here when creating new configuration file.
|
||||||
|
|
||||||
**maildir.synchronize\_flags**
|
.. _show.extra_headers:
|
||||||
|
|
||||||
|
show.extra\_headers
|
||||||
|
|
||||||
|
By default :any:`notmuch-show(1)` includes the following headers
|
||||||
|
in structured output if they are present in the message:
|
||||||
|
`Subject`, `From`, `To`, `Cc`, `Bcc`, `Reply-To`, `Date`. This
|
||||||
|
option allows the specification of a list of further
|
||||||
|
headers to output.
|
||||||
|
|
||||||
|
History: This configuration value was introduced in notmuch 0.35.
|
||||||
|
|
||||||
|
Default: empty list.
|
||||||
|
|
||||||
|
maildir.synchronize\_flags
|
||||||
If true, then the following maildir flags (in message filenames)
|
If true, then the following maildir flags (in message filenames)
|
||||||
will be synchronized with the corresponding notmuch tags:
|
will be synchronized with the corresponding notmuch tags:
|
||||||
|
|
||||||
|
@ -178,7 +192,7 @@ paths are presumed relative to `$HOME` for items in section
|
||||||
|
|
||||||
Default: ``true``.
|
Default: ``true``.
|
||||||
|
|
||||||
**index.decrypt**
|
index.decrypt
|
||||||
Policy for decrypting encrypted messages during indexing. Must be
|
Policy for decrypting encrypted messages during indexing. Must be
|
||||||
one of: ``false``, ``auto``, ``nostash``, or ``true``.
|
one of: ``false``, ``auto``, ``nostash``, or ``true``.
|
||||||
|
|
||||||
|
@ -231,7 +245,7 @@ paths are presumed relative to `$HOME` for items in section
|
||||||
|
|
||||||
Default: ``auto``.
|
Default: ``auto``.
|
||||||
|
|
||||||
**index.header.<prefix>**
|
index.header.<prefix>
|
||||||
Define the query prefix <prefix>, based on a mail header. For
|
Define the query prefix <prefix>, based on a mail header. For
|
||||||
example ``index.header.List=List-Id`` will add a probabilistic
|
example ``index.header.List=List-Id`` will add a probabilistic
|
||||||
prefix ``List:`` that searches the ``List-Id`` field. User
|
prefix ``List:`` that searches the ``List-Id`` field. User
|
||||||
|
@ -240,18 +254,18 @@ paths are presumed relative to `$HOME` for items in section
|
||||||
supported. See :any:`notmuch-search-terms(7)` for a list of existing
|
supported. See :any:`notmuch-search-terms(7)` for a list of existing
|
||||||
prefixes, and an explanation of probabilistic prefixes.
|
prefixes, and an explanation of probabilistic prefixes.
|
||||||
|
|
||||||
**built_with.<name>**
|
built_with.<name>
|
||||||
Compile time feature <name>. Current possibilities include
|
Compile time feature <name>. Current possibilities include
|
||||||
"retry_lock" (configure option, included by default).
|
"retry_lock" (configure option, included by default).
|
||||||
(since notmuch 0.30, "compact" and "field_processor" are
|
(since notmuch 0.30, "compact" and "field_processor" are
|
||||||
always included.)
|
always included.)
|
||||||
|
|
||||||
**query.<name>**
|
query.<name>
|
||||||
Expansion for named query called <name>. See
|
Expansion for named query called <name>. See
|
||||||
:any:`notmuch-search-terms(7)` for more information about named
|
:any:`notmuch-search-terms(7)` for more information about named
|
||||||
queries.
|
queries.
|
||||||
|
|
||||||
**squery.<name>**
|
squery.<name>
|
||||||
Expansion for named query called <name>, using s-expression syntax. See
|
Expansion for named query called <name>, using s-expression syntax. See
|
||||||
:any:`notmuch-sexp-queries(7)` for more information about s-expression
|
:any:`notmuch-sexp-queries(7)` for more information about s-expression
|
||||||
queries.
|
queries.
|
||||||
|
|
|
@ -28,13 +28,13 @@ Supported options for **count** include
|
||||||
|
|
||||||
.. option:: --output=(messages|threads|files)
|
.. option:: --output=(messages|threads|files)
|
||||||
|
|
||||||
**messages**
|
messages
|
||||||
Output the number of matching messages. This is the default.
|
Output the number of matching messages. This is the default.
|
||||||
|
|
||||||
**threads**
|
threads
|
||||||
Output the number of matching threads.
|
Output the number of matching threads.
|
||||||
|
|
||||||
**files**
|
files
|
||||||
Output the number of files associated with matching
|
Output the number of files associated with matching
|
||||||
messages. This may be bigger than the number of matching
|
messages. This may be bigger than the number of matching
|
||||||
messages due to duplicates (i.e. multiple files having the
|
messages due to duplicates (i.e. multiple files having the
|
||||||
|
|
|
@ -39,7 +39,7 @@ Supported options for **dump** include
|
||||||
Notmuch restore supports two plain text dump formats, both with
|
Notmuch restore supports two plain text dump formats, both with
|
||||||
one message-id per line, followed by a list of tags.
|
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
|
The default **batch-tag** dump format is intended to more
|
||||||
robust against malformed message-ids and tags containing
|
robust against malformed message-ids and tags containing
|
||||||
whitespace or non-\ :manpage:`ascii(7)` characters. Each line
|
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
|
:any:`notmuch-tag(1)`; note that the single message-id query is
|
||||||
mandatory for :any:`notmuch-restore(1)`.
|
mandatory for :any:`notmuch-restore(1)`.
|
||||||
|
|
||||||
**sup**
|
sup
|
||||||
The **sup** dump file format is specifically chosen to be
|
The **sup** dump file format is specifically chosen to be
|
||||||
compatible with the format of files produced by
|
compatible with the format of files produced by
|
||||||
:manpage:`sup-dump(1)`. So if you've previously been using sup
|
: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.
|
Control what kind of metadata is included in the output.
|
||||||
|
|
||||||
**config**
|
config
|
||||||
Output configuration data stored in the database. Each line
|
Output configuration data stored in the database. Each line
|
||||||
starts with "#@ ", followed by a space separated key-value
|
starts with "#@ ", followed by a space separated key-value
|
||||||
pair. Both key and value are hex encoded if needed.
|
pair. Both key and value are hex encoded if needed.
|
||||||
|
|
||||||
**properties**
|
properties
|
||||||
Output per-message (key,value) metadata. Each line starts
|
Output per-message (key,value) metadata. Each line starts
|
||||||
with "#= ", followed by a message id, and a space separated
|
with "#= ", followed by a message id, and a space separated
|
||||||
list of key=value pairs. Ids, keys and values are hex encoded
|
list of key=value pairs. Ids, keys and values are hex encoded
|
||||||
if needed. See :any:`notmuch-properties(7)` for more details.
|
if needed. See :any:`notmuch-properties(7)` for more details.
|
||||||
|
|
||||||
**tags**
|
tags
|
||||||
Output per-message boolean metadata, namely tags. See *format* above
|
Output per-message boolean metadata, namely tags. See *format* above
|
||||||
for description of the output.
|
for description of the output.
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ DESCRIPTION
|
||||||
|
|
||||||
**notmuch insert** reads a message from standard input and delivers it
|
**notmuch insert** reads a message from standard input and delivers it
|
||||||
into the maildir directory given by configuration option
|
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
|
database. It is an alternative to using a separate tool to deliver the
|
||||||
message then running :any:`notmuch-new(1)` afterwards.
|
message then running :any:`notmuch-new(1)` afterwards.
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ Supported options for **insert** include
|
||||||
.. option:: --folder=<folder>
|
.. option:: --folder=<folder>
|
||||||
|
|
||||||
Deliver the message to the specified folder, relative to the
|
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
|
default is the empty string, which means delivering to the
|
||||||
top-level directory.
|
top-level directory.
|
||||||
|
|
||||||
|
|
|
@ -40,22 +40,22 @@ Supported options for **reply** include
|
||||||
|
|
||||||
.. option:: --format=(default|json|sexp|headers-only)
|
.. option:: --format=(default|json|sexp|headers-only)
|
||||||
|
|
||||||
**default**
|
default
|
||||||
Includes subject and quoted message body as an RFC 2822
|
Includes subject and quoted message body as an RFC 2822
|
||||||
message.
|
message.
|
||||||
|
|
||||||
**json**
|
json
|
||||||
Produces JSON output containing headers for a reply message
|
Produces JSON output containing headers for a reply message
|
||||||
and the contents of the original message. This output can be
|
and the contents of the original message. This output can be
|
||||||
used by a client to create a reply message intelligently.
|
used by a client to create a reply message intelligently.
|
||||||
|
|
||||||
**sexp**
|
sexp
|
||||||
Produces S-Expression output containing headers for a reply
|
Produces S-Expression output containing headers for a reply
|
||||||
message and the contents of the original message. This output
|
message and the contents of the original message. This output
|
||||||
can be used by a client to create a reply message
|
can be used by a client to create a reply message
|
||||||
intelligently.
|
intelligently.
|
||||||
|
|
||||||
**headers-only**
|
headers-only
|
||||||
Only produces In-Reply-To, References, To, Cc, and Bcc
|
Only produces In-Reply-To, References, To, Cc, and Bcc
|
||||||
headers.
|
headers.
|
||||||
|
|
||||||
|
@ -67,10 +67,10 @@ Supported options for **reply** include
|
||||||
|
|
||||||
.. option:: --reply-to=(all|sender)
|
.. option:: --reply-to=(all|sender)
|
||||||
|
|
||||||
**all** (default)
|
all (default)
|
||||||
Replies to all addresses.
|
Replies to all addresses.
|
||||||
|
|
||||||
**sender**
|
sender
|
||||||
Replies only to the sender. If replying to user's own message
|
Replies only to the sender. If replying to user's own message
|
||||||
(Reply-to: or From: header is one of the user's configured
|
(Reply-to: or From: header is one of the user's configured
|
||||||
email addresses), try To:, Cc:, and Bcc: headers in this
|
email addresses), try To:, Cc:, and Bcc: headers in this
|
||||||
|
|
|
@ -32,14 +32,14 @@ Supported options for **restore** include
|
||||||
line specifying a message-id and a set of tags. For details of the
|
line specifying a message-id and a set of tags. For details of the
|
||||||
actual formats, see :any:`notmuch-dump(1)`.
|
actual formats, see :any:`notmuch-dump(1)`.
|
||||||
|
|
||||||
**sup**
|
sup
|
||||||
The **sup** dump file format is specifically chosen to be
|
The **sup** dump file format is specifically chosen to be
|
||||||
compatible with the format of files produced by sup-dump. So
|
compatible with the format of files produced by sup-dump. So
|
||||||
if you've previously been using sup for mail, then the
|
if you've previously been using sup for mail, then the
|
||||||
**notmuch restore** command provides you a way to import all
|
**notmuch restore** command provides you a way to import all
|
||||||
of your tags (or labels as sup calls them).
|
of your tags (or labels as sup calls them).
|
||||||
|
|
||||||
**batch-tag**
|
batch-tag
|
||||||
The **batch-tag** dump format is intended to more robust
|
The **batch-tag** dump format is intended to more robust
|
||||||
against malformed message-ids and tags containing whitespace
|
against malformed message-ids and tags containing whitespace
|
||||||
or non-\ **ascii(7)** characters. See :any:`notmuch-dump(1)` for
|
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
|
changes if the **maildir.synchronize\_flags** configuration
|
||||||
option is enabled. See :any:`notmuch-config(1)` for details.
|
option is enabled. See :any:`notmuch-config(1)` for details.
|
||||||
|
|
||||||
**auto**
|
auto
|
||||||
This option (the default) tries to guess the format from the
|
This option (the default) tries to guess the format from the
|
||||||
input. For correctly formed input in either supported format,
|
input. For correctly formed input in either supported format,
|
||||||
this heuristic, based the fact that batch-tag format contains
|
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.
|
Control what kind of metadata is restored.
|
||||||
|
|
||||||
**config**
|
config
|
||||||
Restore configuration data to the database. Each configuration
|
Restore configuration data to the database. Each configuration
|
||||||
line starts with "#@ ", followed by a space separated
|
line starts with "#@ ", followed by a space separated
|
||||||
key-value pair. Both key and value are hex encoded if needed.
|
key-value pair. Both key and value are hex encoded if needed.
|
||||||
|
|
||||||
**properties**
|
properties
|
||||||
Restore per-message (key,value) metadata. Each line starts
|
Restore per-message (key,value) metadata. Each line starts
|
||||||
with "#= ", followed by a message id, and a space separated
|
with "#= ", followed by a message id, and a space separated
|
||||||
list of key=value pairs. Ids, keys and values are hex encoded
|
list of key=value pairs. Ids, keys and values are hex encoded
|
||||||
if needed. See :any:`notmuch-properties(7)` for more details.
|
if needed. See :any:`notmuch-properties(7)` for more details.
|
||||||
|
|
||||||
**tags**
|
tags
|
||||||
Restore per-message metadata, namely tags. See *format* above
|
Restore per-message metadata, namely tags. See *format* above
|
||||||
for more details.
|
for more details.
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ Supported options for **search** include
|
||||||
|
|
||||||
.. option:: --output=(summary|threads|messages|files|tags)
|
.. option:: --output=(summary|threads|messages|files|tags)
|
||||||
|
|
||||||
**summary**
|
summary
|
||||||
Output a summary of each thread with any message matching the
|
Output a summary of each thread with any message matching the
|
||||||
search terms. The summary includes the thread ID, date, the
|
search terms. The summary includes the thread ID, date, the
|
||||||
number of messages in the thread (both the number matched and
|
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
|
for some messages, the total number of files is printed in
|
||||||
parentheses (see below for an example).
|
parentheses (see below for an example).
|
||||||
|
|
||||||
**threads**
|
threads
|
||||||
Output the thread IDs of all threads with any message matching
|
Output the thread IDs of all threads with any message matching
|
||||||
the search terms, either one per line (``--format=text``),
|
the search terms, either one per line (``--format=text``),
|
||||||
separated by null characters (``--format=text0``), as a JSON array
|
separated by null characters (``--format=text0``), as a JSON array
|
||||||
(``--format=json``), or an S-Expression list (``--format=sexp``).
|
(``--format=json``), or an S-Expression list (``--format=sexp``).
|
||||||
|
|
||||||
**messages**
|
messages
|
||||||
Output the message IDs of all messages matching the search
|
Output the message IDs of all messages matching the search
|
||||||
terms, either one per line (``--format=text``), separated by null
|
terms, either one per line (``--format=text``), separated by null
|
||||||
characters (``--format=text0``), as a JSON array (``--format=json``),
|
characters (``--format=text0``), as a JSON array (``--format=json``),
|
||||||
or as an S-Expression list (``--format=sexp``).
|
or as an S-Expression list (``--format=sexp``).
|
||||||
|
|
||||||
**files**
|
files
|
||||||
Output the filenames of all messages matching the search
|
Output the filenames of all messages matching the search
|
||||||
terms, either one per line (``--format=text``), separated by null
|
terms, either one per line (``--format=text``), separated by null
|
||||||
characters (``--format=text0``), as a JSON array (``--format=json``),
|
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
|
in other directories that are included in the output, although
|
||||||
these files alone would not match the search.
|
these files alone would not match the search.
|
||||||
|
|
||||||
**tags**
|
tags
|
||||||
Output all tags that appear on any message matching the search
|
Output all tags that appear on any message matching the search
|
||||||
terms, either one per line (``--format=text``), separated by null
|
terms, either one per line (``--format=text``), separated by null
|
||||||
characters (``--format=text0``), as a JSON array (``--format=json``),
|
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
|
terms. This option specifies whether to omit excluded messages in
|
||||||
the search process.
|
the search process.
|
||||||
|
|
||||||
**true** (default)
|
true (default)
|
||||||
Prevent excluded messages from matching the search terms.
|
Prevent excluded messages from matching the search terms.
|
||||||
|
|
||||||
**all**
|
all
|
||||||
Additionally prevent excluded messages from appearing in
|
Additionally prevent excluded messages from appearing in
|
||||||
displayed results, in effect behaving as though the excluded
|
displayed results, in effect behaving as though the excluded
|
||||||
messages do not exist.
|
messages do not exist.
|
||||||
|
|
||||||
**false**
|
false
|
||||||
Allow excluded messages to match search terms and appear in
|
Allow excluded messages to match search terms and appear in
|
||||||
displayed results. Excluded messages are still marked in the
|
displayed results. Excluded messages are still marked in the
|
||||||
relevant outputs.
|
relevant outputs.
|
||||||
|
|
||||||
**flag**
|
flag
|
||||||
Only has an effect when ``--output=summary``. The output is
|
Only has an effect when ``--output=summary``. The output is
|
||||||
almost identical to **false**, but the "match count" is the
|
almost identical to **false**, but the "match count" is the
|
||||||
number of matching non-excluded messages in the thread, rather
|
number of matching non-excluded messages in the thread, rather
|
||||||
|
|
|
@ -36,7 +36,7 @@ Supported options for **show** include
|
||||||
|
|
||||||
.. option:: --format=(text|json|sexp|mbox|raw)
|
.. 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
|
The default plain-text format has all text-content MIME parts
|
||||||
decoded. Various components in the output, (**message**,
|
decoded. Various components in the output, (**message**,
|
||||||
**header**, **body**, **attachment**, and MIME **part**), will
|
**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
|
'}'), to either open or close the component. For a multipart
|
||||||
MIME message, these parts will be nested.
|
MIME message, these parts will be nested.
|
||||||
|
|
||||||
**json**
|
json
|
||||||
The output is formatted with Javascript Object Notation
|
The output is formatted with Javascript Object Notation
|
||||||
(JSON). This format is more robust than the text format for
|
(JSON). This format is more robust than the text format for
|
||||||
automated processing. The nested structure of multipart MIME
|
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
|
as UTF-8 and any message content included in the output will
|
||||||
be charset-converted to UTF-8.
|
be charset-converted to UTF-8.
|
||||||
|
|
||||||
**sexp**
|
sexp
|
||||||
The output is formatted as the Lisp s-expression (sexp)
|
The output is formatted as the Lisp s-expression (sexp)
|
||||||
equivalent of the JSON format above. Objects are formatted as
|
equivalent of the JSON format above. Objects are formatted as
|
||||||
property lists whose keys are keywords (symbols preceded by a
|
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
|
formatted as ``nil``. As for JSON, the s-expression output is
|
||||||
always encoded as UTF-8.
|
always encoded as UTF-8.
|
||||||
|
|
||||||
**mbox**
|
mbox
|
||||||
All matching messages are output in the traditional, Unix mbox
|
All matching messages are output in the traditional, Unix mbox
|
||||||
format with each message being prefixed by a line beginning
|
format with each message being prefixed by a line beginning
|
||||||
with "From " and a blank line separating each message. Lines
|
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
|
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
|
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
|
standard out. For this format, it is an error to specify a
|
||||||
query that matches more than one message.
|
query that matches more than one message.
|
||||||
|
@ -221,6 +221,13 @@ email messages. For this, use a search term of "thread:<thread-id>" as
|
||||||
can be seen in the first column of output from the
|
can be seen in the first column of output from the
|
||||||
:any:`notmuch-search(1)` command.
|
:any:`notmuch-search(1)` command.
|
||||||
|
|
||||||
|
CONFIGURATION
|
||||||
|
=============
|
||||||
|
|
||||||
|
Structured output (json / sexp) is influenced by the configuration
|
||||||
|
option :ref:`show.extra_headers <show.extra_headers>`. See
|
||||||
|
:any:`notmuch-config(1)` for details.
|
||||||
|
|
||||||
EXIT STATUS
|
EXIT STATUS
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ must have executable permissions.
|
||||||
|
|
||||||
The currently available hooks are described below.
|
The currently available hooks are described below.
|
||||||
|
|
||||||
**pre-new**
|
pre-new
|
||||||
This hook is invoked by the :any:`notmuch-new(1)` command before
|
This hook is invoked by the :any:`notmuch-new(1)` command before
|
||||||
scanning or importing new messages into the database. If this hook
|
scanning or importing new messages into the database. If this hook
|
||||||
exits with a non-zero status, notmuch will abort further
|
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
|
Typically this hook is used for fetching or delivering new mail to
|
||||||
be imported into the database.
|
be imported into the database.
|
||||||
|
|
||||||
**post-new**
|
post-new
|
||||||
This hook is invoked by the :any:`notmuch-new(1)` command after
|
This hook is invoked by the :any:`notmuch-new(1)` command after
|
||||||
new messages have been imported into the database and initial tags
|
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
|
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
|
Typically this hook is used to perform additional query-based
|
||||||
tagging on the imported messages.
|
tagging on the imported messages.
|
||||||
|
|
||||||
**post-insert**
|
post-insert
|
||||||
This hook is invoked by the :any:`notmuch-insert(1)` command after
|
This hook is invoked by the :any:`notmuch-insert(1)` command after
|
||||||
the message has been delivered, added to the database, and initial
|
the message has been delivered, added to the database, and initial
|
||||||
tags have been applied. The hook will not be run if there have
|
tags have been applied. The hook will not be run if there have
|
||||||
|
|
|
@ -55,7 +55,7 @@ MESSAGE PROPERTIES
|
||||||
The following properties are set by notmuch internally in the course
|
The following properties are set by notmuch internally in the course
|
||||||
of its normal activity.
|
of its normal activity.
|
||||||
|
|
||||||
**index.decryption**
|
index.decryption
|
||||||
If a message contains encrypted content, and notmuch tries to
|
If a message contains encrypted content, and notmuch tries to
|
||||||
decrypt that content during indexing, it will add the property
|
decrypt that content during indexing, it will add the property
|
||||||
``index.decryption=success`` when the cleartext was successfully
|
``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
|
:any:`notmuch-config(1)`), then this property will not be set on that
|
||||||
message.
|
message.
|
||||||
|
|
||||||
**session-key**
|
session-key
|
||||||
|
|
||||||
When :any:`notmuch-show(1)` or :any:`notmuch-reply(1)` encounters
|
When :any:`notmuch-show(1)` or :any:`notmuch-reply(1)` encounters
|
||||||
a message with an encrypted part, if notmuch finds a
|
a message with an encrypted part, if notmuch finds a
|
||||||
``session-key`` property associated with the message, it will try
|
``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:
|
example, an AES-128 key might be stashed in a notmuch property as:
|
||||||
``session-key=7:14B16AF65536C28AF209828DFE34C9E0``.
|
``session-key=7:14B16AF65536C28AF209828DFE34C9E0``.
|
||||||
|
|
||||||
**index.repaired**
|
index.repaired
|
||||||
|
|
||||||
Some messages arrive in forms that are confusing to view; they can
|
Some messages arrive in forms that are confusing to view; they can
|
||||||
be mangled by mail transport agents, or the sending mail user
|
be mangled by mail transport agents, or the sending mail user
|
||||||
agent may structure them in a way that is confusing. If notmuch
|
agent may structure them in a way that is confusing. If notmuch
|
||||||
|
|
|
@ -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
|
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
|
s-expressions inside parentheses. Atoms are either
|
||||||
|
|
||||||
*basic value*
|
*basic value*
|
||||||
|
|
||||||
A basic value is an unquoted string containing no whitespace, double quotes, or
|
A basic value is an unquoted string containing no whitespace, double quotes, or
|
||||||
parentheses.
|
parentheses.
|
||||||
|
|
||||||
*quoted string*
|
*quoted string*
|
||||||
|
|
||||||
Double quotes (") delimit strings possibly containing whitespace
|
Double quotes (") delimit strings possibly containing whitespace
|
||||||
or parentheses. These can contain double quote characters by
|
or parentheses. These can contain double quote characters by
|
||||||
escaping with backslash. E.g. ``"this is a quote \""``.
|
escaping with backslash. E.g. ``"this is a quote \""``.
|
||||||
|
@ -48,9 +50,11 @@ a *field*, *logical operation*, or *modifier*, and 0 or more
|
||||||
subqueries.
|
subqueries.
|
||||||
|
|
||||||
``*``
|
``*``
|
||||||
|
|
||||||
"*" matches any non-empty string in the current field.
|
"*" matches any non-empty string in the current field.
|
||||||
|
|
||||||
``()``
|
``()``
|
||||||
|
|
||||||
The empty list matches all messages
|
The empty list matches all messages
|
||||||
|
|
||||||
*term*
|
*term*
|
||||||
|
@ -62,19 +66,23 @@ subqueries.
|
||||||
phrase splitting see :any:`fields`.
|
phrase splitting see :any:`fields`.
|
||||||
|
|
||||||
``(`` *field* |q1| |q2| ... |qn| ``)``
|
``(`` *field* |q1| |q2| ... |qn| ``)``
|
||||||
|
|
||||||
Restrict the queries |q1| to |qn| to *field*, and combine with *and*
|
Restrict the queries |q1| to |qn| to *field*, and combine with *and*
|
||||||
(for most fields) or *or*. See :any:`fields` for more information.
|
(for most fields) or *or*. See :any:`fields` for more information.
|
||||||
|
|
||||||
``(`` *operator* |q1| |q2| ... |qn| ``)``
|
``(`` *operator* |q1| |q2| ... |qn| ``)``
|
||||||
|
|
||||||
Combine queries |q1| to |qn|. Currently supported operators are
|
Combine queries |q1| to |qn|. Currently supported operators are
|
||||||
``and``, ``or``, and ``not``. ``(not`` |q1| ... |qn| ``)`` is equivalent
|
``and``, ``or``, and ``not``. ``(not`` |q1| ... |qn| ``)`` is equivalent
|
||||||
to ``(and (not`` |q1| ``) ... (not`` |qn| ``))``.
|
to ``(and (not`` |q1| ``) ... (not`` |qn| ``))``.
|
||||||
|
|
||||||
``(`` *modifier* |q1| |q2| ... |qn| ``)``
|
``(`` *modifier* |q1| |q2| ... |qn| ``)``
|
||||||
|
|
||||||
Combine queries |q1| to |qn|, and reinterpret the result (e.g. as a regular expression).
|
Combine queries |q1| to |qn|, and reinterpret the result (e.g. as a regular expression).
|
||||||
See :any:`modifiers` for more information.
|
See :any:`modifiers` for more information.
|
||||||
|
|
||||||
``(macro (`` |p1| ... |pn| ``) body)``
|
``(macro (`` |p1| ... |pn| ``) body)``
|
||||||
|
|
||||||
Define saved query with parameter substitution. The syntax is
|
Define saved query with parameter substitution. The syntax is
|
||||||
recognized only in saved s-expression queries (see ``squery.*`` in
|
recognized only in saved s-expression queries (see ``squery.*`` in
|
||||||
:any:`notmuch-config(1)`). Parameter names in ``body`` must be
|
:any:`notmuch-config(1)`). Parameter names in ``body`` must be
|
||||||
|
@ -164,26 +172,31 @@ MODIFIERS
|
||||||
that are neither operators nor fields.
|
that are neither operators nor fields.
|
||||||
|
|
||||||
``(infix`` *atom* ``)``
|
``(infix`` *atom* ``)``
|
||||||
|
|
||||||
Interpret *atom* as an infix notmuch query (see
|
Interpret *atom* as an infix notmuch query (see
|
||||||
:any:`notmuch-search-terms(7)`). Not supported inside fields.
|
:any:`notmuch-search-terms(7)`). Not supported inside fields.
|
||||||
|
|
||||||
``(matching`` |q1| |q2| ... |qn| ``)`` ``(of`` |q1| |q2| ... |qn| ``)``
|
``(matching`` |q1| |q2| ... |qn| ``)`` ``(of`` |q1| |q2| ... |qn| ``)``
|
||||||
|
|
||||||
Match all messages have the same values of the current field as
|
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
|
those matching all of |q1| ... |qn|. Supported in most term [#not-path]_ or
|
||||||
phrase fields. Most commonly used in the ``thread`` field.
|
phrase fields. Most commonly used in the ``thread`` field.
|
||||||
|
|
||||||
``(query`` *atom* ``)``
|
``(query`` *atom* ``)``
|
||||||
|
|
||||||
Expand to the saved query named by *atom*. See
|
Expand to the saved query named by *atom*. See
|
||||||
:any:`notmuch-config(1)` for more. Note that the saved query must
|
:any:`notmuch-config(1)` for more. Note that the saved query must
|
||||||
be in infix syntax (:any:`notmuch-search-terms(7)`). Not supported
|
be in infix syntax (:any:`notmuch-search-terms(7)`). Not supported
|
||||||
inside fields.
|
inside fields.
|
||||||
|
|
||||||
``(regex`` *atom* ``)`` ``(rx`` *atom* ``)``
|
``(regex`` *atom* ``)`` ``(rx`` *atom* ``)``
|
||||||
|
|
||||||
Interpret *atom* as a POSIX.2 regular expression (see
|
Interpret *atom* as a POSIX.2 regular expression (see
|
||||||
:manpage:`regex(7)`). This applies in term fields and a subset [#not-phrase]_ of
|
:manpage:`regex(7)`). This applies in term fields and a subset [#not-phrase]_ of
|
||||||
phrase fields (see :any:`field-table`).
|
phrase fields (see :any:`field-table`).
|
||||||
|
|
||||||
``(starts-with`` *subword* ``)``
|
``(starts-with`` *subword* ``)``
|
||||||
|
|
||||||
Matches any term starting with *subword*. This applies in either
|
Matches any term starting with *subword*. This applies in either
|
||||||
phrase or term :any:`fields <fields>`, or outside of fields [#not-body]_. Note that
|
phrase or term :any:`fields <fields>`, or outside of fields [#not-body]_. Note that
|
||||||
a ``starts-with`` query cannot be part of a phrase. The
|
a ``starts-with`` query cannot be part of a phrase. The
|
||||||
|
@ -193,63 +206,80 @@ EXAMPLES
|
||||||
========
|
========
|
||||||
|
|
||||||
``Wizard``
|
``Wizard``
|
||||||
|
|
||||||
Match all messages containing the word "wizard", ignoring case.
|
Match all messages containing the word "wizard", ignoring case.
|
||||||
|
|
||||||
``added``
|
``added``
|
||||||
|
|
||||||
Match all messages containing "added", but also those containing "add", "additional",
|
Match all messages containing "added", but also those containing "add", "additional",
|
||||||
"Additional", "adds", etc... via stemming.
|
"Additional", "adds", etc... via stemming.
|
||||||
|
|
||||||
``(and Bob Marley)``
|
``(and Bob Marley)``
|
||||||
|
|
||||||
Match messages containing words "Bob" and "Marley", or their stems
|
Match messages containing words "Bob" and "Marley", or their stems
|
||||||
The words need not be adjacent.
|
The words need not be adjacent.
|
||||||
|
|
||||||
``(not Bob Marley)``
|
``(not Bob Marley)``
|
||||||
|
|
||||||
Match messages containing neither "Bob" nor "Marley", nor their stems,
|
Match messages containing neither "Bob" nor "Marley", nor their stems,
|
||||||
|
|
||||||
``"quick fox"`` ``quick-fox`` ``quick@fox``
|
``"quick fox"`` ``quick-fox`` ``quick@fox``
|
||||||
|
|
||||||
Match the *phrase* "quick" followed by "fox" in phrase fields (or
|
Match the *phrase* "quick" followed by "fox" in phrase fields (or
|
||||||
outside a field). Match the literal string in a term field.
|
outside a field). Match the literal string in a term field.
|
||||||
|
|
||||||
``(folder (of (id 1234@invalid)))``
|
``(folder (of (id 1234@invalid)))``
|
||||||
|
|
||||||
Match any message in the same folder as the one with Message-Id "1234@invalid"
|
Match any message in the same folder as the one with Message-Id "1234@invalid"
|
||||||
|
|
||||||
``(id 1234@invalid blah@test)``
|
``(id 1234@invalid blah@test)``
|
||||||
|
|
||||||
Matches Message-Id "1234@invalid" *or* Message-Id "blah@test"
|
Matches Message-Id "1234@invalid" *or* Message-Id "blah@test"
|
||||||
|
|
||||||
``(and (infix "date:2009-11-18..2009-11-18") (tag unread))``
|
``(and (infix "date:2009-11-18..2009-11-18") (tag unread))``
|
||||||
|
|
||||||
Match messages in the given date range with tag unread.
|
Match messages in the given date range with tag unread.
|
||||||
|
|
||||||
``(starts-with prelim)``
|
``(starts-with prelim)``
|
||||||
|
|
||||||
Match any words starting with "prelim".
|
Match any words starting with "prelim".
|
||||||
|
|
||||||
``(subject quick "brown fox")``
|
``(subject quick "brown fox")``
|
||||||
|
|
||||||
Match messages whose subject contains "quick" (anywhere, stemmed) and
|
Match messages whose subject contains "quick" (anywhere, stemmed) and
|
||||||
the phrase "brown fox".
|
the phrase "brown fox".
|
||||||
|
|
||||||
``(subject (starts-with prelim))``
|
``(subject (starts-with prelim))``
|
||||||
|
|
||||||
Matches any word starting with "prelim", inside a message subject.
|
Matches any word starting with "prelim", inside a message subject.
|
||||||
|
|
||||||
``(subject (starts-wih quick) "brown fox")``
|
``(subject (starts-wih quick) "brown fox")``
|
||||||
|
|
||||||
Match messages whose subject contains "quick brown fox", but also
|
Match messages whose subject contains "quick brown fox", but also
|
||||||
"brown fox quicksand".
|
"brown fox quicksand".
|
||||||
|
|
||||||
``(thread (of (id 1234@invalid)))``
|
``(thread (of (id 1234@invalid)))``
|
||||||
|
|
||||||
Match any message in the same thread as the one with Message-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)))``
|
``(thread (matching (from bob@example.com) (to bob@example.com)))``
|
||||||
|
|
||||||
Match any (messages in) a thread containing a message from
|
Match any (messages in) a thread containing a message from
|
||||||
"bob@example.com" and a (possibly distinct) message to "bob at
|
"bob@example.com" and a (possibly distinct) message to "bob at
|
||||||
example.com")
|
example.com")
|
||||||
|
|
||||||
``(to (or bob@example.com mallory@example.org))`` ``(or (to bob@example.com) (to mallory@example.org))``
|
``(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",
|
Match in the "To" or "Cc" headers, "bob@example.com",
|
||||||
"mallory@example.org", and also "bob@example.com.au" since it
|
"mallory@example.org", and also "bob@example.com.au" since it
|
||||||
contains the adjacent triple "bob", "example", "com".
|
contains the adjacent triple "bob", "example", "com".
|
||||||
|
|
||||||
``(not (to *))``
|
``(not (to *))``
|
||||||
|
|
||||||
Match messages with an empty or invalid 'To' and 'Cc' field.
|
Match messages with an empty or invalid 'To' and 'Cc' field.
|
||||||
|
|
||||||
``(List *)``
|
``(List *)``
|
||||||
|
|
||||||
Match messages with a non-empty List-Id header, assuming
|
Match messages with a non-empty List-Id header, assuming
|
||||||
configuration ``index.header.List=List-Id``
|
configuration ``index.header.List=List-Id``
|
||||||
|
|
||||||
|
@ -306,10 +336,10 @@ NOTES
|
||||||
in notmuch, this modifier is not supported in the
|
in notmuch, this modifier is not supported in the
|
||||||
``path`` field.
|
``path`` field.
|
||||||
|
|
||||||
.. |q1| replace:: :math:`q_1`
|
.. |q1| replace:: `q`\ :sub:`1`
|
||||||
.. |q2| replace:: :math:`q_2`
|
.. |q2| replace:: `q`\ :sub:`2`
|
||||||
.. |qn| replace:: :math:`q_n`
|
.. |qn| replace:: `q`\ :sub:`n`
|
||||||
|
|
||||||
.. |p1| replace:: :math:`p_1`
|
.. |p1| replace:: `p`\ :sub:`1`
|
||||||
.. |p2| replace:: :math:`p_2`
|
.. |p2| replace:: `p`\ :sub:`2`
|
||||||
.. |pn| replace:: :math:`p_n`
|
.. |pn| replace:: `p`\ :sub:`n`
|
||||||
|
|
|
@ -56,7 +56,7 @@ notmuch-hello key bindings
|
||||||
``<tab>``
|
``<tab>``
|
||||||
Move to the next widget (button or text entry field)
|
Move to the next widget (button or text entry field)
|
||||||
|
|
||||||
``<backspace>``
|
``<backtab>``
|
||||||
Move to the previous widget.
|
Move to the previous widget.
|
||||||
|
|
||||||
``<return>``
|
``<return>``
|
||||||
|
@ -175,6 +175,16 @@ variables.
|
||||||
:index:`notmuch-search-oldest-first`
|
:index:`notmuch-search-oldest-first`
|
||||||
Display the oldest threads at the top of the buffer
|
Display the oldest threads at the top of the buffer
|
||||||
|
|
||||||
|
It is also possible to customize how the name of buffers containing
|
||||||
|
search results is formatted using the following variables:
|
||||||
|
|
||||||
|
:index:`notmuch-search-buffer-name-format`
|
||||||
|
|docstring::notmuch-search-buffer-name-format|
|
||||||
|
|
||||||
|
:index:`notmuch-saved-search-buffer-name-format`
|
||||||
|
|docstring::notmuch-saved-search-buffer-name-format|
|
||||||
|
|
||||||
|
|
||||||
.. _notmuch-show:
|
.. _notmuch-show:
|
||||||
|
|
||||||
notmuch-show
|
notmuch-show
|
||||||
|
@ -222,6 +232,9 @@ Display of messages can be controlled by the following variables
|
||||||
:index:`notmuch-message-headers-visible`
|
:index:`notmuch-message-headers-visible`
|
||||||
|docstring::notmuch-message-headers-visible|
|
|docstring::notmuch-message-headers-visible|
|
||||||
|
|
||||||
|
:index:`notmuch-show-header-line`
|
||||||
|
|docstring::notmuch-show-header-line|
|
||||||
|
|
||||||
.. _show-copy:
|
.. _show-copy:
|
||||||
|
|
||||||
Copy to kill-ring
|
Copy to kill-ring
|
||||||
|
|
|
@ -42,7 +42,7 @@ emacs_mua := $(dir)/notmuch-emacs-mua
|
||||||
emacs_mua_desktop := $(dir)/notmuch-emacs-mua.desktop
|
emacs_mua_desktop := $(dir)/notmuch-emacs-mua.desktop
|
||||||
|
|
||||||
emacs_images := \
|
emacs_images := \
|
||||||
$(srcdir)/$(dir)/notmuch-logo.png
|
$(srcdir)/$(dir)/notmuch-logo.svg
|
||||||
|
|
||||||
emacs_bytecode = $(emacs_sources:.el=.elc)
|
emacs_bytecode = $(emacs_sources:.el=.elc)
|
||||||
emacs_docstrings = $(emacs_sources:.el=.rsti)
|
emacs_docstrings = $(emacs_sources:.el=.rsti)
|
||||||
|
|
|
@ -45,7 +45,7 @@ Otherwise respect `fill-column'."
|
||||||
:group 'coolj
|
:group 'coolj
|
||||||
:type 'boolean)
|
:type 'boolean)
|
||||||
|
|
||||||
(defcustom coolj-line-prefix-regexp "^\\(>+ \\)*"
|
(defcustom coolj-line-prefix-regexp "^\\(>+ ?\\)*"
|
||||||
"Regular expression that matches line prefixes."
|
"Regular expression that matches line prefixes."
|
||||||
:group 'coolj
|
:group 'coolj
|
||||||
:type 'regexp)
|
:type 'regexp)
|
||||||
|
|
|
@ -198,7 +198,7 @@ fields of the search."
|
||||||
(defvar notmuch-hello-indent 4
|
(defvar notmuch-hello-indent 4
|
||||||
"How much to indent non-headers.")
|
"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
|
(defcustom notmuch-show-logo t
|
||||||
"Should the notmuch logo be shown?"
|
"Should the notmuch logo be shown?"
|
||||||
|
@ -486,11 +486,14 @@ diagonal."
|
||||||
(defun notmuch-hello-widget-search (widget &rest _ignore)
|
(defun notmuch-hello-widget-search (widget &rest _ignore)
|
||||||
(cl-case (widget-get widget :notmuch-search-type)
|
(cl-case (widget-get widget :notmuch-search-type)
|
||||||
(tree
|
(tree
|
||||||
|
(let ((n (notmuch-search-format-buffer-name (widget-value widget) "tree" t)))
|
||||||
(notmuch-tree (widget-get widget :notmuch-search-terms)
|
(notmuch-tree (widget-get widget :notmuch-search-terms)
|
||||||
nil nil nil nil nil nil
|
nil nil n nil nil nil
|
||||||
(widget-get widget :notmuch-search-oldest-first)))
|
(widget-get widget :notmuch-search-oldest-first))))
|
||||||
(unthreaded
|
(unthreaded
|
||||||
(notmuch-unthreaded (widget-get widget :notmuch-search-terms)))
|
(let ((n (notmuch-search-format-buffer-name (widget-value widget)
|
||||||
|
"unthreaded" t)))
|
||||||
|
(notmuch-unthreaded (widget-get widget :notmuch-search-terms) nil nil n)))
|
||||||
(t
|
(t
|
||||||
(notmuch-search (widget-get widget :notmuch-search-terms)
|
(notmuch-search (widget-get widget :notmuch-search-terms)
|
||||||
(widget-get widget :notmuch-search-oldest-first)))))
|
(widget-get widget :notmuch-search-oldest-first)))))
|
||||||
|
@ -557,7 +560,8 @@ with any properties in the original saved-search.
|
||||||
|
|
||||||
The values :show-empty-searches, :filter and :filter-count from
|
The values :show-empty-searches, :filter and :filter-count from
|
||||||
options will be handled as specified for
|
options will be handled as specified for
|
||||||
`notmuch-hello-insert-searches'."
|
`notmuch-hello-insert-searches'. :disable-includes can be used to
|
||||||
|
turn off the default exclude processing in `notmuch-count(1)'"
|
||||||
(with-temp-buffer
|
(with-temp-buffer
|
||||||
(dolist (elem query-list nil)
|
(dolist (elem query-list nil)
|
||||||
(let ((count-query (or (notmuch-saved-search-get elem :count-query)
|
(let ((count-query (or (notmuch-saved-search-get elem :count-query)
|
||||||
|
@ -570,7 +574,11 @@ options will be handled as specified for
|
||||||
(plist-get options :filter))))
|
(plist-get options :filter))))
|
||||||
"\n")))
|
"\n")))
|
||||||
(unless (= (notmuch--call-process-region (point-min) (point-max) notmuch-command
|
(unless (= (notmuch--call-process-region (point-min) (point-max) notmuch-command
|
||||||
t t nil "count" "--batch") 0)
|
t t nil "count"
|
||||||
|
(if (plist-get options :disable-excludes)
|
||||||
|
"--exclude=false"
|
||||||
|
"--exclude=true")
|
||||||
|
"--batch") 0)
|
||||||
(notmuch-logged-error
|
(notmuch-logged-error
|
||||||
"notmuch count --batch failed"
|
"notmuch count --batch failed"
|
||||||
"Please check that the notmuch CLI is new enough to support `count
|
"Please check that the notmuch CLI is new enough to support `count
|
||||||
|
@ -702,7 +710,6 @@ with `notmuch-hello-query-counts'."
|
||||||
;; that when we modify map it does not modify widget-keymap).
|
;; that when we modify map it does not modify widget-keymap).
|
||||||
(let ((map (make-composed-keymap (list (make-sparse-keymap) widget-keymap))))
|
(let ((map (make-composed-keymap (list (make-sparse-keymap) widget-keymap))))
|
||||||
(set-keymap-parent map notmuch-common-keymap)
|
(set-keymap-parent map notmuch-common-keymap)
|
||||||
(define-key map (kbd "<C-tab>") 'widget-backward)
|
|
||||||
map)
|
map)
|
||||||
"Keymap for \"notmuch hello\" buffers.")
|
"Keymap for \"notmuch hello\" buffers.")
|
||||||
|
|
||||||
|
@ -786,7 +793,7 @@ Complete list of currently available key bindings:
|
||||||
:help-echo "Refresh"
|
:help-echo "Refresh"
|
||||||
(notmuch-hello-nice-number
|
(notmuch-hello-nice-number
|
||||||
(string-to-number
|
(string-to-number
|
||||||
(car (notmuch--process-lines notmuch-command "count")))))
|
(car (notmuch--process-lines notmuch-command "count" "--exclude=false")))))
|
||||||
(widget-insert " messages.\n")))
|
(widget-insert " messages.\n")))
|
||||||
|
|
||||||
(defun notmuch-hello-insert-saved-searches ()
|
(defun notmuch-hello-insert-saved-searches ()
|
||||||
|
@ -918,7 +925,8 @@ following:
|
||||||
nil
|
nil
|
||||||
:initially-hidden (not notmuch-show-all-tags-list)
|
:initially-hidden (not notmuch-show-all-tags-list)
|
||||||
:hide-tags notmuch-hello-hide-tags
|
:hide-tags notmuch-hello-hide-tags
|
||||||
:filter notmuch-hello-tag-list-make-query))
|
:filter notmuch-hello-tag-list-make-query
|
||||||
|
:disable-excludes t))
|
||||||
|
|
||||||
(defun notmuch-hello-insert-footer ()
|
(defun notmuch-hello-insert-footer ()
|
||||||
"Insert the notmuch-hello footer."
|
"Insert the notmuch-hello footer."
|
||||||
|
|
27
emacs/notmuch-logo.svg
Normal file
27
emacs/notmuch-logo.svg
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"
|
||||||
|
viewbox="0 0 100 100" fill="#000" stroke-width="2">
|
||||||
|
<circle cx="50" cy="5" r="5" />
|
||||||
|
<g transform="translate(50 20) rotate(20)">
|
||||||
|
<circle cx="-47" cy="0" r="3" />
|
||||||
|
<circle cx="47" cy="0" r="3" />
|
||||||
|
<path d="M-47 -1 L0 -3 L47 -1 L47 1 L0 3 L-47 1 Z" />
|
||||||
|
</g>
|
||||||
|
<path d="M49 4 L45 88
|
||||||
|
A5 5 0 0 1 40 93 L20 93 A5 5 0 0 0 15 100
|
||||||
|
L85 100
|
||||||
|
A5 5 0 0 0 80 93 L60 93 A5 5 0 0 1 55 88
|
||||||
|
L55 90 L51 4 Z" />
|
||||||
|
<g fill="#fff" stroke="#000">
|
||||||
|
<rect x="7" y="33" width="30" height="18" />
|
||||||
|
<line x1="7" y1="51" x2="18" y2="41" />
|
||||||
|
<line x1="37" y1="51" x2="26" y2="41" />
|
||||||
|
<polyline points="7 33 22 44 37 33" fill="none" />
|
||||||
|
</g>
|
||||||
|
<path d="M-18 0 A24 20 0 0 0 18 0" transform="translate(22 51.0)" />
|
||||||
|
<path d="M-18 0 A24 20 0 0 0 18 0" transform="translate(78 71.5)" />
|
||||||
|
<g fill="none" stroke="#000">
|
||||||
|
<path d="M9 53.0 l 12 -42 l 2 0 l 12 42" />
|
||||||
|
<path d="M91 73.5 l-12 -42 l-2 0 l-12 42" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -149,6 +149,7 @@ Otherwise set it according to `notmuch-fcc-dirs'."
|
||||||
(buf (current-buffer))
|
(buf (current-buffer))
|
||||||
(mml-externalize-attachments message-fcc-externalize-attachments))
|
(mml-externalize-attachments message-fcc-externalize-attachments))
|
||||||
(with-current-buffer (get-buffer-create " *message temp*")
|
(with-current-buffer (get-buffer-create " *message temp*")
|
||||||
|
(message-clone-locals buf) ;; for message-encoded-mail-cache
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(insert-buffer-substring buf)
|
(insert-buffer-substring buf)
|
||||||
,@body)))
|
,@body)))
|
||||||
|
@ -158,7 +159,10 @@ Otherwise set it according to `notmuch-fcc-dirs'."
|
||||||
|
|
||||||
This should be called on a temporary copy.
|
This should be called on a temporary copy.
|
||||||
This is taken from the function message-do-fcc."
|
This is taken from the function message-do-fcc."
|
||||||
|
(if (not message-encoded-mail-cache)
|
||||||
(message-encode-message-body)
|
(message-encode-message-body)
|
||||||
|
(erase-buffer)
|
||||||
|
(insert message-encoded-mail-cache))
|
||||||
(save-restriction
|
(save-restriction
|
||||||
(message-narrow-to-headers)
|
(message-narrow-to-headers)
|
||||||
(mail-encode-encoded-word-buffer))
|
(mail-encode-encoded-word-buffer))
|
||||||
|
@ -179,12 +183,12 @@ This is a rearranged version of message mode's message-do-fcc."
|
||||||
(setq file (message-fetch-field "fcc" t)))
|
(setq file (message-fetch-field "fcc" t)))
|
||||||
(when file
|
(when file
|
||||||
(with-temporary-notmuch-message-buffer
|
(with-temporary-notmuch-message-buffer
|
||||||
|
(notmuch-maildir-setup-message-for-saving)
|
||||||
(save-restriction
|
(save-restriction
|
||||||
(message-narrow-to-headers)
|
(message-narrow-to-headers)
|
||||||
(while (setq file (message-fetch-field "fcc" t))
|
(while (setq file (message-fetch-field "fcc" t))
|
||||||
(push file files)
|
(push file files)
|
||||||
(message-remove-header "fcc" nil t)))
|
(message-remove-header "fcc" nil t)))
|
||||||
(notmuch-maildir-setup-message-for-saving)
|
|
||||||
;; Process FCC operations.
|
;; Process FCC operations.
|
||||||
(mapc #'notmuch-fcc-handler files)
|
(mapc #'notmuch-fcc-handler files)
|
||||||
(kill-buffer (current-buffer)))))))
|
(kill-buffer (current-buffer)))))))
|
||||||
|
|
|
@ -84,6 +84,11 @@ visible for any given message."
|
||||||
:type 'boolean
|
:type 'boolean
|
||||||
:group 'notmuch-show)
|
:group 'notmuch-show)
|
||||||
|
|
||||||
|
(defcustom notmuch-show-header-line t
|
||||||
|
"Show a header line with the current message's subject."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'notmuch-show)
|
||||||
|
|
||||||
(defcustom notmuch-show-relative-dates t
|
(defcustom notmuch-show-relative-dates t
|
||||||
"Display relative dates in the message summary line."
|
"Display relative dates in the message summary line."
|
||||||
:type 'boolean
|
:type 'boolean
|
||||||
|
@ -1345,11 +1350,12 @@ If no messages match the query return NIL."
|
||||||
(notmuch-show-mapc
|
(notmuch-show-mapc
|
||||||
(lambda () (notmuch-show-set-prop :orig-tags (notmuch-show-get-tags))))
|
(lambda () (notmuch-show-set-prop :orig-tags (notmuch-show-get-tags))))
|
||||||
;; Set the header line to the subject of the first message.
|
;; Set the header line to the subject of the first message.
|
||||||
|
(when notmuch-show-header-line
|
||||||
(setq header-line-format
|
(setq header-line-format
|
||||||
(replace-regexp-in-string "%" "%%"
|
(replace-regexp-in-string "%" "%%"
|
||||||
(notmuch-sanitize
|
(notmuch-sanitize
|
||||||
(notmuch-show-strip-re
|
(notmuch-show-strip-re
|
||||||
(notmuch-show-get-subject)))))
|
(notmuch-show-get-subject))))))
|
||||||
(run-hooks 'notmuch-show-hook)
|
(run-hooks 'notmuch-show-hook)
|
||||||
(if state
|
(if state
|
||||||
(notmuch-show-apply-state state)
|
(notmuch-show-apply-state state)
|
||||||
|
|
|
@ -241,7 +241,7 @@ DATA is the content of an SVG picture (e.g., as returned by
|
||||||
"Return SVG data representing a star icon.
|
"Return SVG data representing a star icon.
|
||||||
This can be used with `notmuch-tag-format-image-data'."
|
This can be used with `notmuch-tag-format-image-data'."
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
|
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
|
||||||
<svg version=\"1.1\" width=\"16\" height=\"16\">
|
<svg version=\"1.1\" width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\">
|
||||||
<g transform=\"translate(-242.81601,-315.59635)\">
|
<g transform=\"translate(-242.81601,-315.59635)\">
|
||||||
<path
|
<path
|
||||||
d=\"m 290.25762,334.31206 -17.64143,-11.77975 -19.70508,7.85447 5.75171,-20.41814 -13.55925,-16.31348 21.19618,-0.83936 11.325,-17.93675 7.34825,19.89939 20.55849,5.22795 -16.65471,13.13786 z\"
|
d=\"m 290.25762,334.31206 -17.64143,-11.77975 -19.70508,7.85447 5.75171,-20.41814 -13.55925,-16.31348 21.19618,-0.83936 11.325,-17.93675 7.34825,19.89939 20.55849,5.22795 -16.65471,13.13786 z\"
|
||||||
|
@ -254,7 +254,7 @@ This can be used with `notmuch-tag-format-image-data'."
|
||||||
"Return SVG data representing an empty star icon.
|
"Return SVG data representing an empty star icon.
|
||||||
This can be used with `notmuch-tag-format-image-data'."
|
This can be used with `notmuch-tag-format-image-data'."
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
|
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
|
||||||
<svg version=\"1.1\" width=\"16\" height=\"16\">
|
<svg version=\"1.1\" width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\">
|
||||||
<g transform=\"translate(-242.81601,-315.59635)\">
|
<g transform=\"translate(-242.81601,-315.59635)\">
|
||||||
<path
|
<path
|
||||||
d=\"m 290.25762,334.31206 -17.64143,-11.77975 -19.70508,7.85447 5.75171,-20.41814 -13.55925,-16.31348 21.19618,-0.83936 11.325,-17.93675 7.34825,19.89939 20.55849,5.22795 -16.65471,13.13786 z\"
|
d=\"m 290.25762,334.31206 -17.64143,-11.77975 -19.70508,7.85447 5.75171,-20.41814 -13.55925,-16.31348 21.19618,-0.83936 11.325,-17.93675 7.34825,19.89939 20.55849,5.22795 -16.65471,13.13786 z\"
|
||||||
|
@ -267,7 +267,7 @@ This can be used with `notmuch-tag-format-image-data'."
|
||||||
"Return SVG data representing a tag icon.
|
"Return SVG data representing a tag icon.
|
||||||
This can be used with `notmuch-tag-format-image-data'."
|
This can be used with `notmuch-tag-format-image-data'."
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
|
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
|
||||||
<svg version=\"1.1\" width=\"16\" height=\"16\">
|
<svg version=\"1.1\" width=\"16\" height=\"16\" xmlns=\"http://www.w3.org/2000/svg\">
|
||||||
<g transform=\"translate(0,-1036.3622)\">
|
<g transform=\"translate(0,-1036.3622)\">
|
||||||
<path
|
<path
|
||||||
d=\"m 0.44642857,1040.9336 12.50000043,0 2.700893,3.6161 -2.700893,3.616 -12.50000043,0 z\"
|
d=\"m 0.44642857,1040.9336 12.50000043,0 2.700893,3.6161 -2.700893,3.616 -12.50000043,0 z\"
|
||||||
|
@ -429,17 +429,9 @@ initial input in the minibuffer."
|
||||||
(set-keymap-parent map crm-local-completion-map)
|
(set-keymap-parent map crm-local-completion-map)
|
||||||
(define-key map " " 'self-insert-command)
|
(define-key map " " 'self-insert-command)
|
||||||
map)))
|
map)))
|
||||||
(delete "" (completing-read-multiple
|
(completing-read-multiple prompt tag-list
|
||||||
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
|
nil nil initial-input
|
||||||
'notmuch-read-tag-changes-history))))
|
'notmuch-read-tag-changes-history)))
|
||||||
|
|
||||||
;;; Tagging
|
;;; Tagging
|
||||||
|
|
||||||
|
|
|
@ -179,7 +179,7 @@ Note that the author string should not contain whitespace
|
||||||
(:foreground "dark blue"))
|
(:foreground "dark blue"))
|
||||||
(t
|
(t
|
||||||
(:bold 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-tree
|
||||||
:group 'notmuch-faces)
|
:group 'notmuch-faces)
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ Note that the author string should not contain whitespace
|
||||||
|
|
||||||
(defface notmuch-tree-no-match-author-face
|
(defface notmuch-tree-no-match-author-face
|
||||||
nil
|
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-tree
|
||||||
:group 'notmuch-faces)
|
:group 'notmuch-faces)
|
||||||
|
|
||||||
|
@ -1191,11 +1191,11 @@ The arguments are:
|
||||||
(setq query (notmuch-read-query (concat "Notmuch "
|
(setq query (notmuch-read-query (concat "Notmuch "
|
||||||
(if unthreaded "unthreaded " "tree ")
|
(if unthreaded "unthreaded " "tree ")
|
||||||
"view search: "))))
|
"view search: "))))
|
||||||
(let ((buffer (get-buffer-create (generate-new-buffer-name
|
(let* ((name
|
||||||
(or buffer-name
|
(or buffer-name
|
||||||
(concat "*notmuch-"
|
(notmuch-search-buffer-title query
|
||||||
(if unthreaded "unthreaded-" "tree-")
|
(if unthreaded "unthreaded" "tree"))))
|
||||||
query "*")))))
|
(buffer (get-buffer-create (generate-new-buffer-name name)))
|
||||||
(inhibit-read-only t))
|
(inhibit-read-only t))
|
||||||
(pop-to-buffer-same-window buffer))
|
(pop-to-buffer-same-window buffer))
|
||||||
;; Don't track undo information for this buffer
|
;; Don't track undo information for this buffer
|
||||||
|
@ -1206,6 +1206,9 @@ The arguments are:
|
||||||
|
|
||||||
(defun notmuch-unthreaded (&optional query query-context target buffer-name
|
(defun notmuch-unthreaded (&optional query query-context target buffer-name
|
||||||
open-target)
|
open-target)
|
||||||
|
"Display threads matching QUERY in unthreaded view.
|
||||||
|
|
||||||
|
See function NOTMUCH-TREE for documentation of the arguments"
|
||||||
(interactive)
|
(interactive)
|
||||||
(notmuch-tree query query-context target buffer-name open-target t))
|
(notmuch-tree query query-context target buffer-name open-target t))
|
||||||
|
|
||||||
|
|
|
@ -535,12 +535,12 @@ thread."
|
||||||
(message "End of search results."))))
|
(message "End of search results."))))
|
||||||
|
|
||||||
(defun notmuch-tree-from-search-current-query ()
|
(defun notmuch-tree-from-search-current-query ()
|
||||||
"Call notmuch tree with the current query."
|
"Tree view of current query."
|
||||||
(interactive)
|
(interactive)
|
||||||
(notmuch-tree notmuch-search-query-string))
|
(notmuch-tree notmuch-search-query-string))
|
||||||
|
|
||||||
(defun notmuch-unthreaded-from-search-current-query ()
|
(defun notmuch-unthreaded-from-search-current-query ()
|
||||||
"Call notmuch tree with the current query."
|
"Unthreaded view of current query."
|
||||||
(interactive)
|
(interactive)
|
||||||
(notmuch-unthreaded notmuch-search-query-string))
|
(notmuch-unthreaded notmuch-search-query-string))
|
||||||
|
|
||||||
|
@ -880,6 +880,14 @@ sets the :orig-tag property."
|
||||||
(setq notmuch-search-target-thread "found")
|
(setq notmuch-search-target-thread "found")
|
||||||
(goto-char pos))))
|
(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)
|
(defun notmuch-search-process-filter (proc string)
|
||||||
"Process and filter the output of \"notmuch search\"."
|
"Process and filter the output of \"notmuch search\"."
|
||||||
(let ((results-buf (process-buffer proc))
|
(let ((results-buf (process-buffer proc))
|
||||||
|
@ -892,7 +900,9 @@ sets the :orig-tag property."
|
||||||
(goto-char (point-max))
|
(goto-char (point-max))
|
||||||
(insert string))
|
(insert string))
|
||||||
(notmuch-sexp-parse-partial-list 'notmuch-search-append-result
|
(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)
|
;;; Commands (and some helper functions used by them)
|
||||||
|
|
||||||
|
@ -905,7 +915,39 @@ See `notmuch-tag' for information on the format of TAG-CHANGES."
|
||||||
(notmuch-search-get-tags-region (point-min) (point-max)) "Tag all")))
|
(notmuch-search-get-tags-region (point-min) (point-max)) "Tag all")))
|
||||||
(notmuch-search-tag tag-changes (point-min) (point-max) t))
|
(notmuch-search-tag tag-changes (point-min) (point-max) t))
|
||||||
|
|
||||||
(defun notmuch-search-buffer-title (query)
|
(defcustom notmuch-search-buffer-name-format "*notmuch-%t-%s*"
|
||||||
|
"Format for the name of search results buffers.
|
||||||
|
|
||||||
|
In this spec, %s will be replaced by a description of the search
|
||||||
|
query and %t by its type (search, tree or unthreaded). The
|
||||||
|
buffer name is formatted using `format-spec': see its docstring
|
||||||
|
for additional parameters for the s and t format specifiers.
|
||||||
|
|
||||||
|
See also `notmuch-saved-search-buffer-name-format'"
|
||||||
|
:type 'string
|
||||||
|
:group 'notmuch-search)
|
||||||
|
|
||||||
|
(defcustom notmuch-saved-search-buffer-name-format "*notmuch-saved-%t-%s*"
|
||||||
|
"Format for the name of search results buffers for saved searches.
|
||||||
|
|
||||||
|
In this spec, %s will be replaced by the saved search name and %t
|
||||||
|
by its type (search, tree or unthreaded). The buffer name is
|
||||||
|
formatted using `format-spec': see its docstring for additional
|
||||||
|
parameters for the s and t format specifiers.
|
||||||
|
|
||||||
|
See also `notmuch-search-buffer-name-format'"
|
||||||
|
:type 'string
|
||||||
|
:group 'notmuch-search)
|
||||||
|
|
||||||
|
(defun notmuch-search-format-buffer-name (query type saved)
|
||||||
|
"Compose a buffer name for the given QUERY, TYPE (search, tree,
|
||||||
|
unthreaded) and whether it's SAVED (t or nil)."
|
||||||
|
(let ((fmt (if saved
|
||||||
|
notmuch-saved-search-buffer-name-format
|
||||||
|
notmuch-search-buffer-name-format)))
|
||||||
|
(format-spec fmt `((?t . ,(or type "search")) (?s . ,query)))))
|
||||||
|
|
||||||
|
(defun notmuch-search-buffer-title (query &optional type)
|
||||||
"Returns the title for a buffer with notmuch search results."
|
"Returns the title for a buffer with notmuch search results."
|
||||||
(let* ((saved-search
|
(let* ((saved-search
|
||||||
(let (longest
|
(let (longest
|
||||||
|
@ -920,19 +962,20 @@ See `notmuch-tag' for information on the format of TAG-CHANGES."
|
||||||
do (setq longest tuple))
|
do (setq longest tuple))
|
||||||
longest))
|
longest))
|
||||||
(saved-search-name (notmuch-saved-search-get saved-search :name))
|
(saved-search-name (notmuch-saved-search-get saved-search :name))
|
||||||
|
(saved-search-type (notmuch-saved-search-get saved-search :search-type))
|
||||||
(saved-search-query (notmuch-saved-search-get saved-search :query)))
|
(saved-search-query (notmuch-saved-search-get saved-search :query)))
|
||||||
(cond ((and saved-search (equal saved-search-query query))
|
(cond ((and saved-search (equal saved-search-query query))
|
||||||
;; Query is the same as saved search (ignoring case)
|
;; Query is the same as saved search (ignoring case)
|
||||||
(concat "*notmuch-saved-search-" saved-search-name "*"))
|
(notmuch-search-format-buffer-name saved-search-name
|
||||||
|
saved-search-type
|
||||||
|
t))
|
||||||
(saved-search
|
(saved-search
|
||||||
(concat "*notmuch-search-"
|
(let ((query (replace-regexp-in-string
|
||||||
(replace-regexp-in-string
|
|
||||||
(concat "^" (regexp-quote saved-search-query))
|
(concat "^" (regexp-quote saved-search-query))
|
||||||
(concat "[ " saved-search-name " ]")
|
(concat "[ " saved-search-name " ]")
|
||||||
query)
|
query)))
|
||||||
"*"))
|
(notmuch-search-format-buffer-name query saved-search-type t)))
|
||||||
(t
|
(t (notmuch-search-format-buffer-name query type nil)))))
|
||||||
(concat "*notmuch-search-" query "*")))))
|
|
||||||
|
|
||||||
(defun notmuch-read-query (prompt)
|
(defun notmuch-read-query (prompt)
|
||||||
"Read a notmuch-query from the minibuffer with completion.
|
"Read a notmuch-query from the minibuffer with completion.
|
||||||
|
@ -1036,8 +1079,7 @@ the configured default sort order."
|
||||||
(process-put proc 'parse-buf
|
(process-put proc 'parse-buf
|
||||||
(generate-new-buffer " *notmuch search parse*"))
|
(generate-new-buffer " *notmuch search parse*"))
|
||||||
(set-process-filter proc 'notmuch-search-process-filter)
|
(set-process-filter proc 'notmuch-search-process-filter)
|
||||||
(set-process-query-on-exit-flag proc nil))))
|
(set-process-query-on-exit-flag proc nil))))))
|
||||||
(run-hooks 'notmuch-search-hook)))
|
|
||||||
|
|
||||||
(defun notmuch-search-refresh-view ()
|
(defun notmuch-search-refresh-view ()
|
||||||
"Refresh the current view.
|
"Refresh the current view.
|
||||||
|
|
|
@ -32,7 +32,7 @@ notmuch_built_with (const char *name)
|
||||||
return HAVE_XAPIAN_DB_RETRY_LOCK;
|
return HAVE_XAPIAN_DB_RETRY_LOCK;
|
||||||
} else if (STRNCMP_LITERAL (name, "session_key") == 0) {
|
} else if (STRNCMP_LITERAL (name, "session_key") == 0) {
|
||||||
return true;
|
return true;
|
||||||
} else if (STRNCMP_LITERAL (name, "sexpr_query") == 0) {
|
} else if (STRNCMP_LITERAL (name, "sexp_queries") == 0) {
|
||||||
return HAVE_SFSEXP;
|
return HAVE_SFSEXP;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -435,11 +435,6 @@ _notmuch_config_load_from_file (notmuch_database_t *notmuch,
|
||||||
for (gchar **keys_p = keys; *keys_p; keys_p++) {
|
for (gchar **keys_p = keys; *keys_p; keys_p++) {
|
||||||
char *absolute_key = talloc_asprintf (notmuch, "%s.%s", *grp, *keys_p);
|
char *absolute_key = talloc_asprintf (notmuch, "%s.%s", *grp, *keys_p);
|
||||||
char *normalized_val;
|
char *normalized_val;
|
||||||
val = g_key_file_get_value (file, *grp, *keys_p, NULL);
|
|
||||||
if (! val) {
|
|
||||||
status = NOTMUCH_STATUS_FILE_ERROR;
|
|
||||||
goto DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we opened from a given path, do not overwrite it */
|
/* If we opened from a given path, do not overwrite it */
|
||||||
if (strcmp (absolute_key, "database.path") == 0 &&
|
if (strcmp (absolute_key, "database.path") == 0 &&
|
||||||
|
@ -447,6 +442,12 @@ _notmuch_config_load_from_file (notmuch_database_t *notmuch,
|
||||||
notmuch->xapian_db)
|
notmuch->xapian_db)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
val = g_key_file_get_string (file, *grp, *keys_p, NULL);
|
||||||
|
if (! val) {
|
||||||
|
status = NOTMUCH_STATUS_FILE_ERROR;
|
||||||
|
goto DONE;
|
||||||
|
}
|
||||||
|
|
||||||
normalized_val = _expand_path (notmuch, absolute_key, val);
|
normalized_val = _expand_path (notmuch, absolute_key, val);
|
||||||
_notmuch_string_map_set (notmuch->config, absolute_key, normalized_val);
|
_notmuch_string_map_set (notmuch->config, absolute_key, normalized_val);
|
||||||
g_free (val);
|
g_free (val);
|
||||||
|
@ -596,6 +597,8 @@ _notmuch_config_key_to_string (notmuch_config_key_t key)
|
||||||
return "user.name";
|
return "user.name";
|
||||||
case NOTMUCH_CONFIG_AUTOCOMMIT:
|
case NOTMUCH_CONFIG_AUTOCOMMIT:
|
||||||
return "database.autocommit";
|
return "database.autocommit";
|
||||||
|
case NOTMUCH_CONFIG_EXTRA_HEADERS:
|
||||||
|
return "show.extra_headers";
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -643,6 +646,7 @@ _notmuch_config_default (notmuch_database_t *notmuch, notmuch_config_key_t key)
|
||||||
return "";
|
return "";
|
||||||
case NOTMUCH_CONFIG_AUTOCOMMIT:
|
case NOTMUCH_CONFIG_AUTOCOMMIT:
|
||||||
return "8000";
|
return "8000";
|
||||||
|
case NOTMUCH_CONFIG_EXTRA_HEADERS:
|
||||||
case NOTMUCH_CONFIG_HOOK_DIR:
|
case NOTMUCH_CONFIG_HOOK_DIR:
|
||||||
case NOTMUCH_CONFIG_BACKUP_DIR:
|
case NOTMUCH_CONFIG_BACKUP_DIR:
|
||||||
case NOTMUCH_CONFIG_OTHER_EMAIL:
|
case NOTMUCH_CONFIG_OTHER_EMAIL:
|
||||||
|
@ -657,6 +661,10 @@ notmuch_status_t
|
||||||
_notmuch_config_load_defaults (notmuch_database_t *notmuch)
|
_notmuch_config_load_defaults (notmuch_database_t *notmuch)
|
||||||
{
|
{
|
||||||
notmuch_config_key_t key;
|
notmuch_config_key_t key;
|
||||||
|
notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (notmuch->config == NULL)
|
||||||
|
notmuch->config = _notmuch_string_map_create (notmuch);
|
||||||
|
|
||||||
for (key = NOTMUCH_CONFIG_FIRST;
|
for (key = NOTMUCH_CONFIG_FIRST;
|
||||||
key < NOTMUCH_CONFIG_LAST;
|
key < NOTMUCH_CONFIG_LAST;
|
||||||
|
@ -666,11 +674,14 @@ _notmuch_config_load_defaults (notmuch_database_t *notmuch)
|
||||||
|
|
||||||
val = _notmuch_string_map_get (notmuch->config, key_string);
|
val = _notmuch_string_map_get (notmuch->config, key_string);
|
||||||
if (! val) {
|
if (! val) {
|
||||||
|
if (key == NOTMUCH_CONFIG_MAIL_ROOT && (notmuch->params & NOTMUCH_PARAM_SPLIT))
|
||||||
|
status = NOTMUCH_STATUS_NO_MAIL_ROOT;
|
||||||
|
|
||||||
_notmuch_string_map_set (notmuch->config, key_string, _notmuch_config_default (notmuch,
|
_notmuch_string_map_set (notmuch->config, key_string, _notmuch_config_default (notmuch,
|
||||||
key));
|
key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NOTMUCH_STATUS_SUCCESS;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
|
|
|
@ -160,11 +160,12 @@ operator&= (_notmuch_features &a, _notmuch_features b)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configuration options for xapian database fields */
|
* Configuration options for xapian database fields */
|
||||||
typedef enum notmuch_field_flags {
|
typedef enum {
|
||||||
NOTMUCH_FIELD_NO_FLAGS = 0,
|
NOTMUCH_FIELD_NO_FLAGS = 0,
|
||||||
NOTMUCH_FIELD_EXTERNAL = 1 << 0,
|
NOTMUCH_FIELD_EXTERNAL = 1 << 0,
|
||||||
NOTMUCH_FIELD_PROBABILISTIC = 1 << 1,
|
NOTMUCH_FIELD_PROBABILISTIC = 1 << 1,
|
||||||
NOTMUCH_FIELD_PROCESSOR = 1 << 2,
|
NOTMUCH_FIELD_PROCESSOR = 1 << 2,
|
||||||
|
NOTMUCH_FIELD_STRIP_TRAILING_SLASH = 1 << 3,
|
||||||
} notmuch_field_flag_t;
|
} notmuch_field_flag_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -191,12 +192,17 @@ operator& (notmuch_field_flag_t a, notmuch_field_flag_t b)
|
||||||
Xapian::QueryParser::FLAG_PURE_NOT)
|
Xapian::QueryParser::FLAG_PURE_NOT)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Which parameters were explicit when the database was opened */
|
* explicit and implied parameters to open */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NOTMUCH_PARAM_NONE = 0,
|
NOTMUCH_PARAM_NONE = 0,
|
||||||
|
/* database passed explicitely */
|
||||||
NOTMUCH_PARAM_DATABASE = 1 << 0,
|
NOTMUCH_PARAM_DATABASE = 1 << 0,
|
||||||
|
/* config file passed explicitely */
|
||||||
NOTMUCH_PARAM_CONFIG = 1 << 1,
|
NOTMUCH_PARAM_CONFIG = 1 << 1,
|
||||||
|
/* profile name passed explicitely */
|
||||||
NOTMUCH_PARAM_PROFILE = 1 << 2,
|
NOTMUCH_PARAM_PROFILE = 1 << 2,
|
||||||
|
/* split (e.g. XDG) configuration */
|
||||||
|
NOTMUCH_PARAM_SPLIT = 1 << 3,
|
||||||
} notmuch_open_param_t;
|
} notmuch_open_param_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -374,5 +380,10 @@ notmuch_status_t
|
||||||
_notmuch_sexp_string_to_xapian_query (notmuch_database_t *notmuch, const char *querystr,
|
_notmuch_sexp_string_to_xapian_query (notmuch_database_t *notmuch, const char *querystr,
|
||||||
Xapian::Query &output);
|
Xapian::Query &output);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* parse-time-vrp.h */
|
||||||
|
notmuch_status_t
|
||||||
|
_notmuch_date_strings_to_query (Xapian::valueno slot, const std::string &from, const std::string &to,
|
||||||
|
Xapian::Query &output, std::string &msg);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -311,6 +311,8 @@ notmuch_status_to_string (notmuch_status_t status)
|
||||||
return "Database exists, not recreated";
|
return "Database exists, not recreated";
|
||||||
case NOTMUCH_STATUS_BAD_QUERY_SYNTAX:
|
case NOTMUCH_STATUS_BAD_QUERY_SYNTAX:
|
||||||
return "Syntax error in query";
|
return "Syntax error in query";
|
||||||
|
case NOTMUCH_STATUS_NO_MAIL_ROOT:
|
||||||
|
return "No mail root found";
|
||||||
default:
|
default:
|
||||||
case NOTMUCH_STATUS_LAST_STATUS:
|
case NOTMUCH_STATUS_LAST_STATUS:
|
||||||
return "Unknown error status value";
|
return "Unknown error status value";
|
||||||
|
@ -590,8 +592,10 @@ notmuch_database_compact (const char *path,
|
||||||
notmuch_database_t *notmuch = NULL;
|
notmuch_database_t *notmuch = NULL;
|
||||||
char *message = NULL;
|
char *message = NULL;
|
||||||
|
|
||||||
ret = notmuch_database_open_verbose (path,
|
ret = notmuch_database_open_with_config (path,
|
||||||
NOTMUCH_DATABASE_MODE_READ_WRITE,
|
NOTMUCH_DATABASE_MODE_READ_WRITE,
|
||||||
|
"",
|
||||||
|
NULL,
|
||||||
¬much,
|
¬much,
|
||||||
&message);
|
&message);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -751,6 +755,8 @@ notmuch_database_destroy (notmuch_database_t *notmuch)
|
||||||
notmuch->date_range_processor = NULL;
|
notmuch->date_range_processor = NULL;
|
||||||
delete notmuch->last_mod_range_processor;
|
delete notmuch->last_mod_range_processor;
|
||||||
notmuch->last_mod_range_processor = NULL;
|
notmuch->last_mod_range_processor = NULL;
|
||||||
|
delete notmuch->stemmer;
|
||||||
|
notmuch->stemmer = NULL;
|
||||||
|
|
||||||
talloc_free (notmuch);
|
talloc_free (notmuch);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
|
|
||||||
#include "notmuch-private.h"
|
#include "notmuch-private.h"
|
||||||
|
|
||||||
|
struct _notmuch_indexopts {
|
||||||
|
_notmuch_crypto_t crypto;
|
||||||
|
};
|
||||||
|
|
||||||
notmuch_indexopts_t *
|
notmuch_indexopts_t *
|
||||||
notmuch_database_get_default_indexopts (notmuch_database_t *db)
|
notmuch_database_get_default_indexopts (notmuch_database_t *db)
|
||||||
{
|
{
|
||||||
|
|
|
@ -121,7 +121,7 @@ typedef enum {
|
||||||
*/
|
*/
|
||||||
#define NOTMUCH_MESSAGE_ID_MAX (200 - sizeof (NOTMUCH_METADATA_THREAD_ID_PREFIX))
|
#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. */
|
/* First, copy all the public status values. */
|
||||||
NOTMUCH_PRIVATE_STATUS_SUCCESS = NOTMUCH_STATUS_SUCCESS,
|
NOTMUCH_PRIVATE_STATUS_SUCCESS = NOTMUCH_STATUS_SUCCESS,
|
||||||
NOTMUCH_PRIVATE_STATUS_OUT_OF_MEMORY = NOTMUCH_STATUS_OUT_OF_MEMORY,
|
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)
|
(notmuch_status_t) private_status)
|
||||||
|
|
||||||
/* Flags shared by various lookup functions. */
|
/* Flags shared by various lookup functions. */
|
||||||
typedef enum _notmuch_find_flags {
|
typedef enum {
|
||||||
/* Lookup without creating any documents. This is the default
|
/* Lookup without creating any documents. This is the default
|
||||||
* behavior. */
|
* behavior. */
|
||||||
NOTMUCH_FIND_LOOKUP = 0,
|
NOTMUCH_FIND_LOOKUP = 0,
|
||||||
|
@ -711,9 +711,7 @@ _notmuch_thread_create (void *ctx,
|
||||||
|
|
||||||
/* indexopts.c */
|
/* indexopts.c */
|
||||||
|
|
||||||
struct _notmuch_indexopts {
|
struct _notmuch_indexopts;
|
||||||
_notmuch_crypto_t crypto;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define CONFIG_HEADER_PREFIX "index.header."
|
#define CONFIG_HEADER_PREFIX "index.header."
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ NOTMUCH_BEGIN_DECLS
|
||||||
* version in Makefile.local.
|
* version in Makefile.local.
|
||||||
*/
|
*/
|
||||||
#define LIBNOTMUCH_MAJOR_VERSION 5
|
#define LIBNOTMUCH_MAJOR_VERSION 5
|
||||||
#define LIBNOTMUCH_MINOR_VERSION 5
|
#define LIBNOTMUCH_MINOR_VERSION 6
|
||||||
#define LIBNOTMUCH_MICRO_VERSION 0
|
#define LIBNOTMUCH_MICRO_VERSION 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ typedef int notmuch_bool_t;
|
||||||
* A zero value (NOTMUCH_STATUS_SUCCESS) indicates that the function
|
* A zero value (NOTMUCH_STATUS_SUCCESS) indicates that the function
|
||||||
* completed without error. Any other value indicates an error.
|
* completed without error. Any other value indicates an error.
|
||||||
*/
|
*/
|
||||||
typedef enum _notmuch_status {
|
typedef enum {
|
||||||
/**
|
/**
|
||||||
* No error occurred.
|
* No error occurred.
|
||||||
*/
|
*/
|
||||||
|
@ -224,6 +224,10 @@ typedef enum _notmuch_status {
|
||||||
* Syntax error in query
|
* Syntax error in query
|
||||||
*/
|
*/
|
||||||
NOTMUCH_STATUS_BAD_QUERY_SYNTAX,
|
NOTMUCH_STATUS_BAD_QUERY_SYNTAX,
|
||||||
|
/**
|
||||||
|
* No mail root could be deduced from parameters and environment
|
||||||
|
*/
|
||||||
|
NOTMUCH_STATUS_NO_MAIL_ROOT,
|
||||||
/**
|
/**
|
||||||
* Not an actual status value. Just a way to find out how many
|
* Not an actual status value. Just a way to find out how many
|
||||||
* valid status values there are.
|
* valid status values there are.
|
||||||
|
@ -323,7 +327,7 @@ typedef enum {
|
||||||
* config_path="" and error_message=NULL
|
* config_path="" and error_message=NULL
|
||||||
* @deprecated Deprecated as of libnotmuch 5.4 (notmuch 0.32)
|
* @deprecated Deprecated as of libnotmuch 5.4 (notmuch 0.32)
|
||||||
*/
|
*/
|
||||||
/* NOTMUCH_DEPRECATED(5, 4) */
|
NOTMUCH_DEPRECATED(5, 4)
|
||||||
notmuch_status_t
|
notmuch_status_t
|
||||||
notmuch_database_open (const char *path,
|
notmuch_database_open (const char *path,
|
||||||
notmuch_database_mode_t mode,
|
notmuch_database_mode_t mode,
|
||||||
|
@ -335,7 +339,7 @@ notmuch_database_open (const char *path,
|
||||||
* @deprecated Deprecated as of libnotmuch 5.4 (notmuch 0.32)
|
* @deprecated Deprecated as of libnotmuch 5.4 (notmuch 0.32)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
/* NOTMUCH_DEPRECATED(5, 4) */
|
NOTMUCH_DEPRECATED(5, 4)
|
||||||
notmuch_status_t
|
notmuch_status_t
|
||||||
notmuch_database_open_verbose (const char *path,
|
notmuch_database_open_verbose (const char *path,
|
||||||
notmuch_database_mode_t mode,
|
notmuch_database_mode_t mode,
|
||||||
|
@ -1686,7 +1690,7 @@ notmuch_message_reindex (notmuch_message_t *message,
|
||||||
/**
|
/**
|
||||||
* Message flags.
|
* Message flags.
|
||||||
*/
|
*/
|
||||||
typedef enum _notmuch_message_flag {
|
typedef enum {
|
||||||
NOTMUCH_MESSAGE_FLAG_MATCH,
|
NOTMUCH_MESSAGE_FLAG_MATCH,
|
||||||
NOTMUCH_MESSAGE_FLAG_EXCLUDED,
|
NOTMUCH_MESSAGE_FLAG_EXCLUDED,
|
||||||
|
|
||||||
|
@ -2532,7 +2536,7 @@ notmuch_config_list_destroy (notmuch_config_list_t *config_list);
|
||||||
/**
|
/**
|
||||||
* Configuration keys known to libnotmuch
|
* Configuration keys known to libnotmuch
|
||||||
*/
|
*/
|
||||||
typedef enum _notmuch_config_key {
|
typedef enum {
|
||||||
NOTMUCH_CONFIG_FIRST,
|
NOTMUCH_CONFIG_FIRST,
|
||||||
NOTMUCH_CONFIG_DATABASE_PATH = NOTMUCH_CONFIG_FIRST,
|
NOTMUCH_CONFIG_DATABASE_PATH = NOTMUCH_CONFIG_FIRST,
|
||||||
NOTMUCH_CONFIG_MAIL_ROOT,
|
NOTMUCH_CONFIG_MAIL_ROOT,
|
||||||
|
@ -2546,6 +2550,7 @@ typedef enum _notmuch_config_key {
|
||||||
NOTMUCH_CONFIG_OTHER_EMAIL,
|
NOTMUCH_CONFIG_OTHER_EMAIL,
|
||||||
NOTMUCH_CONFIG_USER_NAME,
|
NOTMUCH_CONFIG_USER_NAME,
|
||||||
NOTMUCH_CONFIG_AUTOCOMMIT,
|
NOTMUCH_CONFIG_AUTOCOMMIT,
|
||||||
|
NOTMUCH_CONFIG_EXTRA_HEADERS,
|
||||||
NOTMUCH_CONFIG_LAST
|
NOTMUCH_CONFIG_LAST
|
||||||
} notmuch_config_key_t;
|
} notmuch_config_key_t;
|
||||||
|
|
||||||
|
|
63
lib/open.cc
63
lib/open.cc
|
@ -19,9 +19,8 @@ notmuch_database_open (const char *path,
|
||||||
char *status_string = NULL;
|
char *status_string = NULL;
|
||||||
notmuch_status_t status;
|
notmuch_status_t status;
|
||||||
|
|
||||||
status = notmuch_database_open_verbose (path, mode, database,
|
status = notmuch_database_open_with_config (path, mode, "", NULL,
|
||||||
&status_string);
|
database, &status_string);
|
||||||
|
|
||||||
if (status_string) {
|
if (status_string) {
|
||||||
fputs (status_string, stderr);
|
fputs (status_string, stderr);
|
||||||
free (status_string);
|
free (status_string);
|
||||||
|
@ -187,11 +186,10 @@ _db_dir_exists (const char *database_path, char **message)
|
||||||
}
|
}
|
||||||
|
|
||||||
static notmuch_status_t
|
static notmuch_status_t
|
||||||
_choose_database_path (void *ctx,
|
_choose_database_path (notmuch_database_t *notmuch,
|
||||||
const char *profile,
|
const char *profile,
|
||||||
GKeyFile *key_file,
|
GKeyFile *key_file,
|
||||||
const char **database_path,
|
const char **database_path,
|
||||||
bool *split,
|
|
||||||
char **message)
|
char **message)
|
||||||
{
|
{
|
||||||
if (! *database_path) {
|
if (! *database_path) {
|
||||||
|
@ -199,24 +197,24 @@ _choose_database_path (void *ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! *database_path && key_file) {
|
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) {
|
||||||
if (path[0] == '/')
|
if (path[0] == '/')
|
||||||
*database_path = talloc_strdup (ctx, path);
|
*database_path = talloc_strdup (notmuch, path);
|
||||||
else
|
else
|
||||||
*database_path = talloc_asprintf (ctx, "%s/%s", getenv ("HOME"), path);
|
*database_path = talloc_asprintf (notmuch, "%s/%s", getenv ("HOME"), path);
|
||||||
g_free (path);
|
g_free (path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (! *database_path) {
|
if (! *database_path) {
|
||||||
notmuch_status_t status;
|
notmuch_status_t status;
|
||||||
|
|
||||||
*database_path = _xdg_dir (ctx, "XDG_DATA_HOME", ".local/share", profile);
|
*database_path = _xdg_dir (notmuch, "XDG_DATA_HOME", ".local/share", profile);
|
||||||
status = _db_dir_exists (*database_path, message);
|
status = _db_dir_exists (*database_path, message);
|
||||||
if (status) {
|
if (status) {
|
||||||
*database_path = NULL;
|
*database_path = NULL;
|
||||||
} else {
|
} else {
|
||||||
*split = true;
|
notmuch->params |= NOTMUCH_PARAM_SPLIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +225,7 @@ _choose_database_path (void *ctx,
|
||||||
if (! *database_path) {
|
if (! *database_path) {
|
||||||
notmuch_status_t status;
|
notmuch_status_t status;
|
||||||
|
|
||||||
*database_path = talloc_asprintf (ctx, "%s/mail", getenv ("HOME"));
|
*database_path = talloc_asprintf (notmuch, "%s/mail", getenv ("HOME"));
|
||||||
status = _db_dir_exists (*database_path, message);
|
status = _db_dir_exists (*database_path, message);
|
||||||
if (status) {
|
if (status) {
|
||||||
*database_path = NULL;
|
*database_path = NULL;
|
||||||
|
@ -511,11 +509,9 @@ notmuch_database_open_with_config (const char *database_path,
|
||||||
char **status_string)
|
char **status_string)
|
||||||
{
|
{
|
||||||
notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
|
notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
|
||||||
void *local = talloc_new (NULL);
|
|
||||||
notmuch_database_t *notmuch = NULL;
|
notmuch_database_t *notmuch = NULL;
|
||||||
char *message = NULL;
|
char *message = NULL;
|
||||||
GKeyFile *key_file = NULL;
|
GKeyFile *key_file = NULL;
|
||||||
bool split = false;
|
|
||||||
|
|
||||||
_notmuch_init ();
|
_notmuch_init ();
|
||||||
|
|
||||||
|
@ -531,8 +527,8 @@ notmuch_database_open_with_config (const char *database_path,
|
||||||
goto DONE;
|
goto DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status = _choose_database_path (local, profile, key_file,
|
if ((status = _choose_database_path (notmuch, profile, key_file,
|
||||||
&database_path, &split,
|
&database_path,
|
||||||
&message)))
|
&message)))
|
||||||
goto DONE;
|
goto DONE;
|
||||||
|
|
||||||
|
@ -550,8 +546,6 @@ notmuch_database_open_with_config (const char *database_path,
|
||||||
status = _finish_open (notmuch, profile, mode, key_file, &message);
|
status = _finish_open (notmuch, profile, mode, key_file, &message);
|
||||||
|
|
||||||
DONE:
|
DONE:
|
||||||
talloc_free (local);
|
|
||||||
|
|
||||||
if (key_file)
|
if (key_file)
|
||||||
g_key_file_free (key_file);
|
g_key_file_free (key_file);
|
||||||
|
|
||||||
|
@ -613,9 +607,7 @@ notmuch_database_create_with_config (const char *database_path,
|
||||||
const char *notmuch_path = NULL;
|
const char *notmuch_path = NULL;
|
||||||
char *message = NULL;
|
char *message = NULL;
|
||||||
GKeyFile *key_file = NULL;
|
GKeyFile *key_file = NULL;
|
||||||
void *local = talloc_new (NULL);
|
|
||||||
int err;
|
int err;
|
||||||
bool split = false;
|
|
||||||
|
|
||||||
_notmuch_init ();
|
_notmuch_init ();
|
||||||
|
|
||||||
|
@ -631,8 +623,8 @@ notmuch_database_create_with_config (const char *database_path,
|
||||||
goto DONE;
|
goto DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status = _choose_database_path (local, profile, key_file,
|
if ((status = _choose_database_path (notmuch, profile, key_file,
|
||||||
&database_path, &split, &message)))
|
&database_path, &message)))
|
||||||
goto DONE;
|
goto DONE;
|
||||||
|
|
||||||
status = _db_dir_exists (database_path, &message);
|
status = _db_dir_exists (database_path, &message);
|
||||||
|
@ -641,39 +633,36 @@ notmuch_database_create_with_config (const char *database_path,
|
||||||
|
|
||||||
_set_database_path (notmuch, database_path);
|
_set_database_path (notmuch, database_path);
|
||||||
|
|
||||||
if (key_file && ! split) {
|
if (key_file && ! (notmuch->params & NOTMUCH_PARAM_SPLIT)) {
|
||||||
char *mail_root = notmuch_canonicalize_file_name (
|
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);
|
char *db_path = notmuch_canonicalize_file_name (database_path);
|
||||||
|
|
||||||
split = (mail_root && (0 != strcmp (mail_root, db_path)));
|
if (mail_root && (0 != strcmp (mail_root, db_path)))
|
||||||
|
notmuch->params |= NOTMUCH_PARAM_SPLIT;
|
||||||
|
|
||||||
free (mail_root);
|
free (mail_root);
|
||||||
free (db_path);
|
free (db_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (split) {
|
if (notmuch->params & NOTMUCH_PARAM_SPLIT) {
|
||||||
notmuch_path = database_path;
|
notmuch_path = database_path;
|
||||||
} else {
|
} else {
|
||||||
if (! (notmuch_path = talloc_asprintf (local, "%s/%s", database_path, ".notmuch"))) {
|
if (! (notmuch_path = talloc_asprintf (notmuch, "%s/%s", database_path, ".notmuch"))) {
|
||||||
status = NOTMUCH_STATUS_OUT_OF_MEMORY;
|
status = NOTMUCH_STATUS_OUT_OF_MEMORY;
|
||||||
goto DONE;
|
goto DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mkdir (notmuch_path, 0755);
|
err = mkdir (notmuch_path, 0755);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (errno == EEXIST) {
|
if (errno != EEXIST) {
|
||||||
status = NOTMUCH_STATUS_DATABASE_EXISTS;
|
|
||||||
talloc_free (notmuch);
|
|
||||||
notmuch = NULL;
|
|
||||||
} else {
|
|
||||||
IGNORE_RESULT (asprintf (&message, "Error: Cannot create directory %s: %s.\n",
|
IGNORE_RESULT (asprintf (&message, "Error: Cannot create directory %s: %s.\n",
|
||||||
notmuch_path, strerror (errno)));
|
notmuch_path, strerror (errno)));
|
||||||
status = NOTMUCH_STATUS_FILE_ERROR;
|
status = NOTMUCH_STATUS_FILE_ERROR;
|
||||||
}
|
|
||||||
goto DONE;
|
goto DONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (! (notmuch->xapian_path = talloc_asprintf (notmuch, "%s/%s", notmuch_path, "xapian"))) {
|
if (! (notmuch->xapian_path = talloc_asprintf (notmuch, "%s/%s", notmuch_path, "xapian"))) {
|
||||||
status = NOTMUCH_STATUS_OUT_OF_MEMORY;
|
status = NOTMUCH_STATUS_OUT_OF_MEMORY;
|
||||||
|
@ -712,8 +701,6 @@ notmuch_database_create_with_config (const char *database_path,
|
||||||
}
|
}
|
||||||
|
|
||||||
DONE:
|
DONE:
|
||||||
talloc_free (local);
|
|
||||||
|
|
||||||
if (key_file)
|
if (key_file)
|
||||||
g_key_file_free (key_file);
|
g_key_file_free (key_file);
|
||||||
|
|
||||||
|
@ -813,11 +800,9 @@ notmuch_database_load_config (const char *database_path,
|
||||||
char **status_string)
|
char **status_string)
|
||||||
{
|
{
|
||||||
notmuch_status_t status = NOTMUCH_STATUS_SUCCESS, warning = NOTMUCH_STATUS_SUCCESS;
|
notmuch_status_t status = NOTMUCH_STATUS_SUCCESS, warning = NOTMUCH_STATUS_SUCCESS;
|
||||||
void *local = talloc_new (NULL);
|
|
||||||
notmuch_database_t *notmuch = NULL;
|
notmuch_database_t *notmuch = NULL;
|
||||||
char *message = NULL;
|
char *message = NULL;
|
||||||
GKeyFile *key_file = NULL;
|
GKeyFile *key_file = NULL;
|
||||||
bool split = false;
|
|
||||||
|
|
||||||
_notmuch_init ();
|
_notmuch_init ();
|
||||||
|
|
||||||
|
@ -839,8 +824,8 @@ notmuch_database_load_config (const char *database_path,
|
||||||
goto DONE;
|
goto DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = _choose_database_path (local, profile, key_file,
|
status = _choose_database_path (notmuch, profile, key_file,
|
||||||
&database_path, &split, &message);
|
&database_path, &message);
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case NOTMUCH_STATUS_NO_DATABASE:
|
case NOTMUCH_STATUS_NO_DATABASE:
|
||||||
case NOTMUCH_STATUS_SUCCESS:
|
case NOTMUCH_STATUS_SUCCESS:
|
||||||
|
@ -875,8 +860,6 @@ notmuch_database_load_config (const char *database_path,
|
||||||
goto DONE;
|
goto DONE;
|
||||||
|
|
||||||
DONE:
|
DONE:
|
||||||
talloc_free (local);
|
|
||||||
|
|
||||||
if (status_string)
|
if (status_string)
|
||||||
*status_string = message;
|
*status_string = message;
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,8 @@ typedef enum {
|
||||||
SEXP_FLAG_EXPAND = 1 << 6,
|
SEXP_FLAG_EXPAND = 1 << 6,
|
||||||
SEXP_FLAG_DO_EXPAND = 1 << 7,
|
SEXP_FLAG_DO_EXPAND = 1 << 7,
|
||||||
SEXP_FLAG_ORPHAN = 1 << 8,
|
SEXP_FLAG_ORPHAN = 1 << 8,
|
||||||
|
SEXP_FLAG_RANGE = 1 << 9,
|
||||||
|
SEXP_FLAG_PATHNAME = 1 << 10,
|
||||||
} _sexp_flag_t;
|
} _sexp_flag_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -66,16 +68,21 @@ static _sexp_prefix_t prefixes[] =
|
||||||
SEXP_FLAG_FIELD | SEXP_FLAG_WILDCARD | SEXP_FLAG_EXPAND },
|
SEXP_FLAG_FIELD | SEXP_FLAG_WILDCARD | SEXP_FLAG_EXPAND },
|
||||||
{ "body", Xapian::Query::OP_AND, Xapian::Query::MatchAll,
|
{ "body", Xapian::Query::OP_AND, Xapian::Query::MatchAll,
|
||||||
SEXP_FLAG_FIELD },
|
SEXP_FLAG_FIELD },
|
||||||
|
{ "date", Xapian::Query::OP_INVALID, Xapian::Query::MatchAll,
|
||||||
|
SEXP_FLAG_RANGE },
|
||||||
{ "from", Xapian::Query::OP_AND, Xapian::Query::MatchAll,
|
{ "from", Xapian::Query::OP_AND, Xapian::Query::MatchAll,
|
||||||
SEXP_FLAG_FIELD | SEXP_FLAG_WILDCARD | SEXP_FLAG_REGEX | SEXP_FLAG_EXPAND },
|
SEXP_FLAG_FIELD | SEXP_FLAG_WILDCARD | SEXP_FLAG_REGEX | SEXP_FLAG_EXPAND },
|
||||||
{ "folder", Xapian::Query::OP_OR, Xapian::Query::MatchNothing,
|
{ "folder", Xapian::Query::OP_OR, Xapian::Query::MatchNothing,
|
||||||
SEXP_FLAG_FIELD | SEXP_FLAG_BOOLEAN | SEXP_FLAG_WILDCARD | SEXP_FLAG_REGEX | SEXP_FLAG_EXPAND },
|
SEXP_FLAG_FIELD | SEXP_FLAG_BOOLEAN | SEXP_FLAG_WILDCARD | SEXP_FLAG_REGEX | SEXP_FLAG_EXPAND |
|
||||||
|
SEXP_FLAG_PATHNAME },
|
||||||
{ "id", Xapian::Query::OP_OR, Xapian::Query::MatchNothing,
|
{ "id", Xapian::Query::OP_OR, Xapian::Query::MatchNothing,
|
||||||
SEXP_FLAG_FIELD | SEXP_FLAG_BOOLEAN | SEXP_FLAG_WILDCARD | SEXP_FLAG_REGEX },
|
SEXP_FLAG_FIELD | SEXP_FLAG_BOOLEAN | SEXP_FLAG_WILDCARD | SEXP_FLAG_REGEX },
|
||||||
{ "infix", Xapian::Query::OP_INVALID, Xapian::Query::MatchAll,
|
{ "infix", Xapian::Query::OP_INVALID, Xapian::Query::MatchAll,
|
||||||
SEXP_FLAG_SINGLE | SEXP_FLAG_ORPHAN },
|
SEXP_FLAG_SINGLE | SEXP_FLAG_ORPHAN },
|
||||||
{ "is", Xapian::Query::OP_AND, Xapian::Query::MatchAll,
|
{ "is", Xapian::Query::OP_AND, Xapian::Query::MatchAll,
|
||||||
SEXP_FLAG_FIELD | SEXP_FLAG_BOOLEAN | SEXP_FLAG_WILDCARD | SEXP_FLAG_REGEX | SEXP_FLAG_EXPAND },
|
SEXP_FLAG_FIELD | SEXP_FLAG_BOOLEAN | SEXP_FLAG_WILDCARD | SEXP_FLAG_REGEX | SEXP_FLAG_EXPAND },
|
||||||
|
{ "lastmod", Xapian::Query::OP_INVALID, Xapian::Query::MatchAll,
|
||||||
|
SEXP_FLAG_RANGE },
|
||||||
{ "matching", Xapian::Query::OP_AND, Xapian::Query::MatchAll,
|
{ "matching", Xapian::Query::OP_AND, Xapian::Query::MatchAll,
|
||||||
SEXP_FLAG_DO_EXPAND },
|
SEXP_FLAG_DO_EXPAND },
|
||||||
{ "mid", Xapian::Query::OP_OR, Xapian::Query::MatchNothing,
|
{ "mid", Xapian::Query::OP_OR, Xapian::Query::MatchNothing,
|
||||||
|
@ -89,7 +96,8 @@ static _sexp_prefix_t prefixes[] =
|
||||||
{ "or", Xapian::Query::OP_OR, Xapian::Query::MatchNothing,
|
{ "or", Xapian::Query::OP_OR, Xapian::Query::MatchNothing,
|
||||||
SEXP_FLAG_NONE },
|
SEXP_FLAG_NONE },
|
||||||
{ "path", Xapian::Query::OP_OR, Xapian::Query::MatchNothing,
|
{ "path", Xapian::Query::OP_OR, Xapian::Query::MatchNothing,
|
||||||
SEXP_FLAG_FIELD | SEXP_FLAG_BOOLEAN | SEXP_FLAG_WILDCARD | SEXP_FLAG_REGEX },
|
SEXP_FLAG_FIELD | SEXP_FLAG_BOOLEAN | SEXP_FLAG_WILDCARD | SEXP_FLAG_REGEX |
|
||||||
|
SEXP_FLAG_PATHNAME },
|
||||||
{ "property", Xapian::Query::OP_AND, Xapian::Query::MatchAll,
|
{ "property", Xapian::Query::OP_AND, Xapian::Query::MatchAll,
|
||||||
SEXP_FLAG_FIELD | SEXP_FLAG_BOOLEAN | SEXP_FLAG_WILDCARD | SEXP_FLAG_REGEX | SEXP_FLAG_EXPAND },
|
SEXP_FLAG_FIELD | SEXP_FLAG_BOOLEAN | SEXP_FLAG_WILDCARD | SEXP_FLAG_REGEX | SEXP_FLAG_EXPAND },
|
||||||
{ "query", Xapian::Query::OP_INVALID, Xapian::Query::MatchNothing,
|
{ "query", Xapian::Query::OP_INVALID, Xapian::Query::MatchNothing,
|
||||||
|
@ -446,6 +454,79 @@ _sexp_expand_param (notmuch_database_t *notmuch, const _sexp_prefix_t *parent,
|
||||||
return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
|
return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static notmuch_status_t
|
||||||
|
_sexp_parse_range (notmuch_database_t *notmuch, const _sexp_prefix_t *prefix,
|
||||||
|
const sexp_t *sx, Xapian::Query &output)
|
||||||
|
{
|
||||||
|
const char *from, *to;
|
||||||
|
std::string msg;
|
||||||
|
|
||||||
|
/* empty range matches everything */
|
||||||
|
if (! sx) {
|
||||||
|
output = Xapian::Query::MatchAll;
|
||||||
|
return NOTMUCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sx->ty == SEXP_LIST) {
|
||||||
|
_notmuch_database_log (notmuch, "expected atom as first argument of '%s'\n", prefix->name);
|
||||||
|
return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
from = sx->val;
|
||||||
|
to = from;
|
||||||
|
|
||||||
|
if (sx->next) {
|
||||||
|
if (sx->next->ty == SEXP_LIST) {
|
||||||
|
_notmuch_database_log (notmuch, "expected atom as second argument of '%s'\n",
|
||||||
|
prefix->name);
|
||||||
|
return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sx->next->next) {
|
||||||
|
_notmuch_database_log (notmuch, "'%s' expects maximum of two arguments\n", prefix->name);
|
||||||
|
return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
to = sx->next->val;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp (prefix->name, "date") == 0) {
|
||||||
|
notmuch_status_t status;
|
||||||
|
status = _notmuch_date_strings_to_query (NOTMUCH_VALUE_TIMESTAMP, from, to, output, msg);
|
||||||
|
if (status) {
|
||||||
|
if (! msg.empty ())
|
||||||
|
_notmuch_database_log (notmuch, "%s\n", msg.c_str ());
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp (prefix->name, "lastmod") == 0) {
|
||||||
|
long from_idx, to_idx;
|
||||||
|
|
||||||
|
try {
|
||||||
|
from_idx = std::stol (from);
|
||||||
|
} catch (std::logic_error &e) {
|
||||||
|
_notmuch_database_log (notmuch, "bad 'from' revision: '%s'\n", from);
|
||||||
|
return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
to_idx = std::stol (to);
|
||||||
|
} catch (std::logic_error &e) {
|
||||||
|
_notmuch_database_log (notmuch, "bad 'to' revision: '%s'\n", to);
|
||||||
|
return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
output = Xapian::Query (Xapian::Query::OP_VALUE_RANGE, NOTMUCH_VALUE_LAST_MOD,
|
||||||
|
Xapian::sortable_serialise (from_idx),
|
||||||
|
Xapian::sortable_serialise (to_idx));
|
||||||
|
return NOTMUCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
_notmuch_database_log (notmuch, "unimplimented range prefix: '%s'\n", prefix->name);
|
||||||
|
return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
/* Here we expect the s-expression to be a proper list, with first
|
/* Here we expect the s-expression to be a proper list, with first
|
||||||
* element defining and operation, or as a special case the empty
|
* element defining and operation, or as a special case the empty
|
||||||
* list */
|
* list */
|
||||||
|
@ -467,8 +548,13 @@ _sexp_to_xapian_query (notmuch_database_t *notmuch, const _sexp_prefix_t *parent
|
||||||
return _sexp_parse_wildcard (notmuch, parent, env, "", output);
|
return _sexp_parse_wildcard (notmuch, parent, env, "", output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *atom = sx->val;
|
||||||
|
|
||||||
|
if (parent && parent->flags & SEXP_FLAG_PATHNAME)
|
||||||
|
strip_trailing (atom, '/');
|
||||||
|
|
||||||
if (parent && (parent->flags & SEXP_FLAG_BOOLEAN)) {
|
if (parent && (parent->flags & SEXP_FLAG_BOOLEAN)) {
|
||||||
output = Xapian::Query (term_prefix + sx->val);
|
output = Xapian::Query (term_prefix + atom);
|
||||||
return NOTMUCH_STATUS_SUCCESS;
|
return NOTMUCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,7 +605,7 @@ _sexp_to_xapian_query (notmuch_database_t *notmuch, const _sexp_prefix_t *parent
|
||||||
|
|
||||||
for (_sexp_prefix_t *prefix = prefixes; prefix && prefix->name; prefix++) {
|
for (_sexp_prefix_t *prefix = prefixes; prefix && prefix->name; prefix++) {
|
||||||
if (strcmp (prefix->name, sx->list->val) == 0) {
|
if (strcmp (prefix->name, sx->list->val) == 0) {
|
||||||
if (prefix->flags & SEXP_FLAG_FIELD) {
|
if (prefix->flags & (SEXP_FLAG_FIELD | SEXP_FLAG_RANGE)) {
|
||||||
if (parent) {
|
if (parent) {
|
||||||
_notmuch_database_log (notmuch, "nested field: '%s' inside '%s'\n",
|
_notmuch_database_log (notmuch, "nested field: '%s' inside '%s'\n",
|
||||||
prefix->name, parent->name);
|
prefix->name, parent->name);
|
||||||
|
@ -541,6 +627,9 @@ _sexp_to_xapian_query (notmuch_database_t *notmuch, const _sexp_prefix_t *parent
|
||||||
return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
|
return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prefix->flags & SEXP_FLAG_RANGE)
|
||||||
|
return _sexp_parse_range (notmuch, prefix, sx->list->next, output);
|
||||||
|
|
||||||
if (strcmp (prefix->name, "infix") == 0) {
|
if (strcmp (prefix->name, "infix") == 0) {
|
||||||
return _sexp_parse_infix (notmuch, sx->list->next, output);
|
return _sexp_parse_infix (notmuch, sx->list->next, output);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,21 +24,27 @@
|
||||||
#include "parse-time-vrp.h"
|
#include "parse-time-vrp.h"
|
||||||
#include "parse-time-string.h"
|
#include "parse-time-string.h"
|
||||||
|
|
||||||
Xapian::Query
|
notmuch_status_t
|
||||||
ParseTimeRangeProcessor::operator() (const std::string &begin, const std::string &end)
|
_notmuch_date_strings_to_query (Xapian::valueno slot,
|
||||||
|
const std::string &begin, const std::string &end,
|
||||||
|
Xapian::Query &output, std::string &msg)
|
||||||
{
|
{
|
||||||
double from = DBL_MIN, to = DBL_MAX;
|
double from = DBL_MIN, to = DBL_MAX;
|
||||||
time_t parsed_time, now;
|
time_t parsed_time, now;
|
||||||
std::string str;
|
std::string str;
|
||||||
|
|
||||||
/* Use the same 'now' for begin and end. */
|
/* Use the same 'now' for begin and end. */
|
||||||
if (time (&now) == (time_t) -1)
|
if (time (&now) == (time_t) -1) {
|
||||||
throw Xapian::QueryParserError ("unable to get current time");
|
msg = "unable to get current time";
|
||||||
|
return NOTMUCH_STATUS_ILLEGAL_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
if (! begin.empty ()) {
|
if (! begin.empty ()) {
|
||||||
if (parse_time_string (begin.c_str (), &parsed_time, &now, PARSE_TIME_ROUND_DOWN))
|
if (parse_time_string (begin.c_str (), &parsed_time, &now, PARSE_TIME_ROUND_DOWN)) {
|
||||||
throw Xapian::QueryParserError ("Didn't understand date specification '" + begin + "'");
|
msg = "Didn't understand date specification '" + begin + "'";
|
||||||
else
|
return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
from = (double) parsed_time;
|
from = (double) parsed_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,15 +54,30 @@ ParseTimeRangeProcessor::operator() (const std::string &begin, const std::string
|
||||||
else
|
else
|
||||||
str = end;
|
str = end;
|
||||||
|
|
||||||
if (parse_time_string (str.c_str (), &parsed_time, &now, PARSE_TIME_ROUND_UP_INCLUSIVE))
|
if (parse_time_string (str.c_str (), &parsed_time, &now, PARSE_TIME_ROUND_UP_INCLUSIVE)) {
|
||||||
throw Xapian::QueryParserError ("Didn't understand date specification '" + str + "'");
|
msg = "Didn't understand date specification '" + str + "'";
|
||||||
else
|
return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
|
||||||
|
}
|
||||||
to = (double) parsed_time;
|
to = (double) parsed_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Xapian::Query (Xapian::Query::OP_VALUE_RANGE, slot,
|
output = Xapian::Query (Xapian::Query::OP_VALUE_RANGE, slot,
|
||||||
Xapian::sortable_serialise (from),
|
Xapian::sortable_serialise (from),
|
||||||
Xapian::sortable_serialise (to));
|
Xapian::sortable_serialise (to));
|
||||||
|
return NOTMUCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
Xapian::Query
|
||||||
|
ParseTimeRangeProcessor::operator() (const std::string &begin, const std::string &end)
|
||||||
|
{
|
||||||
|
|
||||||
|
Xapian::Query output;
|
||||||
|
std::string msg;
|
||||||
|
|
||||||
|
if (_notmuch_date_strings_to_query (slot, begin, end, output, msg))
|
||||||
|
throw Xapian::QueryParserError (msg);
|
||||||
|
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX TODO: is throwing an exception the right thing to do here? */
|
/* XXX TODO: is throwing an exception the right thing to do here? */
|
||||||
|
|
|
@ -46,7 +46,7 @@ prefix_t prefix_table[] = {
|
||||||
{ "mid", "Q", NOTMUCH_FIELD_EXTERNAL |
|
{ "mid", "Q", NOTMUCH_FIELD_EXTERNAL |
|
||||||
NOTMUCH_FIELD_PROCESSOR },
|
NOTMUCH_FIELD_PROCESSOR },
|
||||||
{ "path", "P", NOTMUCH_FIELD_EXTERNAL |
|
{ "path", "P", NOTMUCH_FIELD_EXTERNAL |
|
||||||
NOTMUCH_FIELD_PROCESSOR },
|
NOTMUCH_FIELD_PROCESSOR | NOTMUCH_FIELD_STRIP_TRAILING_SLASH },
|
||||||
{ "property", "XPROPERTY", NOTMUCH_FIELD_EXTERNAL },
|
{ "property", "XPROPERTY", NOTMUCH_FIELD_EXTERNAL },
|
||||||
/*
|
/*
|
||||||
* Unconditionally add ':' to reduce potential ambiguity with
|
* Unconditionally add ':' to reduce potential ambiguity with
|
||||||
|
@ -55,7 +55,7 @@ prefix_t prefix_table[] = {
|
||||||
* discussion.
|
* discussion.
|
||||||
*/
|
*/
|
||||||
{ "folder", "XFOLDER:", NOTMUCH_FIELD_EXTERNAL |
|
{ "folder", "XFOLDER:", NOTMUCH_FIELD_EXTERNAL |
|
||||||
NOTMUCH_FIELD_PROCESSOR },
|
NOTMUCH_FIELD_PROCESSOR | NOTMUCH_FIELD_STRIP_TRAILING_SLASH },
|
||||||
{ "date", NULL, NOTMUCH_FIELD_EXTERNAL |
|
{ "date", NULL, NOTMUCH_FIELD_EXTERNAL |
|
||||||
NOTMUCH_FIELD_PROCESSOR },
|
NOTMUCH_FIELD_PROCESSOR },
|
||||||
{ "query", NULL, NOTMUCH_FIELD_EXTERNAL |
|
{ "query", NULL, NOTMUCH_FIELD_EXTERNAL |
|
||||||
|
|
|
@ -235,7 +235,15 @@ RegexpFieldProcessor::operator() (const std::string & str)
|
||||||
return parser.parse_query (query_str, NOTMUCH_QUERY_PARSER_FLAGS, term_prefix);
|
return parser.parse_query (query_str, NOTMUCH_QUERY_PARSER_FLAGS, term_prefix);
|
||||||
} else {
|
} else {
|
||||||
/* Boolean prefix */
|
/* Boolean prefix */
|
||||||
std::string term = term_prefix + str;
|
std::string query_str;
|
||||||
|
std::string term;
|
||||||
|
|
||||||
|
if (str.length () > 1 && str.at (str.size () - 1) == '/')
|
||||||
|
query_str = str.substr (0, str.size () - 1);
|
||||||
|
else
|
||||||
|
query_str = str;
|
||||||
|
|
||||||
|
term = term_prefix + query_str;
|
||||||
return Xapian::Query (term);
|
return Xapian::Query (term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ struct sprinter;
|
||||||
struct notmuch_show_params;
|
struct notmuch_show_params;
|
||||||
|
|
||||||
typedef struct notmuch_show_format {
|
typedef struct notmuch_show_format {
|
||||||
struct sprinter *(*new_sprinter)(const void *ctx, FILE *stream);
|
struct sprinter *(*new_sprinter)(notmuch_database_t * db, FILE *stream);
|
||||||
notmuch_status_t (*part)(const void *ctx, struct sprinter *sprinter,
|
notmuch_status_t (*part)(const void *ctx, struct sprinter *sprinter,
|
||||||
struct mime_node *node, int indent,
|
struct mime_node *node, int indent,
|
||||||
const struct notmuch_show_params *params);
|
const struct notmuch_show_params *params);
|
||||||
|
@ -426,13 +426,13 @@ mime_node_seek_dfs (mime_node_t *node, int n);
|
||||||
const _notmuch_message_crypto_t *
|
const _notmuch_message_crypto_t *
|
||||||
mime_node_get_message_crypto_status (mime_node_t *node);
|
mime_node_get_message_crypto_status (mime_node_t *node);
|
||||||
|
|
||||||
typedef enum dump_formats {
|
typedef enum {
|
||||||
DUMP_FORMAT_AUTO,
|
DUMP_FORMAT_AUTO,
|
||||||
DUMP_FORMAT_BATCH_TAG,
|
DUMP_FORMAT_BATCH_TAG,
|
||||||
DUMP_FORMAT_SUP
|
DUMP_FORMAT_SUP
|
||||||
} dump_format_t;
|
} dump_format_t;
|
||||||
|
|
||||||
typedef enum dump_includes {
|
typedef enum {
|
||||||
DUMP_INCLUDE_TAGS = 1,
|
DUMP_INCLUDE_TAGS = 1,
|
||||||
DUMP_INCLUDE_CONFIG = 2,
|
DUMP_INCLUDE_CONFIG = 2,
|
||||||
DUMP_INCLUDE_PROPERTIES = 4
|
DUMP_INCLUDE_PROPERTIES = 4
|
||||||
|
@ -499,11 +499,10 @@ int notmuch_minimal_options (const char *subcommand_name,
|
||||||
struct _notmuch_client_indexing_cli_choices {
|
struct _notmuch_client_indexing_cli_choices {
|
||||||
int decrypt_policy;
|
int decrypt_policy;
|
||||||
bool decrypt_policy_set;
|
bool decrypt_policy_set;
|
||||||
notmuch_indexopts_t *opts;
|
|
||||||
};
|
};
|
||||||
extern struct _notmuch_client_indexing_cli_choices indexing_cli_choices;
|
extern struct _notmuch_client_indexing_cli_choices indexing_cli_choices;
|
||||||
extern const notmuch_opt_desc_t notmuch_shared_indexing_options [];
|
extern const notmuch_opt_desc_t notmuch_shared_indexing_options [];
|
||||||
notmuch_status_t
|
notmuch_status_t
|
||||||
notmuch_process_shared_indexing_options (notmuch_database_t *notmuch);
|
notmuch_process_shared_indexing_options (notmuch_indexopts_t *opts);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -383,7 +383,10 @@ _config_set_list (notmuch_conffile_t *config,
|
||||||
const char *list[],
|
const char *list[],
|
||||||
size_t length)
|
size_t length)
|
||||||
{
|
{
|
||||||
|
if (length > 1)
|
||||||
g_key_file_set_string_list (config->key_file, group, key, list, length);
|
g_key_file_set_string_list (config->key_file, group, key, list, length);
|
||||||
|
else
|
||||||
|
g_key_file_set_string (config->key_file, group, key, list[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -680,9 +683,9 @@ _notmuch_config_list_built_with ()
|
||||||
printf ("%sretry_lock=%s\n",
|
printf ("%sretry_lock=%s\n",
|
||||||
BUILT_WITH_PREFIX,
|
BUILT_WITH_PREFIX,
|
||||||
notmuch_built_with ("retry_lock") ? "true" : "false");
|
notmuch_built_with ("retry_lock") ? "true" : "false");
|
||||||
printf ("%ssexpr_query=%s\n",
|
printf ("%ssexp_queries=%s\n",
|
||||||
BUILT_WITH_PREFIX,
|
BUILT_WITH_PREFIX,
|
||||||
notmuch_built_with ("sexpr_query") ? "true" : "false");
|
notmuch_built_with ("sexp_queries") ? "true" : "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -461,6 +461,8 @@ notmuch_insert_command (notmuch_database_t *notmuch, int argc, char *argv[])
|
||||||
char *maildir;
|
char *maildir;
|
||||||
char *newpath;
|
char *newpath;
|
||||||
int opt_index;
|
int opt_index;
|
||||||
|
notmuch_indexopts_t *indexopts = notmuch_database_get_default_indexopts (notmuch);
|
||||||
|
|
||||||
void *local = talloc_new (NULL);
|
void *local = talloc_new (NULL);
|
||||||
|
|
||||||
notmuch_opt_desc_t options[] = {
|
notmuch_opt_desc_t options[] = {
|
||||||
|
@ -550,7 +552,7 @@ notmuch_insert_command (notmuch_database_t *notmuch, int argc, char *argv[])
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = notmuch_process_shared_indexing_options (notmuch);
|
status = notmuch_process_shared_indexing_options (indexopts);
|
||||||
if (status != NOTMUCH_STATUS_SUCCESS) {
|
if (status != NOTMUCH_STATUS_SUCCESS) {
|
||||||
fprintf (stderr, "Error: Failed to process index options. (%s)\n",
|
fprintf (stderr, "Error: Failed to process index options. (%s)\n",
|
||||||
notmuch_status_to_string (status));
|
notmuch_status_to_string (status));
|
||||||
|
@ -558,7 +560,7 @@ notmuch_insert_command (notmuch_database_t *notmuch, int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Index the message. */
|
/* 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. */
|
/* Commit changes. */
|
||||||
close_status = notmuch_database_close (notmuch);
|
close_status = notmuch_database_close (notmuch);
|
||||||
|
|
|
@ -45,6 +45,7 @@ typedef struct {
|
||||||
const char *db_path;
|
const char *db_path;
|
||||||
const char *mail_root;
|
const char *mail_root;
|
||||||
|
|
||||||
|
notmuch_indexopts_t *indexopts;
|
||||||
int output_is_a_tty;
|
int output_is_a_tty;
|
||||||
enum verbosity verbosity;
|
enum verbosity verbosity;
|
||||||
bool debug;
|
bool debug;
|
||||||
|
@ -376,7 +377,7 @@ add_file (notmuch_database_t *notmuch, const char *filename,
|
||||||
if (status)
|
if (status)
|
||||||
goto DONE;
|
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) {
|
switch (status) {
|
||||||
/* Success. */
|
/* Success. */
|
||||||
case NOTMUCH_STATUS_SUCCESS:
|
case NOTMUCH_STATUS_SUCCESS:
|
||||||
|
@ -600,11 +601,12 @@ add_files (notmuch_database_t *notmuch,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ignore the .notmuch directory and any "tmp" directory
|
/* Ignore any top level .notmuch directory and any "tmp" directory
|
||||||
* that appears within a maildir.
|
* that appears within a maildir.
|
||||||
*/
|
*/
|
||||||
if ((is_maildir && strcmp (entry->d_name, "tmp") == 0) ||
|
if ((is_maildir && strcmp (entry->d_name, "tmp") == 0) ||
|
||||||
strcmp (entry->d_name, ".notmuch") == 0)
|
(strcmp (entry->d_name, ".notmuch") == 0
|
||||||
|
&& (strcmp (path, state->mail_root)) == 0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name);
|
next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name);
|
||||||
|
@ -1150,6 +1152,8 @@ notmuch_new_command (notmuch_database_t *notmuch, int argc, char *argv[])
|
||||||
else if (verbose)
|
else if (verbose)
|
||||||
add_files_state.verbosity = VERBOSITY_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);
|
add_files_state.new_tags = notmuch_config_get_values (notmuch, NOTMUCH_CONFIG_NEW_TAGS);
|
||||||
|
|
||||||
if (print_status_database (
|
if (print_status_database (
|
||||||
|
@ -1217,7 +1221,7 @@ notmuch_new_command (notmuch_database_t *notmuch, int argc, char *argv[])
|
||||||
if (notmuch == NULL)
|
if (notmuch == NULL)
|
||||||
return EXIT_FAILURE;
|
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) {
|
if (status != NOTMUCH_STATUS_SUCCESS) {
|
||||||
fprintf (stderr, "Error: Failed to process index options. (%s)\n",
|
fprintf (stderr, "Error: Failed to process index options. (%s)\n",
|
||||||
notmuch_status_to_string (status));
|
notmuch_status_to_string (status));
|
||||||
|
|
|
@ -90,6 +90,7 @@ notmuch_reindex_command (notmuch_database_t *notmuch, int argc, char *argv[])
|
||||||
int opt_index;
|
int opt_index;
|
||||||
int ret;
|
int ret;
|
||||||
notmuch_status_t status;
|
notmuch_status_t status;
|
||||||
|
notmuch_indexopts_t *indexopts = notmuch_database_get_default_indexopts (notmuch);
|
||||||
|
|
||||||
/* Set up our handler for SIGINT */
|
/* Set up our handler for SIGINT */
|
||||||
memset (&action, 0, sizeof (struct sigaction));
|
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]);
|
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) {
|
if (status != NOTMUCH_STATUS_SUCCESS) {
|
||||||
fprintf (stderr, "Error: Failed to process index options. (%s)\n",
|
fprintf (stderr, "Error: Failed to process index options. (%s)\n",
|
||||||
notmuch_status_to_string (status));
|
notmuch_status_to_string (status));
|
||||||
|
@ -128,7 +129,7 @@ notmuch_reindex_command (notmuch_database_t *notmuch, int argc, char *argv[])
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = reindex_query (notmuch, query_string, indexing_cli_choices.opts);
|
ret = reindex_query (notmuch, query_string, indexopts);
|
||||||
|
|
||||||
notmuch_database_destroy (notmuch);
|
notmuch_database_destroy (notmuch);
|
||||||
|
|
||||||
|
|
|
@ -209,6 +209,30 @@ _is_from_line (const char *line)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Output extra headers if configured with the `show.extra_headers'
|
||||||
|
* configuration option
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
format_extra_headers_sprinter (sprinter_t *sp, GMimeMessage *message)
|
||||||
|
{
|
||||||
|
GMimeHeaderList *header_list = g_mime_object_get_header_list (GMIME_OBJECT (message));
|
||||||
|
|
||||||
|
for (notmuch_config_values_t *extra_headers = notmuch_config_get_values (
|
||||||
|
sp->notmuch, NOTMUCH_CONFIG_EXTRA_HEADERS);
|
||||||
|
notmuch_config_values_valid (extra_headers);
|
||||||
|
notmuch_config_values_move_to_next (extra_headers)) {
|
||||||
|
GMimeHeader *header;
|
||||||
|
const char *header_name = notmuch_config_values_get (extra_headers);
|
||||||
|
|
||||||
|
header = g_mime_header_list_get_header (header_list, header_name);
|
||||||
|
if (header == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sp->map_key (sp, g_mime_header_get_name (header));
|
||||||
|
sp->string (sp, g_mime_header_get_value (header));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
format_headers_sprinter (sprinter_t *sp, GMimeMessage *message,
|
format_headers_sprinter (sprinter_t *sp, GMimeMessage *message,
|
||||||
bool reply, const _notmuch_message_crypto_t *msg_crypto)
|
bool reply, const _notmuch_message_crypto_t *msg_crypto)
|
||||||
|
@ -269,6 +293,9 @@ format_headers_sprinter (sprinter_t *sp, GMimeMessage *message,
|
||||||
sp->string (sp, g_mime_message_get_date_string (sp, message));
|
sp->string (sp, g_mime_message_get_date_string (sp, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Output extra headers the user has configured, if any */
|
||||||
|
if (! reply)
|
||||||
|
format_extra_headers_sprinter (sp, message);
|
||||||
sp->end (sp);
|
sp->end (sp);
|
||||||
talloc_free (local);
|
talloc_free (local);
|
||||||
}
|
}
|
||||||
|
|
13
notmuch.c
13
notmuch.c
|
@ -141,21 +141,18 @@ const notmuch_opt_desc_t notmuch_shared_indexing_options [] = {
|
||||||
|
|
||||||
|
|
||||||
notmuch_status_t
|
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)
|
if (opts == NULL)
|
||||||
indexing_cli_choices.opts = notmuch_database_get_default_indexopts (notmuch);
|
return NOTMUCH_STATUS_NULL_POINTER;
|
||||||
|
|
||||||
if (indexing_cli_choices.decrypt_policy_set) {
|
if (indexing_cli_choices.decrypt_policy_set) {
|
||||||
notmuch_status_t status;
|
notmuch_status_t status;
|
||||||
if (indexing_cli_choices.opts == NULL)
|
status = notmuch_indexopts_set_decrypt_policy (opts,
|
||||||
return NOTMUCH_STATUS_OUT_OF_MEMORY;
|
|
||||||
status = notmuch_indexopts_set_decrypt_policy (indexing_cli_choices.opts,
|
|
||||||
indexing_cli_choices.decrypt_policy);
|
indexing_cli_choices.decrypt_policy);
|
||||||
if (status != NOTMUCH_STATUS_SUCCESS) {
|
if (status != NOTMUCH_STATUS_SUCCESS) {
|
||||||
fprintf (stderr, "Error: Failed to set index decryption policy to %d. (%s)\n",
|
fprintf (stderr, "Error: Failed to set index decryption policy to %d. (%s)\n",
|
||||||
indexing_cli_choices.decrypt_policy, notmuch_status_to_string (status));
|
indexing_cli_choices.decrypt_policy, notmuch_status_to_string (status));
|
||||||
notmuch_indexopts_destroy (indexing_cli_choices.opts);
|
|
||||||
indexing_cli_choices.opts = NULL;
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,7 +172,7 @@ json_separator (struct sprinter *sp)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sprinter *
|
struct sprinter *
|
||||||
sprinter_json_create (const void *ctx, FILE *stream)
|
sprinter_json_create (notmuch_database_t *db, FILE *stream)
|
||||||
{
|
{
|
||||||
static const struct sprinter_json template = {
|
static const struct sprinter_json template = {
|
||||||
.vtable = {
|
.vtable = {
|
||||||
|
@ -192,11 +192,12 @@ sprinter_json_create (const void *ctx, FILE *stream)
|
||||||
};
|
};
|
||||||
struct sprinter_json *res;
|
struct sprinter_json *res;
|
||||||
|
|
||||||
res = talloc (ctx, struct sprinter_json);
|
res = talloc (db, struct sprinter_json);
|
||||||
if (! res)
|
if (! res)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
*res = template;
|
*res = template;
|
||||||
|
res->vtable.notmuch = db;
|
||||||
res->stream = stream;
|
res->stream = stream;
|
||||||
return &res->vtable;
|
return &res->vtable;
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,7 +207,7 @@ sexp_separator (struct sprinter *sp)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sprinter *
|
struct sprinter *
|
||||||
sprinter_sexp_create (const void *ctx, FILE *stream)
|
sprinter_sexp_create (notmuch_database_t *db, FILE *stream)
|
||||||
{
|
{
|
||||||
static const struct sprinter_sexp template = {
|
static const struct sprinter_sexp template = {
|
||||||
.vtable = {
|
.vtable = {
|
||||||
|
@ -227,11 +227,12 @@ sprinter_sexp_create (const void *ctx, FILE *stream)
|
||||||
};
|
};
|
||||||
struct sprinter_sexp *res;
|
struct sprinter_sexp *res;
|
||||||
|
|
||||||
res = talloc (ctx, struct sprinter_sexp);
|
res = talloc (db, struct sprinter_sexp);
|
||||||
if (! res)
|
if (! res)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
*res = template;
|
*res = template;
|
||||||
|
res->vtable.notmuch = db;
|
||||||
res->stream = stream;
|
res->stream = stream;
|
||||||
return &res->vtable;
|
return &res->vtable;
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ text_map_key (unused (struct sprinter *sp), unused (const char *key))
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sprinter *
|
struct sprinter *
|
||||||
sprinter_text_create (const void *ctx, FILE *stream)
|
sprinter_text_create (notmuch_database_t *db, FILE *stream)
|
||||||
{
|
{
|
||||||
static const struct sprinter_text template = {
|
static const struct sprinter_text template = {
|
||||||
.vtable = {
|
.vtable = {
|
||||||
|
@ -134,21 +134,22 @@ sprinter_text_create (const void *ctx, FILE *stream)
|
||||||
};
|
};
|
||||||
struct sprinter_text *res;
|
struct sprinter_text *res;
|
||||||
|
|
||||||
res = talloc (ctx, struct sprinter_text);
|
res = talloc (db, struct sprinter_text);
|
||||||
if (! res)
|
if (! res)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
*res = template;
|
*res = template;
|
||||||
|
res->vtable.notmuch = db;
|
||||||
res->stream = stream;
|
res->stream = stream;
|
||||||
return &res->vtable;
|
return &res->vtable;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sprinter *
|
struct sprinter *
|
||||||
sprinter_text0_create (const void *ctx, FILE *stream)
|
sprinter_text0_create (notmuch_database_t *db, FILE *stream)
|
||||||
{
|
{
|
||||||
struct sprinter *sp;
|
struct sprinter *sp;
|
||||||
|
|
||||||
sp = sprinter_text_create (ctx, stream);
|
sp = sprinter_text_create (db, stream);
|
||||||
if (! sp)
|
if (! sp)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
13
sprinter.h
13
sprinter.h
|
@ -9,6 +9,11 @@
|
||||||
* (strings, integers and booleans).
|
* (strings, integers and booleans).
|
||||||
*/
|
*/
|
||||||
typedef struct sprinter {
|
typedef struct sprinter {
|
||||||
|
/*
|
||||||
|
* Open notmuch database
|
||||||
|
*/
|
||||||
|
notmuch_database_t *notmuch;
|
||||||
|
|
||||||
/* Start a new map/dictionary structure. This should be followed by
|
/* Start a new map/dictionary structure. This should be followed by
|
||||||
* a sequence of alternating calls to map_key and one of the
|
* a sequence of alternating calls to map_key and one of the
|
||||||
* value-printing functions until the map is ended by end.
|
* value-printing functions until the map is ended by end.
|
||||||
|
@ -65,20 +70,20 @@ typedef struct sprinter {
|
||||||
/* Create a new unstructured printer that emits the default text format
|
/* Create a new unstructured printer that emits the default text format
|
||||||
* for "notmuch search". */
|
* for "notmuch search". */
|
||||||
struct sprinter *
|
struct sprinter *
|
||||||
sprinter_text_create (const void *ctx, FILE *stream);
|
sprinter_text_create (notmuch_database_t *db, FILE *stream);
|
||||||
|
|
||||||
/* Create a new unstructured printer that emits the text format for
|
/* Create a new unstructured printer that emits the text format for
|
||||||
* "notmuch search", with each field separated by a null character
|
* "notmuch search", with each field separated by a null character
|
||||||
* instead of the newline character. */
|
* instead of the newline character. */
|
||||||
struct sprinter *
|
struct sprinter *
|
||||||
sprinter_text0_create (const void *ctx, FILE *stream);
|
sprinter_text0_create (notmuch_database_t *db, FILE *stream);
|
||||||
|
|
||||||
/* Create a new structure printer that emits JSON. */
|
/* Create a new structure printer that emits JSON. */
|
||||||
struct sprinter *
|
struct sprinter *
|
||||||
sprinter_json_create (const void *ctx, FILE *stream);
|
sprinter_json_create (notmuch_database_t *db, FILE *stream);
|
||||||
|
|
||||||
/* Create a new structure printer that emits S-Expressions. */
|
/* Create a new structure printer that emits S-Expressions. */
|
||||||
struct sprinter *
|
struct sprinter *
|
||||||
sprinter_sexp_create (const void *ctx, FILE *stream);
|
sprinter_sexp_create (notmuch_database_t *db, FILE *stream);
|
||||||
|
|
||||||
#endif // NOTMUCH_SPRINTER_H
|
#endif // NOTMUCH_SPRINTER_H
|
||||||
|
|
|
@ -51,7 +51,7 @@ cat <<EOF > EXPECTED
|
||||||
built_with.compact=something
|
built_with.compact=something
|
||||||
built_with.field_processor=something
|
built_with.field_processor=something
|
||||||
built_with.retry_lock=something
|
built_with.retry_lock=something
|
||||||
built_with.sexpr_query=something
|
built_with.sexp_queries=something
|
||||||
database.autocommit=8000
|
database.autocommit=8000
|
||||||
database.mail_root=MAIL_DIR
|
database.mail_root=MAIL_DIR
|
||||||
database.path=MAIL_DIR
|
database.path=MAIL_DIR
|
||||||
|
@ -67,6 +67,35 @@ user.primary_email=test_suite@notmuchmail.org
|
||||||
EOF
|
EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
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"
|
test_begin_subtest "Top level --config=FILE option"
|
||||||
cp "${NOTMUCH_CONFIG}" alt-config
|
cp "${NOTMUCH_CONFIG}" alt-config
|
||||||
notmuch --config=alt-config config set user.name "Another Name"
|
notmuch --config=alt-config config set user.name "Another Name"
|
||||||
|
|
|
@ -23,6 +23,13 @@ EOF
|
||||||
expected_dir=$NOTMUCH_SRCDIR/test/setup.expected-output
|
expected_dir=$NOTMUCH_SRCDIR/test/setup.expected-output
|
||||||
test_expect_equal_file ${expected_dir}/config-with-comments new-notmuch-config
|
test_expect_equal_file ${expected_dir}/config-with-comments new-notmuch-config
|
||||||
|
|
||||||
|
test_begin_subtest "setup consistent with config-set for single items"
|
||||||
|
# note this relies on the config state from the previous test.
|
||||||
|
notmuch --config=new-notmuch-config config list > list.setup
|
||||||
|
notmuch --config=new-notmuch-config config set search.exclude_tags baz
|
||||||
|
notmuch --config=new-notmuch-config config list > list.config
|
||||||
|
test_expect_equal_file list.setup list.config
|
||||||
|
|
||||||
test_begin_subtest "notmuch with a config but without a database suggests notmuch new"
|
test_begin_subtest "notmuch with a config but without a database suggests notmuch new"
|
||||||
notmuch 2>&1 | notmuch_dir_sanitize > OUTPUT
|
notmuch 2>&1 | notmuch_dir_sanitize > OUTPUT
|
||||||
cat <<EOF > EXPECTED
|
cat <<EOF > EXPECTED
|
||||||
|
|
|
@ -329,6 +329,18 @@ notmuch config set new.tags "foo;;bar"
|
||||||
output=$(NOTMUCH_NEW --quiet 2>&1)
|
output=$(NOTMUCH_NEW --quiet 2>&1)
|
||||||
test_expect_equal "$output" ""
|
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 <<EOF >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"
|
test_begin_subtest "Tags starting with '-' in new.tags are forbidden"
|
||||||
notmuch config set new.tags "-foo;bar"
|
notmuch config set new.tags "-foo;bar"
|
||||||
output=$(NOTMUCH_NEW --debug 2>&1)
|
output=$(NOTMUCH_NEW --debug 2>&1)
|
||||||
|
@ -339,6 +351,16 @@ test_expect_code 1 "NOTMUCH_NEW --debug 2>&1"
|
||||||
|
|
||||||
notmuch config set new.tags $OLDCONFIG
|
notmuch config set new.tags $OLDCONFIG
|
||||||
|
|
||||||
|
test_begin_subtest ".notmuch only ignored at top level"
|
||||||
|
generate_message '[dir]=foo/bar/.notmuch/cur' '[subject]="Do not ignore, very important"'
|
||||||
|
NOTMUCH_NEW > OUTPUT
|
||||||
|
notmuch search subject:Do-not-ignore | notmuch_search_sanitize >> OUTPUT
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
Added 1 new message to the database.
|
||||||
|
thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Do not ignore, very important (inbox unread)
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
test_begin_subtest "RFC822 group names are indexed"
|
test_begin_subtest "RFC822 group names are indexed"
|
||||||
test_subtest_known_broken
|
test_subtest_known_broken
|
||||||
generate_message [to]="undisclosed-recipients:"
|
generate_message [to]="undisclosed-recipients:"
|
||||||
|
@ -368,31 +390,26 @@ chmod u+w ${MAIL_DIR}/.notmuch/xapian/*.*
|
||||||
test_expect_equal "$output" "A Xapian exception occurred opening database"
|
test_expect_equal "$output" "A Xapian exception occurred opening database"
|
||||||
|
|
||||||
|
|
||||||
|
make_shim dif-shim<<EOF
|
||||||
|
#include <notmuch-test.h>
|
||||||
|
|
||||||
|
WRAP_DLFUNC(notmuch_status_t, notmuch_database_index_file, \
|
||||||
|
(notmuch_database_t *database, const char *filename, notmuch_indexopts_t *indexopts, notmuch_message_t **message))
|
||||||
|
|
||||||
|
if (unlink ("${MAIL_DIR}/vanish")) {
|
||||||
|
fprintf (stderr, "unlink failed\n");
|
||||||
|
exit (42);
|
||||||
|
}
|
||||||
|
return notmuch_database_index_file_orig (database, filename, indexopts, message);
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
test_begin_subtest "Handle files vanishing between scandir and add_file"
|
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.
|
# A file for scandir to find. It won't get indexed, so can be empty.
|
||||||
touch ${MAIL_DIR}/vanish
|
touch ${MAIL_DIR}/vanish
|
||||||
|
notmuch_with_shim dif-shim new 2>OUTPUT 1>/dev/null
|
||||||
# Breakpoint to remove the file before indexing
|
|
||||||
cat <<EOF > 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
|
|
||||||
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
|
echo "exit status: $?" >> OUTPUT
|
||||||
|
|
||||||
# Clean up the file in case gdb isn't available.
|
|
||||||
rm -f ${MAIL_DIR}/vanish
|
|
||||||
|
|
||||||
cat <<EOF > EXPECTED
|
cat <<EOF > EXPECTED
|
||||||
Unexpected error with file ${MAIL_DIR}/vanish
|
Unexpected error with file ${MAIL_DIR}/vanish
|
||||||
add_file: Something went wrong trying to read or write a file
|
add_file: Something went wrong trying to read or write a file
|
||||||
|
|
40
test/T051-new-renames.sh
Executable file
40
test/T051-new-renames.sh
Executable file
|
@ -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
|
|
@ -277,7 +277,7 @@ EOF
|
||||||
built_with.compact=something
|
built_with.compact=something
|
||||||
built_with.field_processor=something
|
built_with.field_processor=something
|
||||||
built_with.retry_lock=something
|
built_with.retry_lock=something
|
||||||
built_with.sexpr_query=something
|
built_with.sexp_queries=something
|
||||||
database.autocommit=8000
|
database.autocommit=8000
|
||||||
database.backup_dir
|
database.backup_dir
|
||||||
database.hook_dir
|
database.hook_dir
|
||||||
|
@ -318,7 +318,14 @@ to=m.header('To')
|
||||||
print(to)
|
print(to)
|
||||||
EOF
|
EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
;& # fall through
|
;;
|
||||||
|
*)
|
||||||
|
backup_database
|
||||||
|
test_begin_subtest ".notmuch without xapian/ handled gracefully ($config)"
|
||||||
|
rm -r $XAPIAN_PATH
|
||||||
|
test_expect_success "notmuch new"
|
||||||
|
restore_database
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
case $config in
|
case $config in
|
||||||
|
|
|
@ -102,22 +102,25 @@ output=$(sed 's/^\(A Xapian exception [^:]*\):.*$/\1/' OUTPUT)
|
||||||
test_expect_equal "${output}" "A Xapian exception occurred opening database"
|
test_expect_equal "${output}" "A Xapian exception occurred opening database"
|
||||||
restore_database
|
restore_database
|
||||||
|
|
||||||
cat <<EOF > count-files.gdb
|
make_shim qsm-shim<<EOF
|
||||||
set breakpoint pending on
|
#include <notmuch-test.h>
|
||||||
set logging file count-files-gdb.log
|
|
||||||
set logging on
|
WRAP_DLFUNC (notmuch_status_t, notmuch_query_search_messages, (notmuch_query_t *query, notmuch_messages_t **messages))
|
||||||
break count_files
|
|
||||||
commands
|
/* XXX WARNING THIS CORRUPTS THE DATABASE */
|
||||||
shell cp /dev/null ${MAIL_DIR}/.notmuch/xapian/postlist.*
|
int fd = open ("target_postlist", O_WRONLY|O_TRUNC);
|
||||||
continue
|
if (fd < 0)
|
||||||
end
|
exit (8);
|
||||||
run
|
close (fd);
|
||||||
|
|
||||||
|
return notmuch_query_search_messages_orig(query, messages);
|
||||||
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
backup_database
|
backup_database
|
||||||
test_begin_subtest "error message from query_search_messages"
|
test_begin_subtest "error message from query_search_messages"
|
||||||
${TEST_GDB} --batch-silent --return-child-result -x count-files.gdb \
|
ln -s ${MAIL_DIR}/.notmuch/xapian/postlist.* target_postlist
|
||||||
--args notmuch count --output=files '*' 2>OUTPUT 1>/dev/null
|
notmuch_with_shim qsm-shim count --output=files '*' 2>OUTPUT 1>/dev/null
|
||||||
cat <<EOF > EXPECTED
|
cat <<EOF > EXPECTED
|
||||||
notmuch count: A Xapian exception occurred
|
notmuch count: A Xapian exception occurred
|
||||||
A Xapian exception occurred performing query
|
A Xapian exception occurred performing query
|
||||||
|
|
|
@ -234,6 +234,18 @@ output=$(notmuch show --format=json id:$gen_msg_id)
|
||||||
test_json_nodes <<<"$output" \
|
test_json_nodes <<<"$output" \
|
||||||
'new_tags:[0][0][0]["tags"] = ["bar", "foo"]'
|
'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 <<EOF >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"
|
test_begin_subtest "Tags starting with '-' in new.tags are forbidden"
|
||||||
notmuch config set new.tags "-foo;bar"
|
notmuch config set new.tags "-foo;bar"
|
||||||
gen_insert_msg
|
gen_insert_msg
|
||||||
|
|
|
@ -185,6 +185,50 @@ notmuch search folder:'""' > EXPECTED
|
||||||
notmuch search --query=sexp '(folder "")' > OUTPUT
|
notmuch search --query=sexp '(folder "")' > OUTPUT
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "Search by 'folder' with --output=files"
|
||||||
|
output=$(notmuch search --output=files --query=sexp '(folder bad/news)' | notmuch_search_files_sanitize)
|
||||||
|
test_expect_equal "$output" "MAIL_DIR/bad/news/msg-XXX
|
||||||
|
MAIL_DIR/duplicate/bad/news/msg-XXX"
|
||||||
|
|
||||||
|
test_begin_subtest "Search by 'folder' with --output=files (trailing /)"
|
||||||
|
output=$(notmuch search --output=files --query=sexp '(folder bad/news/)' | notmuch_search_files_sanitize)
|
||||||
|
test_expect_equal "$output" "MAIL_DIR/bad/news/msg-XXX
|
||||||
|
MAIL_DIR/duplicate/bad/news/msg-XXX"
|
||||||
|
|
||||||
|
test_begin_subtest "Search by 'folder' (multiple)"
|
||||||
|
output=$(notmuch search --query=sexp '(folder bad bad/news things/bad)' | notmuch_search_sanitize)
|
||||||
|
test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; To the bone (inbox unread)
|
||||||
|
thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread)
|
||||||
|
thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)"
|
||||||
|
|
||||||
|
test_begin_subtest "Search by 'folder' (multiple, trailing /)"
|
||||||
|
output=$(notmuch search --query=sexp '(folder bad bad/news/ things/bad)' | notmuch_search_sanitize)
|
||||||
|
test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; To the bone (inbox unread)
|
||||||
|
thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread)
|
||||||
|
thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)"
|
||||||
|
|
||||||
|
test_begin_subtest "Search by 'path' with --output=files"
|
||||||
|
output=$(notmuch search --output=files --query=sexp '(path bad/news)' | notmuch_search_files_sanitize)
|
||||||
|
test_expect_equal "$output" "MAIL_DIR/bad/news/msg-XXX
|
||||||
|
MAIL_DIR/duplicate/bad/news/msg-XXX"
|
||||||
|
|
||||||
|
test_begin_subtest "Search by 'path' with --output=files (trailing /)"
|
||||||
|
output=$(notmuch search --output=files --query=sexp '(path bad/news/)' | notmuch_search_files_sanitize)
|
||||||
|
test_expect_equal "$output" "MAIL_DIR/bad/news/msg-XXX
|
||||||
|
MAIL_DIR/duplicate/bad/news/msg-XXX"
|
||||||
|
|
||||||
|
test_begin_subtest "Search by 'path' specification (multiple)"
|
||||||
|
output=$(notmuch search --query=sexp '(path bad bad/news things/bad)' | notmuch_search_sanitize)
|
||||||
|
test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; To the bone (inbox unread)
|
||||||
|
thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread)
|
||||||
|
thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)"
|
||||||
|
|
||||||
|
test_begin_subtest "Search by 'path' specification (multiple, trailing /)"
|
||||||
|
output=$(notmuch search --query=sexp '(path bad bad/news/ things/bad)' | notmuch_search_sanitize)
|
||||||
|
test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; To the bone (inbox unread)
|
||||||
|
thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread)
|
||||||
|
thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)"
|
||||||
|
|
||||||
test_begin_subtest "Search by 'id'"
|
test_begin_subtest "Search by 'id'"
|
||||||
add_message '[subject]="search by id"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
|
add_message '[subject]="search by id"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
|
||||||
output=$(notmuch search --query=sexp "(id ${gen_msg_id})" | notmuch_search_sanitize)
|
output=$(notmuch search --query=sexp "(id ${gen_msg_id})" | notmuch_search_sanitize)
|
||||||
|
@ -346,7 +390,7 @@ output=$(notmuch search --query=sexp '(attachment (starts-with not))' | notmuch_
|
||||||
test_expect_equal "$output" 'thread:XXX 2009-11-18 [2/2] Lars Kellogg-Stedman; [notmuch] "notmuch help" outputs to stderr? (attachment inbox signed unread)'
|
test_expect_equal "$output" 'thread:XXX 2009-11-18 [2/2] Lars Kellogg-Stedman; [notmuch] "notmuch help" outputs to stderr? (attachment inbox signed unread)'
|
||||||
|
|
||||||
test_begin_subtest "starts-with, folder"
|
test_begin_subtest "starts-with, folder"
|
||||||
notmuch search --output=files --query=sexp '(folder (starts-with bad))' | notmuch_dir_sanitize | sed 's/[0-9]*$/XXX/' > OUTPUT
|
notmuch search --output=files --query=sexp '(folder (starts-with bad))' | notmuch_search_files_sanitize > OUTPUT
|
||||||
cat <<EOF > EXPECTED
|
cat <<EOF > EXPECTED
|
||||||
MAIL_DIR/bad/msg-XXX
|
MAIL_DIR/bad/msg-XXX
|
||||||
MAIL_DIR/bad/news/msg-XXX
|
MAIL_DIR/bad/news/msg-XXX
|
||||||
|
@ -768,6 +812,144 @@ notmuch search date:2009-11-18..2009-11-18 and tag:unread > EXPECTED
|
||||||
notmuch search --query=sexp '(and (infix "date:2009-11-18..2009-11-18") (infix "tag:unread"))' > OUTPUT
|
notmuch search --query=sexp '(and (infix "date:2009-11-18..2009-11-18") (infix "tag:unread"))' > OUTPUT
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "date query, empty"
|
||||||
|
notmuch search from:keithp | notmuch_search_sanitize > EXPECTED
|
||||||
|
notmuch search --query=sexp '(and (date) (from keithp))'| notmuch_search_sanitize > OUTPUT
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "date query, one argument"
|
||||||
|
notmuch search date:2009-11-18 and from:keithp | notmuch_search_sanitize > EXPECTED
|
||||||
|
notmuch search --query=sexp '(and (date 2009-11-18) (from keithp))' | notmuch_search_sanitize > OUTPUT
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "date query, two arguments"
|
||||||
|
notmuch search date:2009-11-17..2009-11-18 and from:keithp | notmuch_search_sanitize > EXPECTED
|
||||||
|
notmuch search --query=sexp '(and (date 2009-11-17 2009-11-18) (from keithp))' | notmuch_search_sanitize > OUTPUT
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "date query, illegal nesting 1"
|
||||||
|
notmuch search --query=sexp '(to (date))' > OUTPUT 2>&1
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
notmuch search: Syntax error in query
|
||||||
|
nested field: 'date' inside 'to'
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "date query, illegal nesting 2"
|
||||||
|
notmuch search --query=sexp '(to (date 2021-11-18))' > OUTPUT 2>&1
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
notmuch search: Syntax error in query
|
||||||
|
nested field: 'date' inside 'to'
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "date query, illegal nesting 3"
|
||||||
|
notmuch search --query=sexp '(date (to))' > OUTPUT 2>&1
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
notmuch search: Syntax error in query
|
||||||
|
expected atom as first argument of 'date'
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "date query, illegal nesting 4"
|
||||||
|
notmuch search --query=sexp '(date today (to))' > OUTPUT 2>&1
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
notmuch search: Syntax error in query
|
||||||
|
expected atom as second argument of 'date'
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "date query, too many arguments"
|
||||||
|
notmuch search --query=sexp '(date yesterday and tommorow)' > OUTPUT 2>&1
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
notmuch search: Syntax error in query
|
||||||
|
'date' expects maximum of two arguments
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "date query, bad date"
|
||||||
|
notmuch search --query=sexp '(date "hawaiian-pizza-day")' > OUTPUT 2>&1
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
notmuch search: Syntax error in query
|
||||||
|
Didn't understand date specification 'hawaiian-pizza-day'
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "lastmod query, empty"
|
||||||
|
notmuch search from:keithp | notmuch_search_sanitize > EXPECTED
|
||||||
|
notmuch search --query=sexp '(and (lastmod) (from keithp))'| notmuch_search_sanitize > OUTPUT
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "lastmod query, one argument"
|
||||||
|
notmuch tag +4EFC743A.3060609@april.org id:4EFC743A.3060609@april.org
|
||||||
|
revision=$(notmuch count --lastmod '*' | cut -f3)
|
||||||
|
notmuch search lastmod:$revision..$revision | notmuch_search_sanitize > EXPECTED
|
||||||
|
notmuch search --query=sexp "(and (lastmod $revision))" | notmuch_search_sanitize > OUTPUT
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "lastmod query, two arguments"
|
||||||
|
notmuch tag +keithp from:keithp
|
||||||
|
revision2=$(notmuch count --lastmod '*' | cut -f3)
|
||||||
|
notmuch search lastmod:$revision..$revision2 | notmuch_search_sanitize > EXPECTED
|
||||||
|
notmuch search --query=sexp "(and (lastmod $revision $revision2))" | notmuch_search_sanitize > OUTPUT
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "lastmod query, illegal nesting 1"
|
||||||
|
notmuch search --query=sexp '(to (lastmod))' > OUTPUT 2>&1
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
notmuch search: Syntax error in query
|
||||||
|
nested field: 'lastmod' inside 'to'
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "lastmod query, bad from revision"
|
||||||
|
notmuch search --query=sexp '(lastmod apples)' > OUTPUT 2>&1
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
notmuch search: Syntax error in query
|
||||||
|
bad 'from' revision: 'apples'
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "lastmod query, bad to revision"
|
||||||
|
notmuch search --query=sexp '(lastmod 0 apples)' > OUTPUT 2>&1
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
notmuch search: Syntax error in query
|
||||||
|
bad 'to' revision: 'apples'
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "lastmod query, illegal nesting 2"
|
||||||
|
notmuch search --query=sexp '(to (lastmod 2021-11-18))' > OUTPUT 2>&1
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
notmuch search: Syntax error in query
|
||||||
|
nested field: 'lastmod' inside 'to'
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "lastmod query, illegal nesting 3"
|
||||||
|
notmuch search --query=sexp '(lastmod (to))' > OUTPUT 2>&1
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
notmuch search: Syntax error in query
|
||||||
|
expected atom as first argument of 'lastmod'
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "lastmod query, illegal nesting 4"
|
||||||
|
notmuch search --query=sexp '(lastmod today (to))' > OUTPUT 2>&1
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
notmuch search: Syntax error in query
|
||||||
|
expected atom as second argument of 'lastmod'
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "lastmod query, too many arguments"
|
||||||
|
notmuch search --query=sexp '(lastmod yesterday and tommorow)' > OUTPUT 2>&1
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
notmuch search: Syntax error in query
|
||||||
|
'lastmod' expects maximum of two arguments
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
test_begin_subtest "user header (unknown header)"
|
test_begin_subtest "user header (unknown header)"
|
||||||
notmuch search --query=sexp '(FooBar)' >& OUTPUT
|
notmuch search --query=sexp '(FooBar)' >& OUTPUT
|
||||||
cat <<EOF > EXPECTED
|
cat <<EOF > EXPECTED
|
||||||
|
|
|
@ -18,6 +18,12 @@ test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; T
|
||||||
thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread)
|
thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread)
|
||||||
thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)"
|
thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)"
|
||||||
|
|
||||||
|
test_begin_subtest "search by path: specification (multiple)"
|
||||||
|
output=$(notmuch search path:bad path:bad/news path:things/bad | notmuch_search_sanitize)
|
||||||
|
test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; To the bone (inbox unread)
|
||||||
|
thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread)
|
||||||
|
thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)"
|
||||||
|
|
||||||
test_begin_subtest "Top level folder"
|
test_begin_subtest "Top level folder"
|
||||||
output=$(notmuch search folder:'""' | notmuch_search_sanitize)
|
output=$(notmuch search folder:'""' | notmuch_search_sanitize)
|
||||||
test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Top level (inbox unread)"
|
test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Top level (inbox unread)"
|
||||||
|
@ -28,8 +34,13 @@ test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite
|
||||||
|
|
||||||
test_begin_subtest "Folder search with --output=files"
|
test_begin_subtest "Folder search with --output=files"
|
||||||
output=$(notmuch search --output=files folder:bad/news | notmuch_search_files_sanitize)
|
output=$(notmuch search --output=files folder:bad/news | notmuch_search_files_sanitize)
|
||||||
test_expect_equal "$output" "MAIL_DIR/bad/news/msg-003
|
test_expect_equal "$output" "MAIL_DIR/bad/news/msg-XXX
|
||||||
MAIL_DIR/duplicate/bad/news/msg-003"
|
MAIL_DIR/duplicate/bad/news/msg-XXX"
|
||||||
|
|
||||||
|
test_begin_subtest "Folder search with --output=files (trailing /)"
|
||||||
|
output=$(notmuch search --output=files folder:bad/news/ | notmuch_search_files_sanitize)
|
||||||
|
test_expect_equal "$output" "MAIL_DIR/bad/news/msg-XXX
|
||||||
|
MAIL_DIR/duplicate/bad/news/msg-XXX"
|
||||||
|
|
||||||
test_begin_subtest "After removing duplicate instance of matching path"
|
test_begin_subtest "After removing duplicate instance of matching path"
|
||||||
rm -r "${MAIL_DIR}/bad/news"
|
rm -r "${MAIL_DIR}/bad/news"
|
||||||
|
@ -39,7 +50,7 @@ test_expect_equal "$output" ""
|
||||||
|
|
||||||
test_begin_subtest "Folder search with --output=files part #2"
|
test_begin_subtest "Folder search with --output=files part #2"
|
||||||
output=$(notmuch search --output=files folder:duplicate/bad/news | notmuch_search_files_sanitize)
|
output=$(notmuch search --output=files folder:duplicate/bad/news | notmuch_search_files_sanitize)
|
||||||
test_expect_equal "$output" "MAIL_DIR/duplicate/bad/news/msg-003"
|
test_expect_equal "$output" "MAIL_DIR/duplicate/bad/news/msg-XXX"
|
||||||
|
|
||||||
test_begin_subtest "After removing duplicate instance of matching path part #2"
|
test_begin_subtest "After removing duplicate instance of matching path part #2"
|
||||||
output=$(notmuch search folder:duplicate/bad/news | notmuch_search_sanitize)
|
output=$(notmuch search folder:duplicate/bad/news | notmuch_search_sanitize)
|
||||||
|
@ -120,6 +131,13 @@ test_expect_equal "$output" "MAIL_DIR/bar/17:2,
|
||||||
MAIL_DIR/bar/18:2,
|
MAIL_DIR/bar/18:2,
|
||||||
MAIL_DIR/cur/51:2,"
|
MAIL_DIR/cur/51:2,"
|
||||||
|
|
||||||
|
test_begin_subtest "path: search (trailing /)"
|
||||||
|
output=$(notmuch search --output=files path:"bar/" | notmuch_search_files_sanitize | sort)
|
||||||
|
# cur/51:2, is a duplicate of bar/18:2,
|
||||||
|
test_expect_equal "$output" "MAIL_DIR/bar/17:2,
|
||||||
|
MAIL_DIR/bar/18:2,
|
||||||
|
MAIL_DIR/cur/51:2,"
|
||||||
|
|
||||||
test_begin_subtest "top level path: search"
|
test_begin_subtest "top level path: search"
|
||||||
output=$(notmuch search --output=files path:'""' | notmuch_search_files_sanitize | sort)
|
output=$(notmuch search --output=files path:'""' | notmuch_search_files_sanitize | sort)
|
||||||
test_expect_equal "$output" "MAIL_DIR/01:2,
|
test_expect_equal "$output" "MAIL_DIR/01:2,
|
||||||
|
|
|
@ -156,4 +156,46 @@ EOF
|
||||||
output=$(notmuch show --format=json --body=false --format-version=2 id:message-id@example.com)
|
output=$(notmuch show --format=json --body=false --format-version=2 id:message-id@example.com)
|
||||||
test_expect_equal_json "$output" "$(cat EXPECTED)"
|
test_expect_equal_json "$output" "$(cat EXPECTED)"
|
||||||
|
|
||||||
|
test_begin_subtest "show extra headers"
|
||||||
|
add_message "[subject]=\"extra-headers\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[in-reply-to]=\"<parent@notmuch-test-suite>\"" "[body]=\"extra-headers test\""\
|
||||||
|
"[header]=\"Received: from mail.example.com (mail.example.com [1.1.1.1])
|
||||||
|
by mail.notmuchmail.org (some MTA) with ESMTP id 12345678
|
||||||
|
for <test_suite_other@notmuchmail.org>; Sat, 10 Apr 2010 07:54:51 -0400 (EDT)\"" \
|
||||||
|
|
||||||
|
notmuch config set show.extra_headers "in-reply-to;received"
|
||||||
|
output=$(notmuch show --format=json --body=false id:${gen_msg_id} | notmuch_json_show_sanitize)
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
[
|
||||||
|
[
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"crypto": {},
|
||||||
|
"date_relative": "2000-01-01",
|
||||||
|
"excluded": false,
|
||||||
|
"filename": [
|
||||||
|
"YYYYY"
|
||||||
|
],
|
||||||
|
"headers": {
|
||||||
|
"Date": "Sat, 01 Jan 2000 12:00:00 +0000",
|
||||||
|
"From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
|
||||||
|
"In-Reply-To": "<parent@notmuch-test-suite>",
|
||||||
|
"Received": "from mail.example.com (mail.example.com [1.1.1.1])\tby mail.notmuchmail.org (some MTA) with ESMTP id 12345678\tfor <test_suite_other@notmuchmail.org>; Sat, 10 Apr 2010 07:54:51 -0400 (EDT)",
|
||||||
|
"Subject": "extra-headers",
|
||||||
|
"To": "Notmuch Test Suite <test_suite@notmuchmail.org>"
|
||||||
|
},
|
||||||
|
"id": "XXXXX",
|
||||||
|
"match": true,
|
||||||
|
"tags": [
|
||||||
|
"inbox",
|
||||||
|
"unread"
|
||||||
|
],
|
||||||
|
"timestamp": 946728000
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
EOF
|
||||||
|
test_expect_equal_json "${output}" "$(cat EXPECTED)"
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
|
@ -47,4 +47,18 @@ filename=$(notmuch search --output=files "id:$id")
|
||||||
attachment_length=$(( $(base64 $NOTMUCH_SRCDIR/test/README | wc -c) - 1 ))
|
attachment_length=$(( $(base64 $NOTMUCH_SRCDIR/test/README | wc -c) - 1 ))
|
||||||
test_expect_equal "$output" "((((:id \"$id\" :match t :excluded nil :filename (\"$filename\") :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\") :body ((:id 1 :content-type \"multipart/mixed\" :content ((:id 2 :content-type \"text/plain\" :content \"This is a test message with inline attachment with a filename\") (:id 3 :content-type \"application/octet-stream\" :content-disposition \"inline\" :filename \"README\" :content-transfer-encoding \"base64\" :content-length $attachment_length)))) :crypto () :headers (:Subject \"sexp-show-inline-attachment-filename\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"test_suite@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\")) ())))"
|
test_expect_equal "$output" "((((:id \"$id\" :match t :excluded nil :filename (\"$filename\") :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\") :body ((:id 1 :content-type \"multipart/mixed\" :content ((:id 2 :content-type \"text/plain\" :content \"This is a test message with inline attachment with a filename\") (:id 3 :content-type \"application/octet-stream\" :content-disposition \"inline\" :filename \"README\" :content-transfer-encoding \"base64\" :content-length $attachment_length)))) :crypto () :headers (:Subject \"sexp-show-inline-attachment-filename\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"test_suite@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\")) ())))"
|
||||||
|
|
||||||
|
test_begin_subtest "show extra headers"
|
||||||
|
add_message "[subject]=\"extra-headers\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[in-reply-to]=\"<parent@notmuch-test-suite>\"" "[body]=\"extra-headers test\""\
|
||||||
|
"[header]=\"Received: from mail.example.com (mail.example.com [1.1.1.1])
|
||||||
|
by mail.notmuchmail.org (some MTA) with ESMTP id 12345678
|
||||||
|
for <test_suite_other@notmuchmail.org>; Sat, 10 Apr 2010 07:54:51 -0400 (EDT)\"" \
|
||||||
|
|
||||||
|
notmuch config set show.extra_headers "in-reply-to;received"
|
||||||
|
notmuch show --format=sexp --body=false id:${gen_msg_id} | \
|
||||||
|
notmuch_dir_sanitize | sed 's/msg-[0-9]*/MSG/g'> OUTPUT
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
((((:id "MSG@notmuch-test-suite" :match t :excluded nil :filename ("MAIL_DIR/MSG") :timestamp 946728000 :date_relative "2000-01-01" :tags ("inbox" "unread") :crypto () :headers (:Subject "extra-headers" :From "Notmuch Test Suite <test_suite@notmuchmail.org>" :To "Notmuch Test Suite <test_suite@notmuchmail.org>" :Date "Sat, 01 Jan 2000 12:00:00 +0000" :In-Reply-To "<parent@notmuch-test-suite>" :Received "from mail.example.com (mail.example.com [1.1.1.1])\011by mail.notmuchmail.org (some MTA) with ESMTP id 12345678\011for <test_suite_other@notmuchmail.org>; Sat, 10 Apr 2010 07:54:51 -0400 (EDT)")) ())))
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
|
@ -485,6 +485,31 @@ Sender <sender@example.com> writes:
|
||||||
EOF
|
EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "Reply with show.extra_headers set"
|
||||||
|
notmuch config set show.extra_headers Received
|
||||||
|
add_message '[from]="Sender <sender@example.com>"' \
|
||||||
|
[to]=test_suite_other@notmuchmail.org
|
||||||
|
|
||||||
|
test_emacs "(let ((message-hidden-headers '()))
|
||||||
|
(notmuch-search \"id:\\\"${gen_msg_id}\\\"\")
|
||||||
|
(notmuch-test-wait)
|
||||||
|
(notmuch-search-reply-to-thread)
|
||||||
|
(test-output))"
|
||||||
|
cat <<EOF >EXPECTED
|
||||||
|
From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
|
||||||
|
To: Sender <sender@example.com>
|
||||||
|
Subject: Re: ${test_subtest_name}
|
||||||
|
In-Reply-To: <${gen_msg_id}>
|
||||||
|
Fcc: ${MAIL_DIR}/sent
|
||||||
|
References: <${gen_msg_id}>
|
||||||
|
--text follows this line--
|
||||||
|
Sender <sender@example.com> writes:
|
||||||
|
|
||||||
|
> This is just a test message (#${gen_msg_cnt})
|
||||||
|
EOF
|
||||||
|
notmuch config set show.extra_headers
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
test_begin_subtest "Reply from address in named group list within emacs"
|
test_begin_subtest "Reply from address in named group list within emacs"
|
||||||
add_message '[from]="Sender <sender@example.com>"' \
|
add_message '[from]="Sender <sender@example.com>"' \
|
||||||
'[to]=group:test_suite@notmuchmail.org,someone@example.com\;' \
|
'[to]=group:test_suite@notmuchmail.org,someone@example.com\;' \
|
||||||
|
@ -680,7 +705,7 @@ References: <XXX>
|
||||||
--text follows this line--
|
--text follows this line--
|
||||||
test_suite@notmuchmail.org writes:
|
test_suite@notmuchmail.org writes:
|
||||||
|
|
||||||
> This is just a test message (#7)
|
> This is just a test message (#${gen_msg_cnt})
|
||||||
EOF
|
EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
|
|
@ -13,16 +13,29 @@ test_description='PGP/MIME signature verification and decryption'
|
||||||
test_require_emacs
|
test_require_emacs
|
||||||
add_gnupg_home
|
add_gnupg_home
|
||||||
|
|
||||||
test_begin_subtest "emacs delivery of signed message"
|
test_begin_subtest "emacs delivery of signed message via fcc"
|
||||||
test_expect_success \
|
test_expect_success \
|
||||||
'emacs_fcc_message \
|
'emacs_fcc_message \
|
||||||
"test signed message 001" \
|
"test signed message 001" \
|
||||||
"This is a test signed message." \
|
"This is a test signed message." \
|
||||||
"(mml-secure-message-sign)"'
|
"(mml-secure-message-sign)"'
|
||||||
|
|
||||||
|
test_begin_subtest "emacs delivery of signed message via fcc and smtp"
|
||||||
|
emacs_deliver_message \
|
||||||
|
'signed message sent via SMTP' \
|
||||||
|
'This is a test that messages are sent via SMTP' \
|
||||||
|
"(add-hook 'message-send-mail-hook (lambda () (sleep-for 1)))
|
||||||
|
(mml-secure-message-sign)"
|
||||||
|
msg_file=$(notmuch search --output=files subject:signed-message-sent-via-SMTP)
|
||||||
|
test_expect_equal_message_body sent_message "$msg_file"
|
||||||
|
|
||||||
test_begin_subtest "signed part content-type indexing"
|
test_begin_subtest "signed part content-type indexing"
|
||||||
output=$(notmuch search mimetype:multipart/signed and mimetype:application/pgp-signature | notmuch_search_sanitize)
|
notmuch search mimetype:multipart/signed and mimetype:application/pgp-signature | notmuch_search_sanitize > OUTPUT
|
||||||
test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; test signed message 001 (inbox signed)"
|
cat <<EOF >EXPECTED
|
||||||
|
thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; test signed message 001 (inbox signed)
|
||||||
|
thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; signed message sent via SMTP (inbox signed)
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
test_begin_subtest "signature verification"
|
test_begin_subtest "signature verification"
|
||||||
output=$(notmuch show --format=json --verify subject:"test signed message 001" \
|
output=$(notmuch show --format=json --verify subject:"test signed message 001" \
|
||||||
|
|
|
@ -24,8 +24,8 @@ test_expect_equal "$output" "No new mail."
|
||||||
|
|
||||||
test_begin_subtest "Multiple files for same message"
|
test_begin_subtest "Multiple files for same message"
|
||||||
cat <<EOF >EXPECTED
|
cat <<EOF >EXPECTED
|
||||||
MAIL_DIR/msg-001
|
MAIL_DIR/msg-XXX
|
||||||
MAIL_DIR/spam/msg-001
|
MAIL_DIR/spam/msg-XXX
|
||||||
EOF
|
EOF
|
||||||
notmuch search --output=files id:$id_x | notmuch_search_files_sanitize >OUTPUT
|
notmuch search --output=files id:$id_x | notmuch_search_files_sanitize >OUTPUT
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
48
test/T392-python-cffi-notmuch.sh
Executable file
48
test/T392-python-cffi-notmuch.sh
Executable file
|
@ -0,0 +1,48 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
test_description="python bindings (notmuch test suite)"
|
||||||
|
. $(dirname "$0")/test-lib.sh || exit 1
|
||||||
|
|
||||||
|
if [ $NOTMUCH_HAVE_PYTHON3_CFFI -eq 0 -o $NOTMUCH_HAVE_PYTHON3_PYTEST -eq 0 ]; then
|
||||||
|
test_done
|
||||||
|
fi
|
||||||
|
|
||||||
|
add_email_corpus
|
||||||
|
|
||||||
|
cat <<EOF > recurse.py
|
||||||
|
from notmuch2 import Database
|
||||||
|
def show_msgs(msgs, level):
|
||||||
|
print('{:s} {:s}'.format(' ' * level*4, type(msgs).__name__))
|
||||||
|
for msg in msgs:
|
||||||
|
print('{:s} {:s}'.format(' ' * (level*4+2), type(msg).__name__))
|
||||||
|
replies=msg.replies()
|
||||||
|
show_msgs(replies, level+1)
|
||||||
|
db = Database(config=Database.CONFIG.SEARCH)
|
||||||
|
msg=db.find("87ocn0qh6d.fsf@yoom.home.cworth.org")
|
||||||
|
threads = db.threads(query="thread:"+msg.threadid)
|
||||||
|
thread = next (threads)
|
||||||
|
show_msgs(thread, 0)
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_begin_subtest "recursive traversal of replies (no crash)"
|
||||||
|
test_python < recurse.py
|
||||||
|
error=$?
|
||||||
|
test_expect_equal "${error}" 0
|
||||||
|
|
||||||
|
test_begin_subtest "recursive traversal of replies (output)"
|
||||||
|
test_python < recurse.py
|
||||||
|
tail -n 10 < OUTPUT > OUTPUT.sample
|
||||||
|
cat <<EOF > EXPECTED
|
||||||
|
OwnedMessage
|
||||||
|
MessageIter
|
||||||
|
OwnedMessage
|
||||||
|
MessageIter
|
||||||
|
OwnedMessage
|
||||||
|
MessageIter
|
||||||
|
OwnedMessage
|
||||||
|
MessageIter
|
||||||
|
OwnedMessage
|
||||||
|
MessageIter
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT.sample
|
||||||
|
|
||||||
|
test_done
|
|
@ -68,6 +68,16 @@ test_emacs '(notmuch-hello)
|
||||||
notmuch tag -$tag '*'
|
notmuch tag -$tag '*'
|
||||||
test_expect_equal_file $EXPECTED/notmuch-hello-long-names OUTPUT
|
test_expect_equal_file $EXPECTED/notmuch-hello-long-names OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "All tags show up"
|
||||||
|
tag=exclude_me
|
||||||
|
notmuch tag +$tag '*'
|
||||||
|
notmuch config set search.exclude_tags $tag
|
||||||
|
test_emacs '(notmuch-hello)
|
||||||
|
(test-output)'
|
||||||
|
notmuch tag -$tag '*'
|
||||||
|
test_expect_equal_file $EXPECTED/notmuch-hello-all-tags OUTPUT
|
||||||
|
|
||||||
|
test_done
|
||||||
test_begin_subtest "notmuch-hello with nonexistent CWD"
|
test_begin_subtest "notmuch-hello with nonexistent CWD"
|
||||||
test_emacs '
|
test_emacs '
|
||||||
(notmuch-hello)
|
(notmuch-hello)
|
||||||
|
|
|
@ -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_expect_equal_file $EXPECTED/notmuch-show-decrypted-message OUTPUT
|
||||||
|
|
||||||
test_begin_subtest "show encrypted rfc822 message"
|
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_emacs '(notmuch-show "id:encrypted-rfc822-attachment@crypto.notmuchmail.org")
|
||||||
(test-visible-output)'
|
(test-visible-output)'
|
||||||
test_expect_code 1 'fgrep "!!!" OUTPUT'
|
test_expect_code 1 'fgrep "!!!" OUTPUT'
|
||||||
|
|
|
@ -9,10 +9,8 @@ test_begin_subtest "building database"
|
||||||
test_expect_success "NOTMUCH_NEW"
|
test_expect_success "NOTMUCH_NEW"
|
||||||
|
|
||||||
cat <<EOF > c_head
|
cat <<EOF > c_head
|
||||||
#include <stdio.h>
|
|
||||||
#include <notmuch.h>
|
|
||||||
#include <notmuch-test.h>
|
#include <notmuch-test.h>
|
||||||
#include <talloc.h>
|
|
||||||
int main (int argc, char** argv)
|
int main (int argc, char** argv)
|
||||||
{
|
{
|
||||||
notmuch_database_t *db;
|
notmuch_database_t *db;
|
||||||
|
@ -82,7 +80,7 @@ cat <<EOF > EXPECTED
|
||||||
== stdout ==
|
== stdout ==
|
||||||
0
|
0
|
||||||
== stderr ==
|
== 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
|
EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
@ -147,7 +145,7 @@ cat <<EOF > EXPECTED
|
||||||
== stdout ==
|
== stdout ==
|
||||||
1
|
1
|
||||||
== stderr ==
|
== 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
|
EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,8 @@ test_begin_subtest "building database"
|
||||||
test_expect_success "NOTMUCH_NEW"
|
test_expect_success "NOTMUCH_NEW"
|
||||||
|
|
||||||
cat <<EOF > c_head
|
cat <<EOF > c_head
|
||||||
#include <stdio.h>
|
|
||||||
#include <notmuch.h>
|
|
||||||
#include <notmuch-test.h>
|
#include <notmuch-test.h>
|
||||||
#include <talloc.h>
|
|
||||||
int main (int argc, char** argv)
|
int main (int argc, char** argv)
|
||||||
{
|
{
|
||||||
notmuch_database_t *db;
|
notmuch_database_t *db;
|
||||||
|
@ -53,7 +51,7 @@ cat <<EOF > EXPECTED
|
||||||
== stdout ==
|
== stdout ==
|
||||||
1
|
1
|
||||||
== stderr ==
|
== 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
|
EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
@ -70,7 +68,7 @@ cat <<EOF > EXPECTED
|
||||||
== stdout ==
|
== stdout ==
|
||||||
1
|
1
|
||||||
== stderr ==
|
== 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
|
EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,8 @@ test_begin_subtest "building database"
|
||||||
test_expect_success "NOTMUCH_NEW"
|
test_expect_success "NOTMUCH_NEW"
|
||||||
|
|
||||||
cat <<EOF > c_head
|
cat <<EOF > c_head
|
||||||
#include <stdio.h>
|
|
||||||
#include <notmuch.h>
|
|
||||||
#include <notmuch-test.h>
|
#include <notmuch-test.h>
|
||||||
#include <talloc.h>
|
|
||||||
int main (int argc, char** argv)
|
int main (int argc, char** argv)
|
||||||
{
|
{
|
||||||
notmuch_database_t *db;
|
notmuch_database_t *db;
|
||||||
|
|
|
@ -19,9 +19,8 @@ cat <<'EOF' > c_tail
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat <<EOF > c_head0
|
cat <<EOF > c_head0
|
||||||
#include <stdio.h>
|
|
||||||
#include <notmuch.h>
|
|
||||||
#include <notmuch-test.h>
|
#include <notmuch-test.h>
|
||||||
|
|
||||||
int main (int argc, char** argv)
|
int main (int argc, char** argv)
|
||||||
{
|
{
|
||||||
notmuch_database_t *db;
|
notmuch_database_t *db;
|
||||||
|
|
|
@ -24,9 +24,8 @@ cat <<'EOF' > c_tail
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat <<EOF > c_head
|
cat <<EOF > c_head
|
||||||
#include <stdio.h>
|
|
||||||
#include <notmuch.h>
|
|
||||||
#include <notmuch-test.h>
|
#include <notmuch-test.h>
|
||||||
|
|
||||||
int main (int argc, char** argv)
|
int main (int argc, char** argv)
|
||||||
{
|
{
|
||||||
notmuch_database_t *db;
|
notmuch_database_t *db;
|
||||||
|
|
|
@ -23,8 +23,6 @@ EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
cat <<EOF > c_head
|
cat <<EOF > c_head
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <notmuch-test.h>
|
#include <notmuch-test.h>
|
||||||
|
|
||||||
int main (int argc, char** argv)
|
int main (int argc, char** argv)
|
||||||
|
@ -272,6 +270,29 @@ EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
restore_database
|
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"
|
test_begin_subtest "notmuch_config_get_values_string"
|
||||||
cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
|
cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
|
||||||
{
|
{
|
||||||
|
@ -418,6 +439,7 @@ cat <<'EOF' >EXPECTED
|
||||||
09: 'NULL'
|
09: 'NULL'
|
||||||
10: 'USER_FULL_NAME'
|
10: 'USER_FULL_NAME'
|
||||||
11: '8000'
|
11: '8000'
|
||||||
|
12: 'NULL'
|
||||||
== stderr ==
|
== stderr ==
|
||||||
EOF
|
EOF
|
||||||
unset MAILDIR
|
unset MAILDIR
|
||||||
|
@ -616,8 +638,6 @@ cp notmuch-config.bak notmuch-config
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
cat <<EOF > c_head2
|
cat <<EOF > c_head2
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <notmuch-test.h>
|
#include <notmuch-test.h>
|
||||||
|
|
||||||
int main (int argc, char** argv)
|
int main (int argc, char** argv)
|
||||||
|
@ -730,6 +750,7 @@ cat <<'EOF' >EXPECTED
|
||||||
09: 'test_suite_other@notmuchmail.org;test_suite@otherdomain.org'
|
09: 'test_suite_other@notmuchmail.org;test_suite@otherdomain.org'
|
||||||
10: 'Notmuch Test Suite'
|
10: 'Notmuch Test Suite'
|
||||||
11: '8000'
|
11: '8000'
|
||||||
|
12: 'NULL'
|
||||||
== stderr ==
|
== stderr ==
|
||||||
EOF
|
EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
@ -763,6 +784,7 @@ cat <<'EOF' >EXPECTED
|
||||||
09: 'NULL'
|
09: 'NULL'
|
||||||
10: 'USER_FULL_NAME'
|
10: 'USER_FULL_NAME'
|
||||||
11: '8000'
|
11: '8000'
|
||||||
|
12: 'NULL'
|
||||||
== stderr ==
|
== stderr ==
|
||||||
EOF
|
EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT.clean
|
test_expect_equal_file EXPECTED OUTPUT.clean
|
||||||
|
@ -839,6 +861,7 @@ maildir.synchronize_flags true
|
||||||
new.ignore sekrit_junk
|
new.ignore sekrit_junk
|
||||||
new.tags unread;inbox
|
new.tags unread;inbox
|
||||||
search.exclude_tags foo;bar;fub
|
search.exclude_tags foo;bar;fub
|
||||||
|
show.extra_headers (null)
|
||||||
test.key1 testvalue1
|
test.key1 testvalue1
|
||||||
test.key2 testvalue2
|
test.key2 testvalue2
|
||||||
user.name Notmuch Test Suite
|
user.name Notmuch Test Suite
|
||||||
|
@ -953,6 +976,7 @@ EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
test_begin_subtest "open: database parameter overrides implicit config"
|
test_begin_subtest "open: database parameter overrides implicit config"
|
||||||
|
cp $NOTMUCH_CONFIG ${NOTMUCH_CONFIG}.bak
|
||||||
notmuch config set database.path ${MAIL_DIR}/nonexistent
|
notmuch config set database.path ${MAIL_DIR}/nonexistent
|
||||||
cat c_head3 - c_tail3 <<'EOF' | test_C ${MAIL_DIR}
|
cat c_head3 - c_tail3 <<'EOF' | test_C ${MAIL_DIR}
|
||||||
const char *path = NULL;
|
const char *path = NULL;
|
||||||
|
@ -963,6 +987,7 @@ cat c_head3 - c_tail3 <<'EOF' | test_C ${MAIL_DIR}
|
||||||
path = notmuch_database_get_path (db);
|
path = notmuch_database_get_path (db);
|
||||||
printf ("path: %s\n", path ? path : "(null)");
|
printf ("path: %s\n", path ? path : "(null)");
|
||||||
EOF
|
EOF
|
||||||
|
cp ${NOTMUCH_CONFIG}.bak ${NOTMUCH_CONFIG}
|
||||||
cat <<EOF> EXPECTED
|
cat <<EOF> EXPECTED
|
||||||
== stdout ==
|
== stdout ==
|
||||||
status: 0
|
status: 0
|
||||||
|
@ -973,4 +998,43 @@ EOF
|
||||||
notmuch_dir_sanitize < OUTPUT > OUTPUT.clean
|
notmuch_dir_sanitize < OUTPUT > OUTPUT.clean
|
||||||
test_expect_equal_file EXPECTED OUTPUT.clean
|
test_expect_equal_file EXPECTED OUTPUT.clean
|
||||||
|
|
||||||
|
cat <<EOF > c_body
|
||||||
|
notmuch_status_t st = notmuch_database_open_with_config(NULL,
|
||||||
|
NOTMUCH_DATABASE_MODE_READ_ONLY,
|
||||||
|
"", NULL, &db, NULL);
|
||||||
|
printf ("status == SUCCESS: %d\n", st == NOTMUCH_STATUS_SUCCESS);
|
||||||
|
if (db) {
|
||||||
|
const char *mail_root = NULL;
|
||||||
|
mail_root = notmuch_config_get (db, NOTMUCH_CONFIG_MAIL_ROOT);
|
||||||
|
printf ("mail_root: %s\n", mail_root ? mail_root : "(null)");
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat <<EOF> EXPECTED.common
|
||||||
|
== stdout ==
|
||||||
|
status == SUCCESS: 0
|
||||||
|
db == NULL: 1
|
||||||
|
== stderr ==
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_begin_subtest "open/error: config=empty with no mail root in db "
|
||||||
|
old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG}
|
||||||
|
unset NOTMUCH_CONFIG
|
||||||
|
cat c_head3 c_body c_tail3 | test_C
|
||||||
|
export NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
|
||||||
|
notmuch_dir_sanitize < OUTPUT > OUTPUT.clean
|
||||||
|
test_expect_equal_file EXPECTED.common OUTPUT.clean
|
||||||
|
|
||||||
|
test_begin_subtest "open/error: config=empty with no mail root in db (xdg)"
|
||||||
|
old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG}
|
||||||
|
unset NOTMUCH_CONFIG
|
||||||
|
backup_database
|
||||||
|
mkdir -p home/.local/share/notmuch
|
||||||
|
mv mail/.notmuch home/.local/share/notmuch/default
|
||||||
|
cat c_head3 c_body c_tail3 | test_C
|
||||||
|
restore_database
|
||||||
|
export NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
|
||||||
|
notmuch_dir_sanitize < OUTPUT > OUTPUT.clean
|
||||||
|
test_expect_equal_file EXPECTED.common OUTPUT.clean
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
|
@ -6,8 +6,6 @@ test_description="library reopen API"
|
||||||
add_email_corpus
|
add_email_corpus
|
||||||
|
|
||||||
cat <<EOF > c_head
|
cat <<EOF > c_head
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <notmuch-test.h>
|
#include <notmuch-test.h>
|
||||||
|
|
||||||
int main (int argc, char** argv)
|
int main (int argc, char** argv)
|
||||||
|
|
|
@ -6,10 +6,6 @@ test_description="message property API"
|
||||||
add_email_corpus
|
add_email_corpus
|
||||||
|
|
||||||
cat <<EOF > c_head
|
cat <<EOF > c_head
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <talloc.h>
|
|
||||||
#include <notmuch-test.h>
|
#include <notmuch-test.h>
|
||||||
|
|
||||||
void print_properties (notmuch_message_t *message, const char *prefix, notmuch_bool_t exact) {
|
void print_properties (notmuch_message_t *message, const char *prefix, notmuch_bool_t exact) {
|
||||||
|
|
|
@ -9,9 +9,6 @@ if [ $NOTMUCH_HAVE_XAPIAN_DB_RETRY_LOCK -ne 1 ]; then
|
||||||
test_subtest_known_broken
|
test_subtest_known_broken
|
||||||
fi
|
fi
|
||||||
test_C ${MAIL_DIR} <<'EOF'
|
test_C ${MAIL_DIR} <<'EOF'
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <notmuch-test.h>
|
#include <notmuch-test.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -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://)
|
first_id=$(notmuch search --output=messages '*'| head -1 | sed s/^id://)
|
||||||
|
|
||||||
test_C ${MAIL_DIR} <<EOF
|
test_C ${MAIL_DIR} <<EOF
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <notmuch-test.h>
|
#include <notmuch-test.h>
|
||||||
#include <talloc.h>
|
|
||||||
#include <assert.h>
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
|
@ -58,13 +58,13 @@ test_expect_equal_file EXPECTED OUTPUT
|
||||||
test_begin_subtest "notmuch search --output=files with partially gzipped mail store"
|
test_begin_subtest "notmuch search --output=files with partially gzipped mail store"
|
||||||
notmuch search --output=files '*' | notmuch_search_files_sanitize > OUTPUT
|
notmuch search --output=files '*' | notmuch_search_files_sanitize > OUTPUT
|
||||||
cat <<EOF > EXPECTED
|
cat <<EOF > EXPECTED
|
||||||
MAIL_DIR/msg-001.gz
|
MAIL_DIR/msg-XXX.gz
|
||||||
MAIL_DIR/msg-002.gz
|
MAIL_DIR/msg-XXX.gz
|
||||||
MAIL_DIR/msg-003.gz
|
MAIL_DIR/msg-XXX.gz
|
||||||
MAIL_DIR/msg-004
|
MAIL_DIR/msg-XXX
|
||||||
MAIL_DIR/msg-005.gz
|
MAIL_DIR/msg-XXX.gz
|
||||||
MAIL_DIR/msg-006
|
MAIL_DIR/msg-XXX
|
||||||
MAIL_DIR/msg-007.gz
|
MAIL_DIR/msg-XXX.gz
|
||||||
EOF
|
EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue