From: David Bremner Date: Sun, 10 Feb 2019 13:47:47 +0000 (-0400) Subject: Merge branch 'release' X-Git-Tag: archive/debian/0.29_rc0-1~138 X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=commitdiff_plain;h=3d0fd40eb0eca54fd05460203ae754c63f633d69;hp=3c752b855f900f5251df9997514b4d27d9f38e83 Merge branch 'release' --- diff --git a/NEWS b/NEWS index 7de5ea7f..d46035cd 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,12 @@ +Notmuch 0.29 (UNRELEASED) +========================= + +Command Line Interface +---------------------- + +`notmuch show` now supports --body=false and --include-html with +--format=text + Notmuch 0.28.1 (2019-02-01) =========================== diff --git a/configure b/configure index ea22587b..a6f5dfa2 100755 --- a/configure +++ b/configure @@ -623,8 +623,8 @@ if [ -z "${EMACSETCDIR-}" ]; then EMACSETCDIR="\$(prefix)/share/emacs/site-lisp" fi -printf "Checking if emacs is available... " -if emacs --quick --batch > /dev/null 2>&1; then +printf "Checking if emacs (>= 24) is available... " +if emacs --quick --batch --eval '(if (< emacs-major-version 24) (kill-emacs 1))' > /dev/null 2>&1; then printf "Yes.\n" have_emacs=1 else diff --git a/debugger.c b/debugger.c index 5cb38ac4..0febf170 100644 --- a/debugger.c +++ b/debugger.c @@ -32,13 +32,14 @@ bool debugger_is_active (void) { char buf[1024]; + char buf2[1024]; if (RUNNING_ON_VALGRIND) return true; sprintf (buf, "/proc/%d/exe", getppid ()); - if (readlink (buf, buf, sizeof (buf)) != -1 && - strncmp (basename (buf), "gdb", 3) == 0) + if (readlink (buf, buf2, sizeof (buf2)) != -1 && + strncmp (basename (buf2), "gdb", 3) == 0) { return true; } diff --git a/doc/Makefile.local b/doc/Makefile.local index 16459e35..f53b3702 100644 --- a/doc/Makefile.local +++ b/doc/Makefile.local @@ -37,6 +37,10 @@ INFO_INFO_FILES := $(INFO_TEXI_FILES:.texi=.info) %.gz: % rm -f $@ && gzip --stdout $^ > $@ +ifeq ($(WITH_EMACS),1) +$(DOCBUILDDIR)/.roff.stamp sphinx-html sphinx-texinfo: docstring.stamp +endif + sphinx-html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(DOCBUILDDIR)/html diff --git a/doc/man1/notmuch-address.rst b/doc/man1/notmuch-address.rst index 12d86e89..2a7df6f0 100644 --- a/doc/man1/notmuch-address.rst +++ b/doc/man1/notmuch-address.rst @@ -92,7 +92,7 @@ Supported options for **address** include ``--exclude=(true|false)`` A message is called "excluded" if it matches at least one tag in - search.tag\_exclude that does not appear explicitly in the search + search.exclude\_tags that does not appear explicitly in the search terms. This option specifies whether to omit excluded messages in the search process. diff --git a/doc/man1/notmuch-count.rst b/doc/man1/notmuch-count.rst index 9ca20dab..0eac5dbe 100644 --- a/doc/man1/notmuch-count.rst +++ b/doc/man1/notmuch-count.rst @@ -36,7 +36,7 @@ Supported options for **count** include same message-id). ``--exclude=(true|false)`` - Specify whether to omit messages matching search.tag\_exclude from + Specify whether to omit messages matching search.exclude\_tags from the count (the default) or not. ``--batch`` diff --git a/doc/man1/notmuch-search.rst b/doc/man1/notmuch-search.rst index 654c5f2c..ed9ff4e5 100644 --- a/doc/man1/notmuch-search.rst +++ b/doc/man1/notmuch-search.rst @@ -100,7 +100,7 @@ Supported options for **search** include ``--exclude=(true|false|all|flag)`` A message is called "excluded" if it matches at least one tag in - search.tag\_exclude that does not appear explicitly in the search + search.exclude\_tags that does not appear explicitly in the search terms. This option specifies whether to omit excluded messages in the search process. diff --git a/doc/man1/notmuch-show.rst b/doc/man1/notmuch-show.rst index 8bfa87c6..becd3e79 100644 --- a/doc/man1/notmuch-show.rst +++ b/doc/man1/notmuch-show.rst @@ -161,7 +161,7 @@ Supported options for **show** include Default: ``auto`` ``--exclude=(true|false)`` - Specify whether to omit threads only matching search.tag\_exclude + Specify whether to omit threads only matching search.exclude\_tags from the search results (the default) or not. In either case the excluded message will be marked with the exclude flag (except when output=mbox when there is nowhere to put the flag). @@ -176,18 +176,19 @@ Supported options for **show** include ``--body=(true|false)`` If true (the default) **notmuch show** includes the bodies of the messages in the output; if false, bodies are omitted. - ``--body=false`` is only implemented for the json and sexp formats - and it is incompatible with ``--part > 0.`` + ``--body=false`` is only implemented for the text, json and sexp + formats and it is incompatible with ``--part > 0.`` This is useful if the caller only needs the headers as body-less output is much faster and substantially smaller. ``--include-html`` - Include "text/html" parts as part of the output (currently only - supported with ``--format=json`` and ``--format=sexp``). By default, - unless ``--part=N`` is used to select a specific part or - ``--include-html`` is used to include all "text/html" parts, no - part with content type "text/html" is included in the output. + Include "text/html" parts as part of the output (currently + only supported with ``--format=text``, ``--format=json`` and + ``--format=sexp``). By default, unless ``--part=N`` is used to + select a specific part or ``--include-html`` is used to include all + "text/html" parts, no part with content type "text/html" is included + in the output. A common use of **notmuch show** is to display a single thread of email messages. For this, use a search term of "thread:" as can be diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst index ce2e358e..2e85b8a5 100644 --- a/doc/notmuch-emacs.rst +++ b/doc/notmuch-emacs.rst @@ -190,6 +190,9 @@ pressing RET after positioning the cursor on a hidden part. advance to the next message, or advance to the next thread (if already on the last message of a thread). +``c`` + :ref:`show-copy` + ``N`` Move to next message @@ -208,6 +211,63 @@ pressing RET after positioning the cursor on a hidden part. ``?`` Display full set of key bindings +Display of messages can be controlled by the following variables + +:index:`notmuch-message-headers` + |docstring::notmuch-message-headers| + +:index:`notmuch-message-headers-visible` + |docstring::notmuch-message-headers-visible| + +.. _show-copy: + +Copy to kill-ring +----------------- + +You can use the usually Emacs ways of copying text to the kill-ring, +but notmuch also provides some shortcuts. These keys are available in +:ref:`notmuch-show`, and :ref:`notmuch-tree`. A subset are available +in :ref:`notmuch-search`. + +``c F`` ``notmuch-show-stash-filename`` + |docstring::notmuch-show-stash-filename| + +``c G`` ``notmuch-show-stash-git-send-email`` + |docstring::notmuch-show-stash-git-send-email| + +``c I`` ``notmuch-show-stash-message-id-stripped`` + |docstring::notmuch-show-stash-message-id-stripped| + +``c L`` ``notmuch-show-stash-mlarchive-link-and-go`` + |docstring::notmuch-show-stash-mlarchive-link-and-go| + +``c T`` ``notmuch-show-stash-tags`` + |docstring::notmuch-show-stash-tags| + +``c c`` ``notmuch-show-stash-cc`` + |docstring::notmuch-show-stash-cc| + +``c d`` ``notmuch-show-stash-date`` + |docstring::notmuch-show-stash-date| + +``c f`` ``notmuch-show-stash-from`` + |docstring::notmuch-show-stash-from| + +``c i`` ``notmuch-show-stash-message-id`` + |docstring::notmuch-show-stash-message-id| + +``c l`` ``notmuch-show-stash-mlarchive-link`` + |docstring::notmuch-show-stash-mlarchive-link| + +``c s`` ``notmuch-show-stash-subject`` + |docstring::notmuch-show-stash-subject| + +``c t`` ``notmuch-show-stash-to`` + |docstring::notmuch-show-stash-to| + +``c ?`` + Show all available copying commands + .. _notmuch-tree: notmuch-tree @@ -218,6 +278,9 @@ email archives. Each line in the buffer represents a single message giving the relative date, the author, subject, and any tags. +``c`` + :ref:`show-copy` + ```` Displays that message. @@ -275,7 +338,13 @@ operations specified in ``notmuch-tagging-keys``; i.e. each :index:`notmuch-tagging-keys` - A list of keys and corresponding tagging operations. + |docstring::notmuch-tagging-keys| + +Buffer navigation +================= + +:index:`notmuch-cycle-notmuch-buffers` + |docstring::notmuch-cycle-notmuch-buffers| Configuration ============= @@ -286,8 +355,10 @@ Importing Mail -------------- :index:`notmuch-poll` + |docstring::notmuch-poll| :index:`notmuch-poll-script` + |docstring::notmuch-poll-script| Init File --------- @@ -300,3 +371,13 @@ suffix exist it will be read instead (just one of these, chosen in this order). Most often users create ``~/.emacs.d/notmuch-config.el`` and just work with it. If Emacs was invoked with the ``-q`` or ``--no-init-file`` options, ``notmuch-init-file`` is not read. + +.. include:: ../emacs/rstdoc.rsti + +.. include:: ../emacs/notmuch.rsti + +.. include:: ../emacs/notmuch-lib.rsti + +.. include:: ../emacs/notmuch-show.rsti + +.. include:: ../emacs/notmuch-tag.rsti diff --git a/emacs/.gitignore b/emacs/.gitignore index fbf8dde6..b9873b0a 100644 --- a/emacs/.gitignore +++ b/emacs/.gitignore @@ -1,4 +1,5 @@ /.eldeps* /*.elc +/*.rsti /notmuch-version.el /notmuch-pkg.el diff --git a/emacs/Makefile.local b/emacs/Makefile.local index 5e4ae1bd..04913a06 100644 --- a/emacs/Makefile.local +++ b/emacs/Makefile.local @@ -45,6 +45,10 @@ emacs_images := \ $(srcdir)/$(dir)/notmuch-logo.png emacs_bytecode = $(emacs_sources:.el=.elc) +emacs_docstrings = $(emacs_sources:.el=.rsti) + +docstring.stamp: ${emacs_docstrings} + touch $@ # Because of defmacro's and defsubst's, we have to account for load # dependencies between Elisp files when byte compiling. Otherwise, @@ -76,6 +80,8 @@ CLEAN+=$(dir)/.eldeps $(dir)/.eldeps.tmp $(dir)/.eldeps.x ifeq ($(HAVE_EMACS),1) %.elc: %.el $(global_deps) $(call quiet,EMACS) --directory emacs -batch -f batch-byte-compile $< +%.rsti: %.el + $(call quiet,EMACS) -batch -L emacs -l rstdoc -f rstdoc-batch-extract $< $@ endif elpa: $(ELPA_FILE) @@ -93,7 +99,7 @@ endif ifeq ($(WITH_EMACS),1) ifeq ($(HAVE_EMACS),1) -all: $(emacs_bytecode) +all: $(emacs_bytecode) $(emacs_docstrings) install-emacs: $(emacs_bytecode) endif @@ -120,4 +126,5 @@ ifeq ($(WITH_DESKTOP),1) -update-desktop-database "$(DESTDIR)$(desktop_dir)" endif -CLEAN := $(CLEAN) $(emacs_bytecode) $(dir)/notmuch-version.el $(dir)/notmuch-pkg.el +CLEAN := $(CLEAN) $(emacs_bytecode) $(dir)/notmuch-version.el $(dir)/notmuch-pkg.el \ + $(emacs_docstrings) docstring.stamp diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el index df2ac447..e205fa4c 100644 --- a/emacs/notmuch-mua.el +++ b/emacs/notmuch-mua.el @@ -306,7 +306,7 @@ modified. This function is notmuch addaptation of (if window ;; Raise the frame already displaying the message buffer. (progn - (gnus-select-frame-set-input-focus (window-frame window)) + (select-frame-set-input-focus (window-frame window)) (select-window window)) (funcall switch-function buffer) (set-buffer buffer)) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index a0a58373..78f1af47 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -604,7 +604,7 @@ will return nil if the CID is unknown or cannot be retrieved." (unless (assq 'notmuch-show-mode w3m-cid-retrieve-function-alist) (push (cons 'notmuch-show-mode #'notmuch-show--cid-w3m-retrieve) w3m-cid-retrieve-function-alist))) - (setq mm-inline-text-html-with-images t)) + (setq mm-html-inhibit-images nil)) (defvar w3m-current-buffer) ;; From `w3m.el'. (defun notmuch-show--cid-w3m-retrieve (url &rest args) diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el index 5f8b9267..54108d93 100644 --- a/emacs/notmuch-wash.el +++ b/emacs/notmuch-wash.el @@ -24,7 +24,7 @@ ;;; Code: (require 'coolj) - +(require 'notmuch-lib) (declare-function notmuch-show-insert-bodypart "notmuch-show" (msg part depth &optional hide)) (defvar notmuch-show-indent-messages-width) diff --git a/emacs/notmuch.el b/emacs/notmuch.el index 44402f8a..804e78ab 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -711,7 +711,7 @@ A thread with TAG will have FACE applied. Here is an example of how to color search results based on tags. (the following text would be placed in your ~/.emacs file): - (setq notmuch-search-line-faces '((\"unread\" . (:foreground \"green\")) + (setq notmuch-search-line-faces \\='((\"unread\" . (:foreground \"green\")) (\"deleted\" . (:foreground \"red\" :background \"blue\")))) @@ -1076,7 +1076,7 @@ current search results AND the additional query string provided." Runs a new search matching only messages that match both the current search results AND that are tagged with the given tag." (interactive - (list (notmuch-select-tag-with-completion "Filter by tag: "))) + (list (notmuch-select-tag-with-completion "Filter by tag: " notmuch-search-query-string))) (notmuch-search (concat notmuch-search-query-string " and tag:" tag) notmuch-search-oldest-first)) ;;;###autoload diff --git a/emacs/rstdoc.el b/emacs/rstdoc.el new file mode 100644 index 00000000..2225aefc --- /dev/null +++ b/emacs/rstdoc.el @@ -0,0 +1,85 @@ +;;; rstdoc.el --- help generate documentation from docstrings -*-lexical-binding: t-*- + +;; Copyright (C) 2018 David Bremner + +;; Author: David Bremner +;; Created: 26 May 2018 +;; Keywords: emacs lisp, documentation +;; Homepage: https://notmuchmail.org + +;; This file is not part of GNU Emacs. + +;; rstdoc.el is free software: you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; rstdoc.el is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with rstdoc.el. If not, see . +;; + +;;; Commentary: +;; + +;; Rstdoc provides a facility to extract all of the docstrings defined in +;; an elisp source file. Usage: +;; +;; emacs -Q --batch -L . -l rstdoc -f rstdoc-batch-extract foo.el foo.rsti + +;;; Code: + +(provide 'rstdoc) + +(defun rstdoc-batch-extract () + "Extract docstrings to and from the files on the command line" + (apply #'rstdoc-extract command-line-args-left)) + +(defun rstdoc-extract (in-file out-file) + "Write docstrings from IN-FILE to OUT-FILE" + (load-file in-file) + (let* ((definitions (cdr (assoc (expand-file-name in-file) load-history))) + (doc-hash (make-hash-table :test 'eq))) + (mapc + (lambda (elt) + (let ((pair + (pcase elt + (`(defun . ,name) (cons name (documentation name))) + (`(,_ . ,_) nil) + (sym (cons sym (get sym 'variable-documentation)))))) + (when (and pair (cdr pair)) + (puthash (car pair) (cdr pair) doc-hash)))) + definitions) + (with-temp-buffer + (maphash + (lambda (key val) + (rstdoc--insert-docstring key val)) + doc-hash) + (write-region (point-min) (point-max) out-file)))) + +(defun rstdoc--insert-docstring (symbol docstring) + (insert (format "\n.. |docstring::%s| replace::\n" symbol)) + (insert (replace-regexp-in-string "^" " " (rstdoc--rst-quote-string docstring))) + (insert "\n")) + +(defvar rst--escape-alist + '( ("\\\\='" . "\\\\'") + ("\\([^\\]\\)'" . "\\1`") + ("^[[:space:]\t]*$" . "|br|") + ("^[[:space:]\t]" . "|indent| ")) + "list of (regex . replacement) pairs") + +(defun rstdoc--rst-quote-string (str) + (with-temp-buffer + (insert str) + (dolist (pair rst--escape-alist) + (goto-char (point-min)) + (while (re-search-forward (car pair) nil t) + (replace-match (cdr pair)))) + (buffer-substring (point-min) (point-max)))) + +;;; rstdoc.el ends here diff --git a/emacs/rstdoc.rsti b/emacs/rstdoc.rsti new file mode 100644 index 00000000..a449b58e --- /dev/null +++ b/emacs/rstdoc.rsti @@ -0,0 +1,21 @@ +.. -*- rst -*- + +.. |br| replace:: |br-texinfo| |br-html| + +.. |br-texinfo| raw:: texinfo + + @* @* + +.. |br-html| raw:: html + +

+ +.. |indent| replace:: |indent-texinfo| |indent-html| + +.. |indent-texinfo| raw:: texinfo + + @* @ @ @ @ + +.. |indent-html| raw:: html + +
     diff --git a/gmime-filter-reply.c b/gmime-filter-reply.c index f673c0a2..480d9381 100644 --- a/gmime-filter-reply.c +++ b/gmime-filter-reply.c @@ -19,6 +19,7 @@ #include #include "gmime-filter-reply.h" +#include "notmuch-client.h" /** * SECTION: gmime-filter-reply @@ -29,7 +30,7 @@ **/ -static void g_mime_filter_reply_class_init (GMimeFilterReplyClass *klass); +static void g_mime_filter_reply_class_init (GMimeFilterReplyClass *klass, void *class_data); static void g_mime_filter_reply_init (GMimeFilterReply *filter, GMimeFilterReplyClass *klass); static void g_mime_filter_reply_finalize (GObject *object); @@ -50,16 +51,16 @@ g_mime_filter_reply_get_type (void) if (!type) { static const GTypeInfo info = { - sizeof (GMimeFilterReplyClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) g_mime_filter_reply_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GMimeFilterReply), - 0, /* n_preallocs */ - (GInstanceInitFunc) g_mime_filter_reply_init, - NULL /* value_table */ + .class_size = sizeof (GMimeFilterReplyClass), + .base_init = NULL, + .base_finalize = NULL, + .class_init = (GClassInitFunc) g_mime_filter_reply_class_init, + .class_finalize = NULL, + .class_data = NULL, + .instance_size = sizeof (GMimeFilterReply), + .n_preallocs = 0, + .instance_init = (GInstanceInitFunc) g_mime_filter_reply_init, + .value_table = NULL, }; type = g_type_register_static (GMIME_TYPE_FILTER, "GMimeFilterReply", &info, (GTypeFlags) 0); @@ -70,7 +71,7 @@ g_mime_filter_reply_get_type (void) static void -g_mime_filter_reply_class_init (GMimeFilterReplyClass *klass) +g_mime_filter_reply_class_init (GMimeFilterReplyClass *klass, unused (void *class_data)) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GMimeFilterClass *filter_class = GMIME_FILTER_CLASS (klass); diff --git a/lib/index.cc b/lib/index.cc index 3f694387..efd9da4c 100644 --- a/lib/index.cc +++ b/lib/index.cc @@ -142,7 +142,8 @@ static void filter_reset (GMimeFilter *filter); static GMimeFilterClass *parent_class = NULL; static void -notmuch_filter_discard_non_term_class_init (NotmuchFilterDiscardNonTermClass *klass) +notmuch_filter_discard_non_term_class_init (NotmuchFilterDiscardNonTermClass *klass, + unused (void *class_data)) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GMimeFilterClass *filter_class = GMIME_FILTER_CLASS (klass); @@ -246,16 +247,16 @@ notmuch_filter_discard_non_term_new (GMimeContentType *content_type) if (!type) { static const GTypeInfo info = { - sizeof (NotmuchFilterDiscardNonTermClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) notmuch_filter_discard_non_term_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (NotmuchFilterDiscardNonTerm), - 0, /* n_preallocs */ - NULL, /* instance_init */ - NULL /* value_table */ + .class_size = sizeof (NotmuchFilterDiscardNonTermClass), + .base_init = NULL, + .base_finalize = NULL, + .class_init = (GClassInitFunc) notmuch_filter_discard_non_term_class_init, + .class_finalize = NULL, + .class_data = NULL, + .instance_size = sizeof (NotmuchFilterDiscardNonTerm), + .n_preallocs = 0, + .instance_init = NULL, + .value_table = NULL, }; type = g_type_register_static (GMIME_TYPE_FILTER, "NotmuchFilterDiscardNonTerm", &info, (GTypeFlags) 0); diff --git a/lib/notmuch.h b/lib/notmuch.h index 247f6ad7..24708f3c 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -889,10 +889,12 @@ notmuch_query_add_tag_exclude (notmuch_query_t *query, const char *tag); * notmuch_query_t *query; * notmuch_threads_t *threads; * notmuch_thread_t *thread; + * notmuch_status_t stat; * * query = notmuch_query_create (database, query_string); * - * for (threads = notmuch_query_search_threads (query); + * for (stat = notmuch_query_search_threads (query, &threads); + * stat == NOTMUCH_STATUS_SUCCESS && * notmuch_threads_valid (threads); * notmuch_threads_move_to_next (threads)) * { @@ -1400,6 +1402,8 @@ notmuch_message_get_thread_id (notmuch_message_t *message); * If there are no replies to 'message', this function will return * NULL. (Note that notmuch_messages_valid will accept that NULL * value as legitimate, and simply return FALSE for it.) + * + * The returned list will be destroyed when the thread is destroyed. */ notmuch_messages_t * notmuch_message_get_replies (notmuch_message_t *message); diff --git a/notmuch-reply.c b/notmuch-reply.c index 75cf7ecb..d87ec06d 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -369,6 +369,14 @@ add_recipients_from_message (GMimeMessage *reply, } } + /* If no recipients were added but we found one of the user's + * addresses to use as a from address then the message is from the + * user to the user - add the discovered from address to the list + * of recipients so that the reply goes back to the user. + */ + if (n == 0 && from_addr) + g_mime_message_add_recipient (reply, GMIME_ADDRESS_TYPE_TO, NULL, from_addr); + return from_addr; } diff --git a/notmuch-show.c b/notmuch-show.c index c3a3783a..07e9a5db 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -574,12 +574,18 @@ format_part_text (const void *ctx, sprinter_t *sp, mime_node_t *node, g_mime_stream_printf (stream, "Date: %s\n", date_string); g_mime_stream_printf (stream, "\fheader}\n"); + if (!params->output_body) + { + g_mime_stream_printf (stream, "\f%s}\n", part_type); + return NOTMUCH_STATUS_SUCCESS; + } g_mime_stream_printf (stream, "\fbody{\n"); } if (leaf) { if (g_mime_content_type_is_type (content_type, "text", "*") && - !g_mime_content_type_is_type (content_type, "text", "html")) + (params->include_html || + ! g_mime_content_type_is_type (content_type, "text", "html"))) { show_text_part_content (node->part, stream, 0); } else { @@ -1204,15 +1210,19 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[]) fprintf (stderr, "Warning: --body=false is incompatible with --part > 0. Disabling.\n"); params.output_body = true; } else { - if (format != NOTMUCH_FORMAT_JSON && format != NOTMUCH_FORMAT_SEXP) + if (format != NOTMUCH_FORMAT_TEXT && + format != NOTMUCH_FORMAT_JSON && + format != NOTMUCH_FORMAT_SEXP) fprintf (stderr, - "Warning: --body=false only implemented for format=json and format=sexp\n"); + "Warning: --body=false only implemented for format=text, format=json and format=sexp\n"); } } if (params.include_html && - (format != NOTMUCH_FORMAT_JSON && format != NOTMUCH_FORMAT_SEXP)) { - fprintf (stderr, "Warning: --include-html only implemented for format=json and format=sexp\n"); + (format != NOTMUCH_FORMAT_TEXT && + format != NOTMUCH_FORMAT_JSON && + format != NOTMUCH_FORMAT_SEXP)) { + fprintf (stderr, "Warning: --include-html only implemented for format=text, format=json and format=sexp\n"); } query_string = query_string_from_args (config, argc-opt_index, argv+opt_index); diff --git a/test/.gitignore b/test/.gitignore index 73fe7e24..69080e5e 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -9,3 +9,4 @@ /test-results /ghost-report /tmp.* +/message-id-parse diff --git a/test/T190-multipart.sh b/test/T190-multipart.sh index 3eeac1db..9ad141cb 100755 --- a/test/T190-multipart.sh +++ b/test/T190-multipart.sh @@ -190,6 +190,21 @@ Non-text part: application/pgp-signature EOF test_expect_equal_file EXPECTED OUTPUT +test_begin_subtest "--format=text --part=0 --body=false, message header" +notmuch show --format=text --part=0 --body=false 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT +cat <EXPECTED + message{ id:87liy5ap00.fsf@yoom.home.cworth.org depth:0 match:1 excluded:0 filename:${MAIL_DIR}/multipart + header{ +Carl Worth (2001-01-05) (attachment inbox signed unread) +Subject: Multipart message +From: Carl Worth +To: cworth@cworth.org +Date: Fri, 05 Jan 2001 15:43:57 +0000 + header} + message} +EOF +test_expect_equal_file EXPECTED OUTPUT + test_begin_subtest "--format=text --part=1, message body" notmuch show --format=text --part=1 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT cat <EXPECTED @@ -310,6 +325,15 @@ Non-text part: text/html EOF test_expect_equal_file EXPECTED OUTPUT +test_begin_subtest "--format=text --include-html --part=5, rfc822's html part" +notmuch show --format=text --include-html --part=5 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT +cat <EXPECTED + part{ ID: 5, Content-type: text/html +

This is an embedded message, with a multipart/alternative part.

+ part} +EOF +test_expect_equal_file EXPECTED OUTPUT + test_begin_subtest "--format=text --part=6, rfc822's text part" notmuch show --format=text --part=6 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT cat <EXPECTED diff --git a/test/T220-reply.sh b/test/T220-reply.sh index ebe710f9..4db3a958 100755 --- a/test/T220-reply.sh +++ b/test/T220-reply.sh @@ -180,6 +180,7 @@ test_expect_equal "$output" "From: Notmuch Test Suite References: <${gen_msg_id}> diff --git a/test/T230-reply-to-sender.sh b/test/T230-reply-to-sender.sh index 134a1063..bbeaa2b9 100755 --- a/test/T230-reply-to-sender.sh +++ b/test/T230-reply-to-sender.sh @@ -203,6 +203,7 @@ test_expect_equal "$output" "From: Notmuch Test Suite References: <${gen_msg_id}> diff --git a/test/T310-emacs.sh b/test/T310-emacs.sh index 5935819f..cb9e99a5 100755 --- a/test/T310-emacs.sh +++ b/test/T310-emacs.sh @@ -610,7 +610,7 @@ test_emacs "(let ((message-hidden-headers '())) (test-output))" cat <EXPECTED From: Notmuch Test Suite -To: +To: test_suite@notmuchmail.org Subject: Re: Reply within emacs to an html-only message In-Reply-To: <${gen_msg_id}> Fcc: ${MAIL_DIR}/sent @@ -623,7 +623,6 @@ EOF test_expect_equal_file EXPECTED OUTPUT test_begin_subtest "Reply within emacs to message from self" -test_subtest_known_broken add_message '[from]="test_suite@notmuchmail.org"' \ '[to]="test_suite@notmuchmail.org"' test_emacs "(let ((message-hidden-headers '())) @@ -657,7 +656,7 @@ test_emacs "(let ((message-hidden-headers '())) (test-output))" cat <EXPECTED From: Notmuch Test Suite -To: +To: test_suite@notmuchmail.org Subject: Re: Quote MML tags in reply In-Reply-To: Fcc: ${MAIL_DIR}/sent diff --git a/test/T350-crypto.sh b/test/T350-crypto.sh index a776ec35..73aa58de 100755 --- a/test/T350-crypto.sh +++ b/test/T350-crypto.sh @@ -388,6 +388,7 @@ output=$(notmuch reply --decrypt=true subject:"test encrypted message 002" \ | notmuch_drop_mail_headers In-Reply-To References) expected='From: Notmuch Test Suite Subject: Re: test encrypted message 002 +To: test_suite@notmuchmail.org On 01 Jan 2000 12:00:00 -0000, Notmuch Test Suite wrote: > This is another test encrypted message.' @@ -401,10 +402,10 @@ test_emacs "(let ((message-hidden-headers '()) (notmuch-show \"subject:test.encrypted.message.002\") (notmuch-show-reply) (test-output))" -# the empty To: is probably a bug, but it's not to do with encryption -grep -v -e '^In-Reply-To:' -e '^References:' -e '^Fcc:' -e 'To:' < OUTPUT > OUTPUT.clean +grep -v -e '^In-Reply-To:' -e '^References:' -e '^Fcc:' < OUTPUT > OUTPUT.clean cat <EXPECTED From: Notmuch Test Suite +To: test_suite@notmuchmail.org Subject: Re: test encrypted message 002 --text follows this line-- <#secure method=pgpmime mode=signencrypt> diff --git a/test/T720-lib-lifetime.sh b/test/T720-lib-lifetime.sh new file mode 100755 index 00000000..3d94d4df --- /dev/null +++ b/test/T720-lib-lifetime.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2018 rhn +# + + +test_description="Lifetime constraints for library" + +. $(dirname "$0")/test-lib.sh || exit 1 + +add_email_corpus threading + +test_begin_subtest "building database" +test_expect_success "NOTMUCH_NEW" + +test_begin_subtest "Message outlives parent Messages from replies" + +test_C ${MAIL_DIR} <<'EOF' +#include +#include +#include +int main (int argc, char** argv) +{ + notmuch_database_t *db; + notmuch_status_t stat; + stat = notmuch_database_open (argv[1], NOTMUCH_DATABASE_MODE_READ_ONLY, &db); + if (stat != NOTMUCH_STATUS_SUCCESS) { + fprintf (stderr, "error opening database: %d\n", stat); + exit (1); + } + + notmuch_query_t *query = notmuch_query_create (db, "id:B00-root@example.org"); + notmuch_threads_t *threads; + + stat = notmuch_query_search_threads (query, &threads); + if (stat != NOTMUCH_STATUS_SUCCESS) { + fprintf (stderr, "error querying threads: %d\n", stat); + exit (1); + } + + if (!notmuch_threads_valid (threads)) { + fprintf (stderr, "invalid threads"); + exit (1); + } + + notmuch_thread_t *thread = notmuch_threads_get (threads); + notmuch_messages_t *messages = notmuch_thread_get_messages (thread); + + if (!notmuch_messages_valid (messages)) { + fprintf (stderr, "invalid messages"); + exit (1); + } + + notmuch_message_t *message = notmuch_messages_get (messages); + notmuch_messages_t *replies = notmuch_message_get_replies (message); + if (!notmuch_messages_valid (replies)) { + fprintf (stderr, "invalid replies"); + exit (1); + } + + notmuch_message_t *reply = notmuch_messages_get (replies); + + notmuch_messages_destroy (replies); // the reply should not get destroyed here + notmuch_message_destroy (message); + notmuch_messages_destroy (messages); // nor here + + const char *mid = notmuch_message_get_message_id (reply); // should not crash when accessing + fprintf (stdout, "Reply id: %s\n", mid); + notmuch_message_destroy (reply); + notmuch_thread_destroy (thread); // this destroys the reply + notmuch_threads_destroy (threads); + notmuch_query_destroy (query); + notmuch_database_destroy (db); +} +EOF +cat <<'EOF' >EXPECTED +== stdout == +Reply id: B01-child@example.org +== stderr == +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_done