[PATCH 2/2] doc: build and install doxygen api docs
Add to the build-man and install-man targets. We also stop hardcoding the version information into doxygen.cfg --- doc/Makefile.local | 14 -- doc/doxygen.cfg| 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/doc/Makefile.local b/doc/Makefile.local index 0980c71..5189f97 100644 --- a/doc/Makefile.local +++ b/doc/Makefile.local @@ -12,6 +12,8 @@ mkdocdeps := python $(srcdir)/$(dir)/mkdocdeps.py # Internal variables. ALLSPHINXOPTS := -d $(DOCBUILDDIR)/doctrees $(SPHINXOPTS) $(srcdir)/$(dir) +APIMAN := $(DOCBUILDDIR)/man/man3/notmuch.3 +DOXYFILE := $(dir)/doxygen.cfg .PHONY: sphinx-html sphinx-texinfo sphinx-info @@ -31,7 +33,7 @@ sphinx-info: sphinx-texinfo -include $(dir)/docdeps.mk -MAN_GZIP_FILES := $(addsuffix .gz,${MAN_ROFF_FILES}) +MAN_GZIP_FILES := $(addsuffix .gz,${MAN_ROFF_FILES} ${APIMAN}) # Use the man page converter that is available. We should never depend # on MAN_ROFF_FILES if a converter is not available. @@ -59,16 +61,24 @@ else build-man: ${MAN_GZIP_FILES} install-man: ${MAN_GZIP_FILES} mkdir -p "$(DESTDIR)$(mandir)/man1" + mkdir -p "$(DESTDIR)$(mandir)/man3" mkdir -p "$(DESTDIR)$(mandir)/man5" mkdir -p "$(DESTDIR)$(mandir)/man7" install -m0644 $(DOCBUILDDIR)/man/man1/*.1.gz $(DESTDIR)/$(mandir)/man1 + install -m0644 $(DOCBUILDDIR)/man/man3/*.3.gz $(DESTDIR)/$(mandir)/man3 install -m0644 $(DOCBUILDDIR)/man/man5/*.5.gz $(DESTDIR)/$(mandir)/man5 install -m0644 $(DOCBUILDDIR)/man/man7/*.7.gz $(DESTDIR)/$(mandir)/man7 cd $(DESTDIR)/$(mandir)/man1 && ln -sf notmuch.1.gz notmuch-setup.1.gz endif +$(APIMAN): $(dir)/version.dox $(dir)/doxygen.cfg $(srcdir)/lib/notmuch.h + doxygen $(DOXYFILE) + +$(dir)/version.dox: $(srcdir)/version + sed -e 's/^/PROJECT_NAME = \"Notmuch /' -e 's/$$/\"/' < $< > $@ + $(dir)/docdeps.mk: $(dir)/conf.py $(dir)/mkdocdeps.py $(mkdocdeps) $(srcdir)/doc $(DOCBUILDDIR) $@ CLEAN := $(CLEAN) $(DOCBUILDDIR) $(dir)/docdeps.mk $(dir)/man.stamp -CLEAN := $(CLEAN) $(MAN_GZIP_FILES) $(MAN_ROFF_FILES) +CLEAN := $(CLEAN) $(MAN_GZIP_FILES) $(MAN_ROFF_FILES) $(dir)/version.dox diff --git a/doc/doxygen.cfg b/doc/doxygen.cfg index 65d5fb5..bf9f075 100644 --- a/doc/doxygen.cfg +++ b/doc/doxygen.cfg @@ -4,11 +4,11 @@ # Project related configuration options #--- DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = "Notmuch 0.17" + at INCLUDE = "doc/version.dox" PROJECT_NUMBER = PROJECT_BRIEF = PROJECT_LOGO = -OUTPUT_DIRECTORY = +OUTPUT_DIRECTORY = doc/_build CREATE_SUBDIRS = NO OUTPUT_LANGUAGE= English BRIEF_MEMBER_DESC = YES -- 1.9.0
[PATCH 1/2] doc: move doxgen config from devel/ to doc/
a first step towards actually instally the API docs --- devel/doxygen.cfg | 304 -- doc/doxygen.cfg | 304 ++ 2 files changed, 304 insertions(+), 304 deletions(-) delete mode 100644 devel/doxygen.cfg create mode 100644 doc/doxygen.cfg diff --git a/devel/doxygen.cfg b/devel/doxygen.cfg deleted file mode 100644 index 65d5fb5..000 --- a/devel/doxygen.cfg +++ /dev/null @@ -1,304 +0,0 @@ -# Doxyfile 1.8.4 - -#--- -# Project related configuration options -#--- -DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = "Notmuch 0.17" -PROJECT_NUMBER = -PROJECT_BRIEF = -PROJECT_LOGO = -OUTPUT_DIRECTORY = -CREATE_SUBDIRS = NO -OUTPUT_LANGUAGE= English -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = -ALWAYS_DETAILED_SEC= NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES= NO -STRIP_FROM_PATH= -STRIP_FROM_INC_PATH= -SHORT_NAMES= NO -JAVADOC_AUTOBRIEF = YES -QT_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -INHERIT_DOCS = YES -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 8 -ALIASES= -TCL_SUBST = -OPTIMIZE_OUTPUT_FOR_C = YES -OPTIMIZE_OUTPUT_JAVA = NO -OPTIMIZE_FOR_FORTRAN = NO -OPTIMIZE_OUTPUT_VHDL = NO -EXTENSION_MAPPING = -MARKDOWN_SUPPORT = YES -AUTOLINK_SUPPORT = YES -BUILTIN_STL_SUPPORT= NO -CPP_CLI_SUPPORT= NO -SIP_SUPPORT= NO -IDL_PROPERTY_SUPPORT = YES -DISTRIBUTE_GROUP_DOC = NO -SUBGROUPING= YES -INLINE_GROUPED_CLASSES = NO -INLINE_SIMPLE_STRUCTS = NO -TYPEDEF_HIDES_STRUCT = YES -LOOKUP_CACHE_SIZE = 0 -#--- -# Build related configuration options -#--- -EXTRACT_ALL= NO -EXTRACT_PRIVATE= NO -EXTRACT_PACKAGE= NO -EXTRACT_STATIC = NO -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -EXTRACT_ANON_NSPACES = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = NO -FORCE_LOCAL_INCLUDES = NO -INLINE_INFO= YES -SORT_MEMBER_DOCS = NO -SORT_BRIEF_DOCS= NO -SORT_MEMBERS_CTORS_1ST = NO -SORT_GROUP_NAMES = NO -SORT_BY_SCOPE_NAME = NO -STRICT_PROTO_MATCHING = NO -GENERATE_TODOLIST = NO -GENERATE_TESTLIST = NO -GENERATE_BUGLIST = NO -GENERATE_DEPRECATEDLIST= NO -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES= NO -SHOW_FILES = NO -SHOW_NAMESPACES= NO -FILE_VERSION_FILTER= -LAYOUT_FILE= -CITE_BIB_FILES = -#--- -# configuration options related to warning and progress messages -#--- -QUIET = YES -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = NO -WARN_FORMAT= "$file:$line: $text" -WARN_LOGFILE = -#--- -# configuration options related to the input files -#--- -INPUT = lib/notmuch.h -INPUT_ENCODING = UTF-8 -FILE_PATTERNS = -RECURSIVE = NO -EXCLUDE= -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXCLUDE_SYMBOLS= -EXAMPLE_PATH = -EXAMPLE_PATTERNS = -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_PATTERNS= -FILTER_SOURCE_FILES= NO -FILTER_SOURCE_PATTERNS = -USE_MDFILE_AS_MAINPAGE = -#--- -# configuration options related to source browsing -#--- -SOURCE_BROWSER = NO -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS= YES -REFERENCED_BY_RELATION = NO -REFERENCES_RELATION= NO -REFERENCES_LINK_SOURCE = YES -USE_HTAGS = NO -VERBATIM_HEADERS = NO -#--- -# configuration options related to the alphabetical class index -#--- -ALPHABETICAL_INDEX = NO -COLS_IN_ALPHA_INDEX= 5 -IGNORE_PREFIX
build and install doxygen api docs
I'm not sure if we really want to install the API docs yet, but I was reviewing Tomi's patch and it occured to me that this was one more place where we could stop hardcoding the version number.
[PATCH v2 4/5] emacs: hello: switch notmuch-hello-insert-buttons to plists
Switching notmuch-hello-insert-buttons to plists means we can easily pass extra options through to the buttons. --- emacs/notmuch-hello.el | 35 --- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 30f26db..f440352 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -424,7 +424,9 @@ (defun notmuch-hello-query-counts (query-list &rest options) these is a plist but other options are available for backwards compatibility: see `notmuch-saved-searches' for details. -The result is the list of elements of the form (NAME QUERY COUNT). +The result is a list of plists each of which includes the +properties :name NAME, :query QUERY and :count COUNT, together +with any properties in the original saved-search. The values :show-empty-searches, :filter and :filter-count from options will be handled as specified for @@ -454,23 +456,26 @@ (defun notmuch-hello-query-counts (query-list &rest options) #'identity (mapcar (lambda (elem) - (let ((name (notmuch-saved-search-get elem :name)) - (search-query (notmuch-saved-search-get elem :query)) - (message-count (prog1 (read (current-buffer)) + (let* ((elem-plist (notmuch-hello-saved-search-to-plist elem)) + (search-query (plist-get elem-plist :query)) + (filtered-query (notmuch-hello-filtered-query + search-query (plist-get options :filter))) + (message-count (prog1 (read (current-buffer)) (forward-line 1 - (and (or (plist-get options :show-empty-searches) (> message-count 0)) - (list name (notmuch-hello-filtered-query - search-query (plist-get options :filter)) -message-count + (when (and filtered-query (or (plist-get options :show-empty-searches) (> message-count 0))) + (setq elem-plist (plist-put elem-plist :query filtered-query)) + (plist-put elem-plist :count message-count query-list (defun notmuch-hello-insert-buttons (searches) "Insert buttons for SEARCHES. -SEARCHES must be a list containing lists of the form (NAME QUERY COUNT), where -QUERY is the query to start when the button for the corresponding entry is -activated. COUNT should be the number of messages matching the query. -Such a list can be computed with `notmuch-hello-query-counts'." +SEARCHES must be a list of plists each of which should contain at +least the properties :name NAME :query QUERY and :count COUNT, +where QUERY is the query to start when the button for the +corresponding entry is activated, and COUNT should be the number +of messages matching the query. Such a plist can be computed +with `notmuch-hello-query-counts'." (let* ((widest (notmuch-hello-longest-label searches)) (tags-and-width (notmuch-hello-tags-per-line widest)) (tags-per-line (car tags-and-width)) @@ -488,9 +493,9 @@ (defun notmuch-hello-insert-buttons (searches) (when elem (if (> column-indent 0) (widget-insert (make-string column-indent ? ))) - (let* ((name (first elem)) -(query (second elem)) -(msg-count (third elem))) + (let* ((name (plist-get elem :name)) +(query (plist-get elem :query)) +(msg-count (plist-get elem :count))) (widget-insert (format "%8s " (notmuch-hello-nice-number msg-count))) (widget-create 'push-button -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 5/5] emacs: Add a sort-order option to saved-searches
This adds a sort-order option to saved-searches, stores it in the saved-search buttons (widgets), and uses the stored value when the button is pressed. Storing the sort-order in the widget was suggested by Jani in id:4c3876274126985683e888641b29cf18142a5eb8.1391771337.git.j...@nikula.org. --- emacs/notmuch-hello.el |8 +++- emacs/notmuch-lib.el | 10 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index f440352..f0675f2 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -363,7 +363,8 @@ (defun notmuch-hello-reflect (list ncols) (defun notmuch-hello-widget-search (widget &rest ignore) (notmuch-search (widget-get widget :notmuch-search-terms) - notmuch-search-oldest-first)) + (widget-get widget + :notmuch-search-oldest-first))) (defun notmuch-saved-search-count (search) (car (process-lines notmuch-command "count" search))) @@ -495,12 +496,17 @@ (defun notmuch-hello-insert-buttons (searches) (widget-insert (make-string column-indent ? ))) (let* ((name (plist-get elem :name)) (query (plist-get elem :query)) +(oldest-first (case (plist-get elem :sort-order) +(newest-first nil) +(oldest-first t) +(otherwise notmuch-search-oldest-first))) (msg-count (plist-get elem :count))) (widget-insert (format "%8s " (notmuch-hello-nice-number msg-count))) (widget-create 'push-button :notify #'notmuch-hello-widget-search :notmuch-search-terms query + :notmuch-search-oldest-first oldest-first name) (setq column-indent (1+ (max 0 (- column-width (length name))) diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index a54a055..3a3c69d 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -125,7 +125,12 @@ (define-widget 'notmuch-saved-search-plist 'list (group :format "%v" :inline t (const :format " Query: " :query) (string :format "%v"))) (checklist :inline t :format "%v" -(group :format "%v" :inline t (const :format "Count-Query: " :count-query) (string :format "%v") +(group :format "%v" :inline t (const :format "Count-Query: " :count-query) (string :format "%v")) +(group :format "%v" :inline t (const :format "" :sort-order) + (choice :tag " Sort Order" + (const :tag "Default" nil) + (const :tag "Oldest-first" oldest-first) + (const :tag "Newest-first" newest-first)) (defcustom notmuch-saved-searches '((:name "inbox" :query "tag:inbox") (:name "unread" :query "tag:unread")) @@ -139,6 +144,9 @@ (defcustom notmuch-saved-searches '((:name "inbox" :query "tag:inbox") :count-query Optional extra query to generate the count shown. If not present then the :query property is used. + :sort-order Specify the sort order to be used for the search. + Possible values are 'oldest-first 'newest-first or + nil. Nil means use the default sort order. Other accepted forms are a cons cell of the form (NAME . QUERY) or a list of the form (NAME QUERY COUNT-QUERY)." -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 2/5] emacs: hello: use the saved-search helper functions
This uses the helper functions: the saved searches format has not changed yet but backwards compatibility means everything still works. --- emacs/notmuch-hello.el | 48 ++-- emacs/notmuch.el |6 +++--- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index f81ec27..568ae47 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -318,7 +318,7 @@ (defun notmuch-hello-add-saved-search (widget) (setq notmuch-saved-searches (loop for elem in notmuch-saved-searches if (not (equal name - (car elem))) + (notmuch-saved-search-get elem :name))) collect elem)) ;; Add the new one. (customize-save-variable 'notmuch-saved-searches @@ -338,7 +338,7 @@ (defun notmuch-hello-delete-search-from-history (widget) (defun notmuch-hello-longest-label (searches-alist) (or (loop for elem in searches-alist - maximize (length (car elem))) + maximize (length (notmuch-saved-search-get elem :name))) 0)) (defun notmuch-hello-reflect-generate-row (ncols nrows row list) @@ -417,13 +417,12 @@ (defun notmuch-hello-filtered-query (query filter) (concat "(" query ") and (" filter ")")) (t query))) -(defun notmuch-hello-query-counts (query-alist &rest options) - "Compute list of counts of matched messages from QUERY-ALIST. +(defun notmuch-hello-query-counts (query-list &rest options) + "Compute list of counts of matched messages from QUERY-LIST. -QUERY-ALIST must be a list containing elements of the form (NAME . QUERY) -or (NAME QUERY COUNT-QUERY). If the latter form is used, -COUNT-QUERY specifies an alternate query to be used to generate -the count for the associated query. +QUERY-LIST must be a list of saved-searches. Ideally each of +these is a plist but other options are available for backwards +compatibility: see `notmuch-saved-searches' for details. The result is the list of elements of the form (NAME QUERY COUNT). @@ -431,11 +430,9 @@ (defun notmuch-hello-query-counts (query-alist &rest options) options will be handled as specified for `notmuch-hello-insert-searches'." (with-temp-buffer -(dolist (elem query-alist nil) - (let ((count-query (if (consp (cdr elem)) -;; do we have a different query for the message count? -(third elem) - (cdr elem +(dolist (elem query-list nil) + (let ((count-query (or (notmuch-saved-search-get elem :count-query) +(notmuch-saved-search-get elem :query (insert (replace-regexp-in-string "\n" " " @@ -457,18 +454,15 @@ (defun notmuch-hello-query-counts (query-alist &rest options) #'identity (mapcar (lambda (elem) - (let ((name (car elem)) - (search-query (if (consp (cdr elem)) -;; do we have a different query for the message count? -(second elem) - (cdr elem))) + (let ((name (notmuch-saved-search-get elem :name)) + (search-query (notmuch-saved-search-get elem :query)) (message-count (prog1 (read (current-buffer)) (forward-line 1 (and (or (plist-get options :show-empty-searches) (> message-count 0)) (list name (notmuch-hello-filtered-query search-query (plist-get options :filter)) message-count - query-alist + query-list (defun notmuch-hello-insert-buttons (searches) "Insert buttons for SEARCHES. @@ -727,13 +721,15 @@ (defun notmuch-hello-insert-recent-searches () (indent-rigidly start (point) notmuch-hello-indent)) nil)) -(defun notmuch-hello-insert-searches (title query-alist &rest options) - "Insert a section with TITLE showing a list of buttons made from QUERY-ALIST. +(defun notmuch-hello-insert-searches (title query-list &rest options) + "Insert a section with TITLE showing a list of buttons made from QUERY-LIST. -QUERY-ALIST must be a list containing elements of the form (NAME . QUERY) -or (NAME QUERY COUNT-QUERY). If the latter form is used, -COUNT-QUERY specifies an alternate query to be used to generate -the count for the associated item. +QUERY-LIST should ideally be a plist but for backwards +compatibility other forms are also accepted (see +`notmuch-saved-searches' for details). The plist should +contain keys :name and :query; if :count-query is also present +then it specifies an alternate query to be used to generate the +count for the associated search. Supports the following entries in OPTIONS as a plist: :initially-hidden - if non-nil, section will be hidden on startup @@ -767,7 +763,7 @@ (defun notmuch-hello-insert-s
[PATCH v2 1/5] emacs: hello: add helper functions for saved-searches
Add helper functions to for saved searches to ease the transition to the new plist form while maintaining backwards compatibility. They will be used in the next patch. --- emacs/notmuch-hello.el | 38 ++ 1 file changed, 38 insertions(+) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index e325cd3..f81ec27 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -269,6 +269,44 @@ (defun notmuch-hello-search (&optional search) (add-to-history 'notmuch-search-history search))) (notmuch-search search notmuch-search-oldest-first)) +(defun notmuch-saved-search-get (saved-search field) + "Get FIELD from SAVED-SEARCH. + +If SAVED-SEARCH is a plist, this is just `plist-get', but for +backwards compatibility, this also deals with the two other +possible formats for SAVED-SEARCH: cons cells (NAME . QUERY) and +lists (NAME QUERY COUNT-QUERY)." + (cond + ((keywordp (car saved-search)) +(plist-get saved-search field)) + ;; It is not a plist so it is an old-style entry. + ((consp (cdr saved-search)) ;; It is a list (NAME QUERY COUNT-QUERY) +(case field + (:name (first saved-search)) + (:query (second saved-search)) + (:count-query (third saved-search)) + (t nil))) + (t ;; It is a cons-cell (NAME . QUERY) +(case field + (:name (car saved-search)) + (:query (cdr saved-search)) + (t nil) + +(defun notmuch-hello-saved-search-to-plist (saved-search) + "Return a copy of SAVED-SEARCH in plist form. + +If saved search is a plist then just return a copy. In other +cases, for backwards compatability, convert to plist form and +return that." + (if (keywordp (car saved-search)) + (copy-seq saved-search) +(let ((fields (list :name :query :count-query)) + plist-search) + (dolist (field fields plist-search) + (let ((string (notmuch-saved-search-get saved-search field))) + (when string + (setq plist-search (append plist-search (list field string) + (defun notmuch-hello-add-saved-search (widget) (interactive) (let ((search (widget-value -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 3/5] emacs: hello: add a customize for saved-searches
Make the defcustom for notmuch-saved-searches use the new plist format. It should still work with oldstyle saved-searches but will write the newstyle form. --- emacs/notmuch-hello.el |2 +- emacs/notmuch-lib.el | 46 ++ 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 568ae47..30f26db 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -323,7 +323,7 @@ (defun notmuch-hello-add-saved-search (widget) ;; Add the new one. (customize-save-variable 'notmuch-saved-searches (add-to-list 'notmuch-saved-searches - (cons name search) t)) + (list :name name :query search) t)) (message "Saved '%s' as '%s'." search name) (notmuch-hello-update))) diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 959764e..a54a055 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -107,10 +107,48 @@ (defcustom notmuch-poll-script nil (defvar notmuch-search-history nil "Variable to store notmuch searches history.") -(defcustom notmuch-saved-searches '(("inbox" . "tag:inbox") - ("unread" . "tag:unread")) - "A list of saved searches to display." - :type '(alist :key-type string :value-type string) +(defun notmuch--saved-searches-to-plist (symbol) + "Extract a saved-search variable into plist form. + +The new style saved search is just a plist, but for backwards +compatatibility we use this function to extract old style saved +searches so they still work in customize." + (let ((saved-searches (default-value symbol))) +(mapcar #'notmuch-hello-saved-search-to-plist saved-searches))) + +(define-widget 'notmuch-saved-search-plist 'list + "A single saved search property list." + :tag "Saved Search" + :args '((list :inline t + :format "%v" + (group :format "%v" :inline t (const :format " Name: " :name) (string :format "%v")) + (group :format "%v" :inline t (const :format " Query: " :query) (string :format "%v"))) + (checklist :inline t +:format "%v" +(group :format "%v" :inline t (const :format "Count-Query: " :count-query) (string :format "%v") + +(defcustom notmuch-saved-searches '((:name "inbox" :query "tag:inbox") + (:name "unread" :query "tag:unread")) + "A list of saved searches to display. + +The saved search can be given in 3 forms. The preferred way is as +a plist. Supported properties are + + :nameName of the search (required). + :query Search to run (required). + :count-query Optional extra query to generate the count + shown. If not present then the :query property + is used. + +Other accepted forms are a cons cell of the form (NAME . QUERY) +or a list of the form (NAME QUERY COUNT-QUERY)." +;; The saved-search format is also used by the all-tags notmuch-hello +;; section. This section generates its own saved-search list in one of +;; the latter two forms. + + :get 'notmuch--saved-searches-to-plist + :type '(repeat notmuch-saved-search-plist) + :tag "List of Saved Searches" :group 'notmuch-hello) (defcustom notmuch-archive-tags '("-inbox") -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 0/5] emacs: hello: convert saved-searches to plists
This is v2 of the series; v1 is at id:1396733065-32602-1-git-send-email-markwalters1...@gmail.com I have made all the changes suggested by Austin in his review of v1. I include the diff from v1 below. There is now one slight oddity in the patch ordering: the documentation for the plist form appears in patch 3 while the users and references to that documentation appear in patch 2. Best wishes Mark Mark Walters (5): emacs: hello: add helper functions for saved-searches emacs: hello: use the saved-search helper functions emacs: hello: add a customize for saved-searches emacs: hello: switch notmuch-hello-insert-buttons to plists emacs: Add a sort-order option to saved-searches emacs/notmuch-hello.el | 127 emacs/notmuch-lib.el | 54 ++-- emacs/notmuch.el |6 +-- 3 files changed, 139 insertions(+), 48 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 6a28372..f0675f2 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -272,17 +272,17 @@ (defun notmuch-hello-search (&optional search) (defun notmuch-saved-search-get (saved-search field) "Get FIELD from SAVED-SEARCH. -In the new style saved-search (a plist) this is just plist-get -but, for backwards compatibility, this deals with the two -old-style forms: cons cells (NAME . QUERY) and lists (NAME QUERY -COUNT-QUERY)." +If SAVED-SEARCH is a plist, this is just `plist-get', but for +backwards compatibility, this also deals with the two other +possible formats for SAVED-SEARCH: cons cells (NAME . QUERY) and +lists (NAME QUERY COUNT-QUERY)." (cond - ((plist-get saved-search :name) + ((keywordp (car saved-search)) (plist-get saved-search field)) ;; It is not a plist so it is an old-style entry. ((consp (cdr saved-search)) ;; It is a list (NAME QUERY COUNT-QUERY) (case field - (:name (car saved-search)) + (:name (first saved-search)) (:query (second saved-search)) (:count-query (third saved-search)) (t nil))) @@ -293,16 +293,15 @@ (defun notmuch-saved-search-get (saved-search field) (t nil) (defun notmuch-hello-saved-search-to-plist (saved-search) - "Convert a saved-search variable into plist form. + "Return a copy of SAVED-SEARCH in plist form. -The new style saved search is just a plist, but for backwards -compatatibility we use this function to give them in -plist-form. In all cases a new copy is returned so it is safe to -modify the returned value." - (if (and (listp (cdr saved-search)) (plist-member saved-search :name)) +If saved search is a plist then just return a copy. In other +cases, for backwards compatability, convert to plist form and +return that." + (if (keywordp (car saved-search)) (copy-seq saved-search) (let ((fields (list :name :query :count-query)) - (plist-search)) + plist-search) (dolist (field fields plist-search) (let ((string (notmuch-saved-search-get saved-search field))) (when string @@ -424,11 +423,11 @@ (defun notmuch-hello-query-counts (query-list &rest options) QUERY-LIST must be a list of saved-searches. Ideally each of these is a plist but other options are available for backwards -compatibility: see notmuch-saved-search-get for details. +compatibility: see `notmuch-saved-searches' for details. The result is a list of plists each of which includes the -pairs :name NAME, :query QUERY and :count COUNT, together with -any pairs in the original saved-search. +properties :name NAME, :query QUERY and :count COUNT, together +with any properties in the original saved-search. The values :show-empty-searches, :filter and :filter-count from options will be handled as specified for @@ -464,20 +463,20 @@ (defun notmuch-hello-query-counts (query-list &rest options) search-query (plist-get options :filter))) (message-count (prog1 (read (current-buffer)) (forward-line 1 - (and (or (plist-get options :show-empty-searches) (> message-count 0)) - (setq elem-plist (plist-put elem-plist :query filtered-query)) - (plist-put elem-plist :count message-count + (when (and filtered-query (or (plist-get options :show-empty-searches) (> message-count 0))) + (setq elem-plist (plist-put elem-plist :query filtered-query)) + (plist-put elem-plist :count message-count query-list (defun notmuch-hello-insert-buttons (searches) "Insert buttons for SEARCHES. SEARCHES must be a list of plists each of which should contain at -least pairs for :name NAME :query QUERY and :count COUNT, where -QUERY is the query to start when the button for the corresponding -entry is activated, and COUNT should be the number of messages -matching the query. Such a plist can be computed with -`notmuch-hello-query-counts'." +least the prop
Re: [PATCH 0/5] emacs: hello: convert saved-searches to plists
On Sun, 06 Apr 2014, David Bremner wrote: > Mark Walters writes: > >> This series converts the saved-search format to plists. This should >> make it much easier to extend their functionality. The final patch >> illustrates this by adding a sort-order option to the saved >> searches. It also exposes the count-query functionality that is >> already present internally, and could be used to store keyboard >> shortcuts for searches. > > Not necessarily an issue for this series, but I'd like start thinking > about a front-end-independent representation for saved searches; perhaps > json for want of better ideas. Yes that sounds good. I think it would be natural to parse the JSON (or sexp if we allow both formats) into a plist for the saved search so that could fit in quite neatly. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 5/5] emacs: Add a sort-order option to saved-searches
Hi On Sun, 06 Apr 2014, Austin Clements wrote: > Quoth Mark Walters on Apr 05 at 10:24 pm: >> This adds a sort-order option to saved-searches, stores it in the >> saved-search buttons (widgets), and uses the stored value when the >> button is pressed. >> >> Storing the sort-order in the widget was suggested by Jani in >> id:4c3876274126985683e888641b29cf18142a5eb8.1391771337.git.j...@nikula.org. >> --- >> emacs/notmuch-hello.el | 11 ++- >> emacs/notmuch-lib.el |7 ++- >> 2 files changed, 16 insertions(+), 2 deletions(-) >> >> diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el >> index aa40e6f..6a28372 100644 >> --- a/emacs/notmuch-hello.el >> +++ b/emacs/notmuch-hello.el >> @@ -364,7 +364,8 @@ (defun notmuch-hello-reflect (list ncols) >> (defun notmuch-hello-widget-search (widget &rest ignore) >>(notmuch-search (widget-get widget >>:notmuch-search-terms) >> - notmuch-search-oldest-first)) >> + (widget-get widget >> + :notmuch-search-oldest-first))) >> >> (defun notmuch-saved-search-count (search) >>(car (process-lines notmuch-command "count" search))) >> @@ -496,12 +497,20 @@ (defun notmuch-hello-insert-buttons (searches) >>(widget-insert (make-string column-indent ? ))) >>(let* ((name (plist-get elem :name)) >> (query (plist-get elem :query)) >> + (oldest-first (cond >> +((eq (plist-get elem :sort-order) >> 'newest-first) >> + nil) >> +((eq (plist-get elem :sort-order) >> 'oldest-first) >> + t) >> +(t >> + notmuch-search-oldest-first))) > > (case (plist-get elem :sort-order) > (newest-first nil) > (oldest-first t) > (otherwise notmuch-search-oldest-first)) This is much better. > >> (msg-count (plist-get elem :count))) >> (widget-insert (format "%8s " >> (notmuch-hello-nice-number msg-count))) >> (widget-create 'push-button >> :notify #'notmuch-hello-widget-search >> :notmuch-search-terms query >> + :notmuch-search-oldest-first oldest-first >> name) >> (setq column-indent >>(1+ (max 0 (- column-width (length name))) >> diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el >> index 8a12f91..8aa8cfc 100644 >> --- a/emacs/notmuch-lib.el >> +++ b/emacs/notmuch-lib.el >> @@ -125,7 +125,12 @@ (define-widget 'notmuch-saved-search-plist 'list >> (group :format "%v" :inline t (const :format " Query: " >> :query) (string :format "%v"))) >>(checklist :inline t >> :format "%v" >> - (group :format "%v" :inline t (const :format "Count-Query: >> " :count-query) (string :format "%v") >> + (group :format "%v" :inline t (const :format "Count-Query: >> " :count-query) (string :format "%v")) >> + (group :format "%v" :inline t (const :format "" >> :sort-order) >> +(choice :tag " Sort Order" > > Should there be a colon? (I haven't applied the patches and I'm > afraid this is beyond my mental implementation of define-widget!) I think it is OK without: since this is using :tag rather than :format the colon is supplied automatically. Many thanks Mark > >> +(const :tag "Default" nil) >> +(const :tag "Oldest-first" oldest-first) >> +(const :tag "Newest-first" >> newest-first)) >> >> (defcustom notmuch-saved-searches '((:name "inbox" :query "tag:inbox") >> (:name "unread" :query "tag:unread")) ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 4/5] emacs: hello: switch notmuch-hello-insert-buttons to plists
Hello >> @@ -455,23 +457,26 @@ (defun notmuch-hello-query-counts (query-list &rest >> options) >> #'identity >> (mapcar >>(lambda (elem) >> -(let ((name (notmuch-saved-search-get elem :name)) >> - (search-query (notmuch-saved-search-get elem :query)) >> - (message-count (prog1 (read (current-buffer)) >> +(let* ((elem-plist (notmuch-hello-saved-search-to-plist elem)) >> + (search-query (plist-get elem-plist :query)) >> + (filtered-query (notmuch-hello-filtered-query >> +search-query (plist-get options :filter))) >> + (message-count (prog1 (read (current-buffer)) >> (forward-line 1 >>(and (or (plist-get options :show-empty-searches) (> message-count 0)) >> - (list name (notmuch-hello-filtered-query >> - search-query (plist-get options :filter)) >> - message-count >> + (setq elem-plist (plist-put elem-plist :query filtered-query)) > > This technically works, but `setq' is a strange thing to see in an > `and'. But the problem isn't the `setq'; it's that crazy `and'. I'd > replace the `and' with `when', keep the `setq' and `plist-put' in the > body, and squint a lot less at this code. This was actually a bug on my part: the filtered query can be nil (which is used to mean hide this search); in earlier versions having a setq inside the `and' achieved this but obviously not in this plist form. I have switched to the when as suggested and added a test for filtered-query being nil. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 5/5] emacs: Add a sort-order option to saved-searches
This adds a sort-order option to saved-searches, stores it in the saved-search buttons (widgets), and uses the stored value when the button is pressed. Storing the sort-order in the widget was suggested by Jani in id:4c3876274126985683e888641b29cf18142a5eb8.1391771337.git.jani at nikula.org. --- emacs/notmuch-hello.el | 11 ++- emacs/notmuch-lib.el |7 ++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index aa40e6f..6a28372 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -364,7 +364,8 @@ (defun notmuch-hello-reflect (list ncols) (defun notmuch-hello-widget-search (widget &rest ignore) (notmuch-search (widget-get widget :notmuch-search-terms) - notmuch-search-oldest-first)) + (widget-get widget + :notmuch-search-oldest-first))) (defun notmuch-saved-search-count (search) (car (process-lines notmuch-command "count" search))) @@ -496,12 +497,20 @@ (defun notmuch-hello-insert-buttons (searches) (widget-insert (make-string column-indent ? ))) (let* ((name (plist-get elem :name)) (query (plist-get elem :query)) +(oldest-first (cond + ((eq (plist-get elem :sort-order) 'newest-first) +nil) + ((eq (plist-get elem :sort-order) 'oldest-first) +t) + (t +notmuch-search-oldest-first))) (msg-count (plist-get elem :count))) (widget-insert (format "%8s " (notmuch-hello-nice-number msg-count))) (widget-create 'push-button :notify #'notmuch-hello-widget-search :notmuch-search-terms query + :notmuch-search-oldest-first oldest-first name) (setq column-indent (1+ (max 0 (- column-width (length name))) diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 8a12f91..8aa8cfc 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -125,7 +125,12 @@ (define-widget 'notmuch-saved-search-plist 'list (group :format "%v" :inline t (const :format " Query: " :query) (string :format "%v"))) (checklist :inline t :format "%v" -(group :format "%v" :inline t (const :format "Count-Query: " :count-query) (string :format "%v") +(group :format "%v" :inline t (const :format "Count-Query: " :count-query) (string :format "%v")) +(group :format "%v" :inline t (const :format "" :sort-order) + (choice :tag " Sort Order" + (const :tag "Default" nil) + (const :tag "Oldest-first" oldest-first) + (const :tag "Newest-first" newest-first)) (defcustom notmuch-saved-searches '((:name "inbox" :query "tag:inbox") (:name "unread" :query "tag:unread")) -- 1.7.10.4
[PATCH 4/5] emacs: hello: switch notmuch-hello-insert-buttons to plists
Switching notmuch-hello-insert-buttons to plists means we can easily pass extra options through to the buttons. --- emacs/notmuch-hello.el | 33 +++-- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index c729af2..aa40e6f 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -425,7 +425,9 @@ (defun notmuch-hello-query-counts (query-list &rest options) these is a plist but other options are available for backwards compatibility: see notmuch-saved-search-get for details. -The result is the list of elements of the form (NAME QUERY COUNT). +The result is a list of plists each of which includes the +pairs :name NAME, :query QUERY and :count COUNT, together with +any pairs in the original saved-search. The values :show-empty-searches, :filter and :filter-count from options will be handled as specified for @@ -455,23 +457,26 @@ (defun notmuch-hello-query-counts (query-list &rest options) #'identity (mapcar (lambda (elem) - (let ((name (notmuch-saved-search-get elem :name)) - (search-query (notmuch-saved-search-get elem :query)) - (message-count (prog1 (read (current-buffer)) + (let* ((elem-plist (notmuch-hello-saved-search-to-plist elem)) + (search-query (plist-get elem-plist :query)) + (filtered-query (notmuch-hello-filtered-query + search-query (plist-get options :filter))) + (message-count (prog1 (read (current-buffer)) (forward-line 1 (and (or (plist-get options :show-empty-searches) (> message-count 0)) - (list name (notmuch-hello-filtered-query - search-query (plist-get options :filter)) -message-count + (setq elem-plist (plist-put elem-plist :query filtered-query)) + (plist-put elem-plist :count message-count query-list (defun notmuch-hello-insert-buttons (searches) "Insert buttons for SEARCHES. -SEARCHES must be a list containing lists of the form (NAME QUERY COUNT), where -QUERY is the query to start when the button for the corresponding entry is -activated. COUNT should be the number of messages matching the query. -Such a list can be computed with `notmuch-hello-query-counts'." +SEARCHES must be a list of plists each of which should contain at +least pairs for :name NAME :query QUERY and :count COUNT, where +QUERY is the query to start when the button for the corresponding +entry is activated, and COUNT should be the number of messages +matching the query. Such a plist can be computed with +`notmuch-hello-query-counts'." (let* ((widest (notmuch-hello-longest-label searches)) (tags-and-width (notmuch-hello-tags-per-line widest)) (tags-per-line (car tags-and-width)) @@ -489,9 +494,9 @@ (defun notmuch-hello-insert-buttons (searches) (when elem (if (> column-indent 0) (widget-insert (make-string column-indent ? ))) - (let* ((name (first elem)) -(query (second elem)) -(msg-count (third elem))) + (let* ((name (plist-get elem :name)) +(query (plist-get elem :query)) +(msg-count (plist-get elem :count))) (widget-insert (format "%8s " (notmuch-hello-nice-number msg-count))) (widget-create 'push-button -- 1.7.10.4
[PATCH 3/5] emacs: hello: add a customize for saved-searches
Make the defcustom for notmuch-saved-searches use the new plist format. It should still work with oldstyle saved-searches but will write the newstyle form. --- emacs/notmuch-hello.el |2 +- emacs/notmuch-lib.el | 28 +--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 733208b..c729af2 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -324,7 +324,7 @@ (defun notmuch-hello-add-saved-search (widget) ;; Add the new one. (customize-save-variable 'notmuch-saved-searches (add-to-list 'notmuch-saved-searches - (cons name search) t)) + (list :name name :query search) t)) (message "Saved '%s' as '%s'." search name) (notmuch-hello-update))) diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 959764e..8a12f91 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -107,10 +107,32 @@ (defcustom notmuch-poll-script nil (defvar notmuch-search-history nil "Variable to store notmuch searches history.") -(defcustom notmuch-saved-searches '(("inbox" . "tag:inbox") - ("unread" . "tag:unread")) +(defun notmuch--saved-searches-to-plist (symbol) + "Extract a saved-search variable into plist form. + +The new style saved search is just a plist, but for backwards +compatatibility we use this function to extract old style saved +searches so they still work in customize." + (let ((saved-searches (default-value symbol))) +(mapcar #'notmuch-hello-saved-search-to-plist saved-searches))) + +(define-widget 'notmuch-saved-search-plist 'list + "A single saved search property list." + :tag "Saved Search" + :args '((list :inline t + :format "%v" + (group :format "%v" :inline t (const :format " Name: " :name) (string :format "%v")) + (group :format "%v" :inline t (const :format " Query: " :query) (string :format "%v"))) + (checklist :inline t +:format "%v" +(group :format "%v" :inline t (const :format "Count-Query: " :count-query) (string :format "%v") + +(defcustom notmuch-saved-searches '((:name "inbox" :query "tag:inbox") + (:name "unread" :query "tag:unread")) "A list of saved searches to display." - :type '(alist :key-type string :value-type string) + :get 'notmuch--saved-searches-to-plist + :type '(repeat notmuch-saved-search-plist) + :tag "List of Saved Searches" :group 'notmuch-hello) (defcustom notmuch-archive-tags '("-inbox") -- 1.7.10.4
[PATCH 2/5] emacs: hello: use the saved-search helper functions
This uses the helper functions: the saved searches format has not changed yet but backwards compatibility means everything still works. --- emacs/notmuch-hello.el | 48 ++-- emacs/notmuch.el |6 +++--- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 0b9ed16..733208b 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -319,7 +319,7 @@ (defun notmuch-hello-add-saved-search (widget) (setq notmuch-saved-searches (loop for elem in notmuch-saved-searches if (not (equal name - (car elem))) + (notmuch-saved-search-get elem :name))) collect elem)) ;; Add the new one. (customize-save-variable 'notmuch-saved-searches @@ -339,7 +339,7 @@ (defun notmuch-hello-delete-search-from-history (widget) (defun notmuch-hello-longest-label (searches-alist) (or (loop for elem in searches-alist - maximize (length (car elem))) + maximize (length (notmuch-saved-search-get elem :name))) 0)) (defun notmuch-hello-reflect-generate-row (ncols nrows row list) @@ -418,13 +418,12 @@ (defun notmuch-hello-filtered-query (query filter) (concat "(" query ") and (" filter ")")) (t query))) -(defun notmuch-hello-query-counts (query-alist &rest options) - "Compute list of counts of matched messages from QUERY-ALIST. +(defun notmuch-hello-query-counts (query-list &rest options) + "Compute list of counts of matched messages from QUERY-LIST. -QUERY-ALIST must be a list containing elements of the form (NAME . QUERY) -or (NAME QUERY COUNT-QUERY). If the latter form is used, -COUNT-QUERY specifies an alternate query to be used to generate -the count for the associated query. +QUERY-LIST must be a list of saved-searches. Ideally each of +these is a plist but other options are available for backwards +compatibility: see notmuch-saved-search-get for details. The result is the list of elements of the form (NAME QUERY COUNT). @@ -432,11 +431,9 @@ (defun notmuch-hello-query-counts (query-alist &rest options) options will be handled as specified for `notmuch-hello-insert-searches'." (with-temp-buffer -(dolist (elem query-alist nil) - (let ((count-query (if (consp (cdr elem)) -;; do we have a different query for the message count? -(third elem) - (cdr elem +(dolist (elem query-list nil) + (let ((count-query (or (notmuch-saved-search-get elem :count-query) +(notmuch-saved-search-get elem :query (insert (replace-regexp-in-string "\n" " " @@ -458,18 +455,15 @@ (defun notmuch-hello-query-counts (query-alist &rest options) #'identity (mapcar (lambda (elem) - (let ((name (car elem)) - (search-query (if (consp (cdr elem)) -;; do we have a different query for the message count? -(second elem) - (cdr elem))) + (let ((name (notmuch-saved-search-get elem :name)) + (search-query (notmuch-saved-search-get elem :query)) (message-count (prog1 (read (current-buffer)) (forward-line 1 (and (or (plist-get options :show-empty-searches) (> message-count 0)) (list name (notmuch-hello-filtered-query search-query (plist-get options :filter)) message-count - query-alist + query-list (defun notmuch-hello-insert-buttons (searches) "Insert buttons for SEARCHES. @@ -728,13 +722,15 @@ (defun notmuch-hello-insert-recent-searches () (indent-rigidly start (point) notmuch-hello-indent)) nil)) -(defun notmuch-hello-insert-searches (title query-alist &rest options) - "Insert a section with TITLE showing a list of buttons made from QUERY-ALIST. +(defun notmuch-hello-insert-searches (title query-list &rest options) + "Insert a section with TITLE showing a list of buttons made from QUERY-LIST. -QUERY-ALIST must be a list containing elements of the form (NAME . QUERY) -or (NAME QUERY COUNT-QUERY). If the latter form is used, -COUNT-QUERY specifies an alternate query to be used to generate -the count for the associated item. +QUERY-LIST should ideally be a plist but for backwards +compatibility other forms are also accepted (see +`notmuch-saved-search-get' for details). The plist should +contain keys :name and :query; if :count-query is also present +then it specifies an alternate query to be used to generate the +count for the associated search. Supports the following entries in OPTIONS as a plist: :initially-hidden - if non-nil, section will be hidden on startup @@ -768,7 +764,7 @@ (defun notmuch-hello-insert-searches
[PATCH 1/5] emacs: hello: add helper functions for saved-searches
Add helper functions to for saved searches to ease the transition to the new plist form while maintaining backwards compatibility. They will be used in the next patch. --- emacs/notmuch-hello.el | 39 +++ 1 file changed, 39 insertions(+) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index e325cd3..0b9ed16 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -269,6 +269,45 @@ (defun notmuch-hello-search (&optional search) (add-to-history 'notmuch-search-history search))) (notmuch-search search notmuch-search-oldest-first)) +(defun notmuch-saved-search-get (saved-search field) + "Get FIELD from SAVED-SEARCH. + +In the new style saved-search (a plist) this is just plist-get +but, for backwards compatibility, this deals with the two +old-style forms: cons cells (NAME . QUERY) and lists (NAME QUERY +COUNT-QUERY)." + (cond + ((plist-get saved-search :name) +(plist-get saved-search field)) + ;; It is not a plist so it is an old-style entry. + ((consp (cdr saved-search)) ;; It is a list (NAME QUERY COUNT-QUERY) +(case field + (:name (car saved-search)) + (:query (second saved-search)) + (:count-query (third saved-search)) + (t nil))) + (t ;; It is a cons-cell (NAME . QUERY) +(case field + (:name (car saved-search)) + (:query (cdr saved-search)) + (t nil) + +(defun notmuch-hello-saved-search-to-plist (saved-search) + "Convert a saved-search variable into plist form. + +The new style saved search is just a plist, but for backwards +compatatibility we use this function to give them in +plist-form. In all cases a new copy is returned so it is safe to +modify the returned value." + (if (and (listp (cdr saved-search)) (plist-member saved-search :name)) + (copy-seq saved-search) +(let ((fields (list :name :query :count-query)) + (plist-search)) + (dolist (field fields plist-search) + (let ((string (notmuch-saved-search-get saved-search field))) + (when string + (setq plist-search (append plist-search (list field string) + (defun notmuch-hello-add-saved-search (widget) (interactive) (let ((search (widget-value -- 1.7.10.4
[PATCH 0/5] emacs: hello: convert saved-searches to plists
This series converts the saved-search format to plists. This should make it much easier to extend their functionality. The final patch illustrates this by adding a sort-order option to the saved searches. It also exposes the count-query functionality that is already present internally, and could be used to store keyboard shortcuts for searches. The series tries hard to be backwardly compatible and seems to work in most cases. However, notmuch-hello is very interconnected so some corner cases may fail: for example if people are doing strange things with notmuch-saved-search-sort-function then it may break. Also note that the functions used for saved-searches are also used for the "all tags" section: I have not converted them as they are purely internal. Since we have backwards compatibility they still work. Best wishes Mark Mark Walters (5): emacs: hello: add helper functions for saved-searches emacs: hello: use the saved-search helper functions emacs: hello: add a customize for saved-searches emacs: hello: switch notmuch-hello-insert-buttons to plists emacs: Add a sort-order option to saved-searches emacs/notmuch-hello.el | 129 +--- emacs/notmuch-lib.el | 33 +++-- emacs/notmuch.el |6 +-- 3 files changed, 122 insertions(+), 46 deletions(-) -- 1.7.10.4
[PATCH 5/7] doc: Allow rst2man.py as an alternative to rst2man
On Sat, Apr 05 2014, "W. Trevor King" wrote: > Gentoo's dev-python/docutils-0.10 installs Docutils scripts with a > *.py extension, so I have /usr/bin/rst2man.py and no rst2man script. > This patch supports users with both types of systems by checking for > rst2man, falling back on rst2man.py, and giving up only if neither is > found. Users can also set the new RST2MAN path variable explicitly > when they call Make: > > make RST2MAN=/my/custom/rst_to_man_converter build-man > > I use POSIX's 'command -v' [1] to find the path to rst2man or > rst2man.py, and save that as RST2MAN in Makefile.config. We can use a > non-empty RST2MAN to check for the availability of an rst2man program, > so there's no need for a separate HAVE_RST2MAN. Then pass the > configured RST2MAN path through to prerst2man.py to use in its system > call. > > [1]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/command.html This series looks good to me. Except the reference to _POSIX_ page. One knows how consistent these specifications are; alternative: http://pubs.opengroup.org/onlinepubs/009695399/utilities/command.html mentions additionally that -v flag "(On systems supporting the User Portability Utilities option.)" Also, we don't give such a treatment to other command either; I'd rather see RST2MAN=rst2man, RST2MAN=rst2man.py *and* RST2MAN= lines used instead -- the last to set RST2MAN to empty string instead of being unset. Tomi > --- > configure | 12 +++- > doc/Makefile.local | 6 +++--- > doc/prerst2man.py | 9 + > 3 files changed, 15 insertions(+), 12 deletions(-) > > diff --git a/configure b/configure > index 1d430b9..81c286b 100755 > --- a/configure > +++ b/configure > @@ -400,7 +400,6 @@ printf "Checking if sphinx is available and supports > nroff output... " > if hash sphinx-build > /dev/null 2>&1 && python -m sphinx.writers.manpage > > /dev/null 2>&1 ; then > printf "Yes.\n" > have_sphinx=1 > -have_rst2man=0 > else > printf "No (falling back to rst2man).\n" > have_sphinx=0 > @@ -408,10 +407,12 @@ else > printf "Checking if rst2man is available... " > if rst2man -V > /dev/null 2>&1; then > printf "Yes.\n" > - have_rst2man=1 > + RST2MAN=$(command -v rst2man) > +elif rst2man.py -V > /dev/null 2>&1; then > + printf "Yes.\n" > + RST2MAN=$(command -v rst2man.py) > else > printf "No (so will not install man pages).\n" > - have_rst2man=0 > fi > fi > > @@ -788,8 +789,9 @@ HAVE_EMACS = ${have_emacs} > # Whether there's a sphinx-build binary available for building documentation > HAVE_SPHINX=${have_sphinx} > > -# Whether there's a rst2man binary available for building documentation > -HAVE_RST2MAN=${have_rst2man} > +# The path to the rst2man program for building documentation. Set to > +# an empty string if no such program is available. > +RST2MAN=${RST2MAN} > > # The directory to which desktop files should be installed > desktop_dir = \$(prefix)/share/applications > diff --git a/doc/Makefile.local b/doc/Makefile.local > index 0980c71..e08fc99 100644 > --- a/doc/Makefile.local > +++ b/doc/Makefile.local > @@ -42,8 +42,8 @@ ifeq ($(HAVE_SPHINX),1) > mkdir -p $(DOCBUILDDIR)/man/man$${section}; \ > mv $(DOCBUILDDIR)/man/*.$${section} > $(DOCBUILDDIR)/man/man$${section}; \ > done > -else ifeq ($(HAVE_RST2MAN),1) > - $(prerst2man) $(srcdir)/doc $(DOCBUILDDIR)/man > +else ifdef RST2MAN > + $(prerst2man) "$(RST2MAN)" $(srcdir)/doc $(DOCBUILDDIR)/man > else > @echo "Fatal: build dependency fail." > @false > @@ -51,7 +51,7 @@ endif > > # Do not try to build or install man pages if a man page converter is > # not available. > -ifeq ($(HAVE_SPHINX)$(HAVE_RST2MAN),00) > +ifeq ($(HAVE_SPHINX)$(RST2MAN),0) > build-man: > install-man: > @echo "No sphinx or rst2man, will not install man pages." > diff --git a/doc/prerst2man.py b/doc/prerst2man.py > index 437dea9..81ce817 100644 > --- a/doc/prerst2man.py > +++ b/doc/prerst2man.py > @@ -4,8 +4,9 @@ from os.path import dirname, isdir > from os import makedirs, system > import re > > -sourcedir = argv[1] > -outdir = argv[2] > +rst2man = argv[1] > +sourcedir = argv[2] > +outdir = argv[3] > > if not isdir(outdir): > makedirs(outdir, 0o755) > @@ -59,5 +60,5 @@ for page in man_pages: > outfile.write("".join(lines)) > outfile.close() > > -system('set -x; rst2man {0} {1}/{2}.{3}' > - .format(filename, outdir, page[0], page[4])) > +system('set -x; {0} {1} {2}/{3}.{4}' > + .format(rst2man, filename, outdir, page[0], page[4])) > -- > 1.9.1.353.gc66d89d > > ___ > notmuch mailing list > notmuch at notmuchmail.org > http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 0/5] emacs: hello: convert saved-searches to plists
Mark Walters writes: > This series converts the saved-search format to plists. This should > make it much easier to extend their functionality. The final patch > illustrates this by adding a sort-order option to the saved > searches. It also exposes the count-query functionality that is > already present internally, and could be used to store keyboard > shortcuts for searches. Not necessarily an issue for this series, but I'd like start thinking about a front-end-independent representation for saved searches; perhaps json for want of better ideas. d
[PATCH 5/5] emacs: Add a sort-order option to saved-searches
Quoth Mark Walters on Apr 05 at 10:24 pm: > This adds a sort-order option to saved-searches, stores it in the > saved-search buttons (widgets), and uses the stored value when the > button is pressed. > > Storing the sort-order in the widget was suggested by Jani in > id:4c3876274126985683e888641b29cf18142a5eb8.1391771337.git.jani at nikula.org. > --- > emacs/notmuch-hello.el | 11 ++- > emacs/notmuch-lib.el |7 ++- > 2 files changed, 16 insertions(+), 2 deletions(-) > > diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el > index aa40e6f..6a28372 100644 > --- a/emacs/notmuch-hello.el > +++ b/emacs/notmuch-hello.el > @@ -364,7 +364,8 @@ (defun notmuch-hello-reflect (list ncols) > (defun notmuch-hello-widget-search (widget &rest ignore) >(notmuch-search (widget-get widget > :notmuch-search-terms) > - notmuch-search-oldest-first)) > + (widget-get widget > + :notmuch-search-oldest-first))) > > (defun notmuch-saved-search-count (search) >(car (process-lines notmuch-command "count" search))) > @@ -496,12 +497,20 @@ (defun notmuch-hello-insert-buttons (searches) > (widget-insert (make-string column-indent ? ))) > (let* ((name (plist-get elem :name)) >(query (plist-get elem :query)) > + (oldest-first (cond > + ((eq (plist-get elem :sort-order) > 'newest-first) > + nil) > + ((eq (plist-get elem :sort-order) > 'oldest-first) > + t) > + (t > + notmuch-search-oldest-first))) (case (plist-get elem :sort-order) (newest-first nil) (oldest-first t) (otherwise notmuch-search-oldest-first)) >(msg-count (plist-get elem :count))) > (widget-insert (format "%8s " > (notmuch-hello-nice-number msg-count))) > (widget-create 'push-button > :notify #'notmuch-hello-widget-search > :notmuch-search-terms query > +:notmuch-search-oldest-first oldest-first > name) > (setq column-indent > (1+ (max 0 (- column-width (length name))) > diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el > index 8a12f91..8aa8cfc 100644 > --- a/emacs/notmuch-lib.el > +++ b/emacs/notmuch-lib.el > @@ -125,7 +125,12 @@ (define-widget 'notmuch-saved-search-plist 'list > (group :format "%v" :inline t (const :format " Query: " > :query) (string :format "%v"))) > (checklist :inline t >:format "%v" > - (group :format "%v" :inline t (const :format "Count-Query: > " :count-query) (string :format "%v") > + (group :format "%v" :inline t (const :format "Count-Query: > " :count-query) (string :format "%v")) > + (group :format "%v" :inline t (const :format "" > :sort-order) > + (choice :tag " Sort Order" Should there be a colon? (I haven't applied the patches and I'm afraid this is beyond my mental implementation of define-widget!) > + (const :tag "Default" nil) > + (const :tag "Oldest-first" oldest-first) > + (const :tag "Newest-first" > newest-first)) > > (defcustom notmuch-saved-searches '((:name "inbox" :query "tag:inbox") > (:name "unread" :query "tag:unread"))
[PATCH 4/5] emacs: hello: switch notmuch-hello-insert-buttons to plists
Quoth Mark Walters on Apr 05 at 10:24 pm: > Switching notmuch-hello-insert-buttons to plists means we can easily > pass extra options through to the buttons. > --- > emacs/notmuch-hello.el | 33 +++-- > 1 file changed, 19 insertions(+), 14 deletions(-) > > diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el > index c729af2..aa40e6f 100644 > --- a/emacs/notmuch-hello.el > +++ b/emacs/notmuch-hello.el > @@ -425,7 +425,9 @@ (defun notmuch-hello-query-counts (query-list &rest > options) > these is a plist but other options are available for backwards > compatibility: see notmuch-saved-search-get for details. > > -The result is the list of elements of the form (NAME QUERY COUNT). > +The result is a list of plists each of which includes the > +pairs :name NAME, :query QUERY and :count COUNT, together with > +any pairs in the original saved-search. "Pair" can be synonymous with "cons", which is not what you mean here. "Properties"? > > The values :show-empty-searches, :filter and :filter-count from > options will be handled as specified for > @@ -455,23 +457,26 @@ (defun notmuch-hello-query-counts (query-list &rest > options) > #'identity > (mapcar >(lambda (elem) > - (let ((name (notmuch-saved-search-get elem :name)) > - (search-query (notmuch-saved-search-get elem :query)) > - (message-count (prog1 (read (current-buffer)) > + (let* ((elem-plist (notmuch-hello-saved-search-to-plist elem)) > +(search-query (plist-get elem-plist :query)) > +(filtered-query (notmuch-hello-filtered-query > + search-query (plist-get options :filter))) > +(message-count (prog1 (read (current-buffer)) > (forward-line 1 > (and (or (plist-get options :show-empty-searches) (> message-count 0)) > -(list name (notmuch-hello-filtered-query > -search-query (plist-get options :filter)) > - message-count > +(setq elem-plist (plist-put elem-plist :query filtered-query)) This technically works, but `setq' is a strange thing to see in an `and'. But the problem isn't the `setq'; it's that crazy `and'. I'd replace the `and' with `when', keep the `setq' and `plist-put' in the body, and squint a lot less at this code. > +(plist-put elem-plist :count message-count >query-list > > (defun notmuch-hello-insert-buttons (searches) >"Insert buttons for SEARCHES. > > -SEARCHES must be a list containing lists of the form (NAME QUERY COUNT), > where > -QUERY is the query to start when the button for the corresponding entry is > -activated. COUNT should be the number of messages matching the query. > -Such a list can be computed with `notmuch-hello-query-counts'." > +SEARCHES must be a list of plists each of which should contain at > +least pairs for :name NAME :query QUERY and :count COUNT, where Same comment about "pairs". > +QUERY is the query to start when the button for the corresponding > +entry is activated, and COUNT should be the number of messages > +matching the query. Such a plist can be computed with > +`notmuch-hello-query-counts'." >(let* ((widest (notmuch-hello-longest-label searches)) >(tags-and-width (notmuch-hello-tags-per-line widest)) >(tags-per-line (car tags-and-width)) > @@ -489,9 +494,9 @@ (defun notmuch-hello-insert-buttons (searches) > (when elem > (if (> column-indent 0) > (widget-insert (make-string column-indent ? ))) > - (let* ((name (first elem)) > - (query (second elem)) > - (msg-count (third elem))) > + (let* ((name (plist-get elem :name)) > + (query (plist-get elem :query)) > + (msg-count (plist-get elem :count))) > (widget-insert (format "%8s " > (notmuch-hello-nice-number msg-count))) > (widget-create 'push-button
[PATCH 2/5] emacs: hello: use the saved-search helper functions
Quoth Mark Walters on Apr 05 at 10:24 pm: > This uses the helper functions: the saved searches format has not > changed yet but backwards compatibility means everything still works. > --- > emacs/notmuch-hello.el | 48 > ++-- > emacs/notmuch.el |6 +++--- > 2 files changed, 25 insertions(+), 29 deletions(-) > > diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el > index 0b9ed16..733208b 100644 > --- a/emacs/notmuch-hello.el > +++ b/emacs/notmuch-hello.el > @@ -319,7 +319,7 @@ (defun notmuch-hello-add-saved-search (widget) > (setq notmuch-saved-searches > (loop for elem in notmuch-saved-searches > if (not (equal name > -(car elem))) > +(notmuch-saved-search-get elem :name))) > collect elem)) > ;; Add the new one. > (customize-save-variable 'notmuch-saved-searches > @@ -339,7 +339,7 @@ (defun notmuch-hello-delete-search-from-history (widget) > > (defun notmuch-hello-longest-label (searches-alist) >(or (loop for elem in searches-alist > - maximize (length (car elem))) > + maximize (length (notmuch-saved-search-get elem :name))) >0)) > > (defun notmuch-hello-reflect-generate-row (ncols nrows row list) > @@ -418,13 +418,12 @@ (defun notmuch-hello-filtered-query (query filter) > (concat "(" query ") and (" filter ")")) > (t query))) > > -(defun notmuch-hello-query-counts (query-alist &rest options) > - "Compute list of counts of matched messages from QUERY-ALIST. > +(defun notmuch-hello-query-counts (query-list &rest options) > + "Compute list of counts of matched messages from QUERY-LIST. > > -QUERY-ALIST must be a list containing elements of the form (NAME . QUERY) > -or (NAME QUERY COUNT-QUERY). If the latter form is used, > -COUNT-QUERY specifies an alternate query to be used to generate > -the count for the associated query. > +QUERY-LIST must be a list of saved-searches. Ideally each of > +these is a plist but other options are available for backwards > +compatibility: see notmuch-saved-search-get for details. s/:/./ Also `'s around notmuch-saved-search-get. Actually, the accepted formats (including the understood keys in plist form) should be documented in `notmuch-saved-searches' and this information should be cited elsewhere and not duplicated. > > The result is the list of elements of the form (NAME QUERY COUNT). > > @@ -432,11 +431,9 @@ (defun notmuch-hello-query-counts (query-alist &rest > options) > options will be handled as specified for > `notmuch-hello-insert-searches'." >(with-temp-buffer > -(dolist (elem query-alist nil) > - (let ((count-query (if (consp (cdr elem)) > - ;; do we have a different query for the message > count? > - (third elem) > -(cdr elem > +(dolist (elem query-list nil) > + (let ((count-query (or (notmuch-saved-search-get elem :count-query) > + (notmuch-saved-search-get elem :query > (insert >(replace-regexp-in-string > "\n" " " > @@ -458,18 +455,15 @@ (defun notmuch-hello-query-counts (query-alist &rest > options) > #'identity > (mapcar >(lambda (elem) > - (let ((name (car elem)) > - (search-query (if (consp (cdr elem)) > - ;; do we have a different query for the > message count? > - (second elem) > - (cdr elem))) > + (let ((name (notmuch-saved-search-get elem :name)) > + (search-query (notmuch-saved-search-get elem :query)) > (message-count (prog1 (read (current-buffer)) > (forward-line 1 > (and (or (plist-get options :show-empty-searches) (> message-count 0)) > (list name (notmuch-hello-filtered-query > search-query (plist-get options :filter)) >message-count > - query-alist > + query-list > > (defun notmuch-hello-insert-buttons (searches) >"Insert buttons for SEARCHES. > @@ -728,13 +722,15 @@ (defun notmuch-hello-insert-recent-searches () >(indent-rigidly start (point) notmuch-hello-indent)) > nil)) > > -(defun notmuch-hello-insert-searches (title query-alist &rest options) > - "Insert a section with TITLE showing a list of buttons made from > QUERY-ALIST. > +(defun notmuch-hello-insert-searches (title query-list &rest options) > + "Insert a section with TITLE showing a list of buttons made from > QUERY-LIST. > > -QUERY-ALIST must be a list containing elements of the form (NAME . QUERY) > -or (NAME QUERY COUNT-QUERY). If the latter form is used, > -COUNT-QUERY specifies an alternate query to be used to generate > -the count for the associated item. > +QUERY-LIST should ideally be a plist but for backw
Feature suggestion. Indexing encrypted mail?
Jeremy Nickurak writes: > Off the top of my head, you could have an encrypted index too, which you > can only search while able to decrypt. Certainly another level of > complexity. > But why add so much complexity? If a user decides that either transport security is enough or additionally the hard disk is encrypted (why store an encrypted index on an encrypted hard disk?), said user could just switch on an option in the notmuch configuration that causes notmuch to ask for the password before or while indexing new messages and to add decrypted messages to the normal index as well. The level of security would be up to the user by means of said configuration option and those that want the convenience of searching encrypted messages could have it. Personally I would argue that if an attacker has the means to access the content of my hard disk either via the network or physically, there is no difference between having whole disk encryption and storing an encrypted index...
[PATCH 1/5] emacs: hello: add helper functions for saved-searches
Quoth Mark Walters on Apr 05 at 10:24 pm: > Add helper functions to for saved searches to ease the transition to > the new plist form while maintaining backwards compatibility. They > will be used in the next patch. > --- > emacs/notmuch-hello.el | 39 +++ > 1 file changed, 39 insertions(+) > > diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el > index e325cd3..0b9ed16 100644 > --- a/emacs/notmuch-hello.el > +++ b/emacs/notmuch-hello.el > @@ -269,6 +269,45 @@ (defun notmuch-hello-search (&optional search) >(add-to-history 'notmuch-search-history search))) >(notmuch-search search notmuch-search-oldest-first)) > > +(defun notmuch-saved-search-get (saved-search field) > + "Get FIELD from SAVED-SEARCH. > + > +In the new style saved-search (a plist) this is just plist-get It won't be "new style" once this has been in for a while. Perhaps "If SAVED-SEARCH is a plist, this is just `plist-get', but for backwards compatibility, ..." > +but, for backwards compatibility, this deals with the two > +old-style forms: cons cells (NAME . QUERY) and lists (NAME QUERY > +COUNT-QUERY)." > + (cond > + ((plist-get saved-search :name) Rather than depending on :name, maybe this should be a more generic plist test like (keywordp (car saved-search))? > +(plist-get saved-search field)) > + ;; It is not a plist so it is an old-style entry. > + ((consp (cdr saved-search)) ;; It is a list (NAME QUERY COUNT-QUERY) > +(case field > + (:name (car saved-search)) Use `first' for consistency with the other case cases? > + (:query (second saved-search)) > + (:count-query (third saved-search)) > + (t nil))) > + (t ;; It is a cons-cell (NAME . QUERY) > +(case field > + (:name (car saved-search)) > + (:query (cdr saved-search)) > + (t nil) > + > +(defun notmuch-hello-saved-search-to-plist (saved-search) > + "Convert a saved-search variable into plist form. This takes a value, not a variable. But it could be more succinct and more accurate: "Return a copy of SAVED-SEARCH in plist form." > + > +The new style saved search is just a plist, but for backwards Same comment about "new style". > +compatatibility we use this function to give them in > +plist-form. In all cases a new copy is returned so it is safe to Grammar error? > +modify the returned value." > + (if (and (listp (cdr saved-search)) (plist-member saved-search :name)) > + (copy-seq saved-search) > +(let ((fields (list :name :query :count-query)) > + (plist-search)) Personally I prefer to either explicitly initialize nil variables or to list them without the parenthesis at all (for some reason my brain automatically reads this as an application), but if you prefer this, that's fine, too. > + (dolist (field fields plist-search) > + (let ((string (notmuch-saved-search-get saved-search field))) > + (when string > + (setq plist-search (append plist-search (list field string) > + > (defun notmuch-hello-add-saved-search (widget) >(interactive) >(let ((search (widget-value
[PATCH v5 1/2] lib: drop support for single-message mbox files
On Sat, Apr 05 2014, David Bremner wrote: > Jani Nikula writes: > >> We've supported mbox files containing a single message for historical >> reasons, but the support has been deprecated, with a warning message >> while indexing, since Notmuch 0.15. Finally drop the support, and >> consider all mbox files non-email. > > series pushed. For now, anyone who wants to check their mail storage whether this have any effect: $ find . -type f | xargs head -1 | grep -B1 '^From ' (I got zero results :D on this machine; have to test on another...) Quickly crafted other test: regexp (and head -1) may be incomplete... $ find . -type f | xargs head -1 | grep -B1 -v -e '^[a-zA-Z_-]*:' -e '==.*==' -e '^$' The first one will find any emails that were found last time but would not be found (as emails) after e.g. dump-restore-reindex. Second one would find (some/most?) emails that weren't indexed in the first place... > d Tomi
[PATCH 7/7] doc/INSTALL: Remove rst2man reference and other updates
"W. Trevor King" writes: > {build|install}-man, which is backend (Sphinx/Docutils) agnostic > sphinx-{html|texinfo|info}, which doesn't have an install target > > Is that distinction intentional? Personally I prefer the consistency > of: > > {build|install}-{man|html|texinfo|info} > I think the sphinx- prefix is a historical accident, from when we tried to control backend with targets, so I don't really mind those switching (back?) to build- install-man is backend agnostic. Similar targets could be written for html and info, but no-one did yet. I guess we'd need variables to specify destinations. Installing info is a bit tricky because of the need to use install-info(1) to update directory files
[PATCH 1/2] doc: move doxgen config from devel/ to doc/
a first step towards actually instally the API docs --- devel/doxygen.cfg | 304 -- doc/doxygen.cfg | 304 ++ 2 files changed, 304 insertions(+), 304 deletions(-) delete mode 100644 devel/doxygen.cfg create mode 100644 doc/doxygen.cfg diff --git a/devel/doxygen.cfg b/devel/doxygen.cfg deleted file mode 100644 index 65d5fb5..000 --- a/devel/doxygen.cfg +++ /dev/null @@ -1,304 +0,0 @@ -# Doxyfile 1.8.4 - -#--- -# Project related configuration options -#--- -DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = "Notmuch 0.17" -PROJECT_NUMBER = -PROJECT_BRIEF = -PROJECT_LOGO = -OUTPUT_DIRECTORY = -CREATE_SUBDIRS = NO -OUTPUT_LANGUAGE= English -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = -ALWAYS_DETAILED_SEC= NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES= NO -STRIP_FROM_PATH= -STRIP_FROM_INC_PATH= -SHORT_NAMES= NO -JAVADOC_AUTOBRIEF = YES -QT_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -INHERIT_DOCS = YES -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 8 -ALIASES= -TCL_SUBST = -OPTIMIZE_OUTPUT_FOR_C = YES -OPTIMIZE_OUTPUT_JAVA = NO -OPTIMIZE_FOR_FORTRAN = NO -OPTIMIZE_OUTPUT_VHDL = NO -EXTENSION_MAPPING = -MARKDOWN_SUPPORT = YES -AUTOLINK_SUPPORT = YES -BUILTIN_STL_SUPPORT= NO -CPP_CLI_SUPPORT= NO -SIP_SUPPORT= NO -IDL_PROPERTY_SUPPORT = YES -DISTRIBUTE_GROUP_DOC = NO -SUBGROUPING= YES -INLINE_GROUPED_CLASSES = NO -INLINE_SIMPLE_STRUCTS = NO -TYPEDEF_HIDES_STRUCT = YES -LOOKUP_CACHE_SIZE = 0 -#--- -# Build related configuration options -#--- -EXTRACT_ALL= NO -EXTRACT_PRIVATE= NO -EXTRACT_PACKAGE= NO -EXTRACT_STATIC = NO -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -EXTRACT_ANON_NSPACES = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = NO -FORCE_LOCAL_INCLUDES = NO -INLINE_INFO= YES -SORT_MEMBER_DOCS = NO -SORT_BRIEF_DOCS= NO -SORT_MEMBERS_CTORS_1ST = NO -SORT_GROUP_NAMES = NO -SORT_BY_SCOPE_NAME = NO -STRICT_PROTO_MATCHING = NO -GENERATE_TODOLIST = NO -GENERATE_TESTLIST = NO -GENERATE_BUGLIST = NO -GENERATE_DEPRECATEDLIST= NO -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES= NO -SHOW_FILES = NO -SHOW_NAMESPACES= NO -FILE_VERSION_FILTER= -LAYOUT_FILE= -CITE_BIB_FILES = -#--- -# configuration options related to warning and progress messages -#--- -QUIET = YES -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = NO -WARN_FORMAT= "$file:$line: $text" -WARN_LOGFILE = -#--- -# configuration options related to the input files -#--- -INPUT = lib/notmuch.h -INPUT_ENCODING = UTF-8 -FILE_PATTERNS = -RECURSIVE = NO -EXCLUDE= -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXCLUDE_SYMBOLS= -EXAMPLE_PATH = -EXAMPLE_PATTERNS = -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_PATTERNS= -FILTER_SOURCE_FILES= NO -FILTER_SOURCE_PATTERNS = -USE_MDFILE_AS_MAINPAGE = -#--- -# configuration options related to source browsing -#--- -SOURCE_BROWSER = NO -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS= YES -REFERENCED_BY_RELATION = NO -REFERENCES_RELATION= NO -REFERENCES_LINK_SOURCE = YES -USE_HTAGS = NO -VERBATIM_HEADERS = NO -#--- -# configuration options related to the alphabetical class index -#--- -ALPHABETICAL_INDEX = NO -COLS_IN_ALPHA_INDEX= 5 -IGNORE_PREFIX
[PATCH 2/2] doc: build and install doxygen api docs
Add to the build-man and install-man targets. We also stop hardcoding the version information into doxygen.cfg --- doc/Makefile.local | 14 -- doc/doxygen.cfg| 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/doc/Makefile.local b/doc/Makefile.local index 0980c71..5189f97 100644 --- a/doc/Makefile.local +++ b/doc/Makefile.local @@ -12,6 +12,8 @@ mkdocdeps := python $(srcdir)/$(dir)/mkdocdeps.py # Internal variables. ALLSPHINXOPTS := -d $(DOCBUILDDIR)/doctrees $(SPHINXOPTS) $(srcdir)/$(dir) +APIMAN := $(DOCBUILDDIR)/man/man3/notmuch.3 +DOXYFILE := $(dir)/doxygen.cfg .PHONY: sphinx-html sphinx-texinfo sphinx-info @@ -31,7 +33,7 @@ sphinx-info: sphinx-texinfo -include $(dir)/docdeps.mk -MAN_GZIP_FILES := $(addsuffix .gz,${MAN_ROFF_FILES}) +MAN_GZIP_FILES := $(addsuffix .gz,${MAN_ROFF_FILES} ${APIMAN}) # Use the man page converter that is available. We should never depend # on MAN_ROFF_FILES if a converter is not available. @@ -59,16 +61,24 @@ else build-man: ${MAN_GZIP_FILES} install-man: ${MAN_GZIP_FILES} mkdir -p "$(DESTDIR)$(mandir)/man1" + mkdir -p "$(DESTDIR)$(mandir)/man3" mkdir -p "$(DESTDIR)$(mandir)/man5" mkdir -p "$(DESTDIR)$(mandir)/man7" install -m0644 $(DOCBUILDDIR)/man/man1/*.1.gz $(DESTDIR)/$(mandir)/man1 + install -m0644 $(DOCBUILDDIR)/man/man3/*.3.gz $(DESTDIR)/$(mandir)/man3 install -m0644 $(DOCBUILDDIR)/man/man5/*.5.gz $(DESTDIR)/$(mandir)/man5 install -m0644 $(DOCBUILDDIR)/man/man7/*.7.gz $(DESTDIR)/$(mandir)/man7 cd $(DESTDIR)/$(mandir)/man1 && ln -sf notmuch.1.gz notmuch-setup.1.gz endif +$(APIMAN): $(dir)/version.dox $(dir)/doxygen.cfg $(srcdir)/lib/notmuch.h + doxygen $(DOXYFILE) + +$(dir)/version.dox: $(srcdir)/version + sed -e 's/^/PROJECT_NAME = \"Notmuch /' -e 's/$$/\"/' < $< > $@ + $(dir)/docdeps.mk: $(dir)/conf.py $(dir)/mkdocdeps.py $(mkdocdeps) $(srcdir)/doc $(DOCBUILDDIR) $@ CLEAN := $(CLEAN) $(DOCBUILDDIR) $(dir)/docdeps.mk $(dir)/man.stamp -CLEAN := $(CLEAN) $(MAN_GZIP_FILES) $(MAN_ROFF_FILES) +CLEAN := $(CLEAN) $(MAN_GZIP_FILES) $(MAN_ROFF_FILES) $(dir)/version.dox diff --git a/doc/doxygen.cfg b/doc/doxygen.cfg index 65d5fb5..bf9f075 100644 --- a/doc/doxygen.cfg +++ b/doc/doxygen.cfg @@ -4,11 +4,11 @@ # Project related configuration options #--- DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = "Notmuch 0.17" +@INCLUDE = "doc/version.dox" PROJECT_NUMBER = PROJECT_BRIEF = PROJECT_LOGO = -OUTPUT_DIRECTORY = +OUTPUT_DIRECTORY = doc/_build CREATE_SUBDIRS = NO OUTPUT_LANGUAGE= English BRIEF_MEMBER_DESC = YES -- 1.9.0 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
build and install doxygen api docs
I'm not sure if we really want to install the API docs yet, but I was reviewing Tomi's patch and it occured to me that this was one more place where we could stop hardcoding the version number. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 0/5] emacs: hello: convert saved-searches to plists
Mark Walters writes: > This series converts the saved-search format to plists. This should > make it much easier to extend their functionality. The final patch > illustrates this by adding a sort-order option to the saved > searches. It also exposes the count-query functionality that is > already present internally, and could be used to store keyboard > shortcuts for searches. Not necessarily an issue for this series, but I'd like start thinking about a front-end-independent representation for saved searches; perhaps json for want of better ideas. d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Feature suggestion. Indexing encrypted mail?
Hello! Would it be possible to add the configurable option to also decrypt encrypted messages on the fly while indexing to make them searchable, too? That would be really great for people that consider gnupg mainly an encryption for transport or have their complete hard drive encrypted... Best regards! John
Re: [PATCH 5/5] emacs: Add a sort-order option to saved-searches
Quoth Mark Walters on Apr 05 at 10:24 pm: > This adds a sort-order option to saved-searches, stores it in the > saved-search buttons (widgets), and uses the stored value when the > button is pressed. > > Storing the sort-order in the widget was suggested by Jani in > id:4c3876274126985683e888641b29cf18142a5eb8.1391771337.git.j...@nikula.org. > --- > emacs/notmuch-hello.el | 11 ++- > emacs/notmuch-lib.el |7 ++- > 2 files changed, 16 insertions(+), 2 deletions(-) > > diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el > index aa40e6f..6a28372 100644 > --- a/emacs/notmuch-hello.el > +++ b/emacs/notmuch-hello.el > @@ -364,7 +364,8 @@ (defun notmuch-hello-reflect (list ncols) > (defun notmuch-hello-widget-search (widget &rest ignore) >(notmuch-search (widget-get widget > :notmuch-search-terms) > - notmuch-search-oldest-first)) > + (widget-get widget > + :notmuch-search-oldest-first))) > > (defun notmuch-saved-search-count (search) >(car (process-lines notmuch-command "count" search))) > @@ -496,12 +497,20 @@ (defun notmuch-hello-insert-buttons (searches) > (widget-insert (make-string column-indent ? ))) > (let* ((name (plist-get elem :name)) >(query (plist-get elem :query)) > + (oldest-first (cond > + ((eq (plist-get elem :sort-order) > 'newest-first) > + nil) > + ((eq (plist-get elem :sort-order) > 'oldest-first) > + t) > + (t > + notmuch-search-oldest-first))) (case (plist-get elem :sort-order) (newest-first nil) (oldest-first t) (otherwise notmuch-search-oldest-first)) >(msg-count (plist-get elem :count))) > (widget-insert (format "%8s " > (notmuch-hello-nice-number msg-count))) > (widget-create 'push-button > :notify #'notmuch-hello-widget-search > :notmuch-search-terms query > +:notmuch-search-oldest-first oldest-first > name) > (setq column-indent > (1+ (max 0 (- column-width (length name))) > diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el > index 8a12f91..8aa8cfc 100644 > --- a/emacs/notmuch-lib.el > +++ b/emacs/notmuch-lib.el > @@ -125,7 +125,12 @@ (define-widget 'notmuch-saved-search-plist 'list > (group :format "%v" :inline t (const :format " Query: " > :query) (string :format "%v"))) > (checklist :inline t >:format "%v" > - (group :format "%v" :inline t (const :format "Count-Query: > " :count-query) (string :format "%v") > + (group :format "%v" :inline t (const :format "Count-Query: > " :count-query) (string :format "%v")) > + (group :format "%v" :inline t (const :format "" > :sort-order) > + (choice :tag " Sort Order" Should there be a colon? (I haven't applied the patches and I'm afraid this is beyond my mental implementation of define-widget!) > + (const :tag "Default" nil) > + (const :tag "Oldest-first" oldest-first) > + (const :tag "Newest-first" > newest-first)) > > (defcustom notmuch-saved-searches '((:name "inbox" :query "tag:inbox") > (:name "unread" :query "tag:unread")) ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 4/5] emacs: hello: switch notmuch-hello-insert-buttons to plists
Quoth Mark Walters on Apr 05 at 10:24 pm: > Switching notmuch-hello-insert-buttons to plists means we can easily > pass extra options through to the buttons. > --- > emacs/notmuch-hello.el | 33 +++-- > 1 file changed, 19 insertions(+), 14 deletions(-) > > diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el > index c729af2..aa40e6f 100644 > --- a/emacs/notmuch-hello.el > +++ b/emacs/notmuch-hello.el > @@ -425,7 +425,9 @@ (defun notmuch-hello-query-counts (query-list &rest > options) > these is a plist but other options are available for backwards > compatibility: see notmuch-saved-search-get for details. > > -The result is the list of elements of the form (NAME QUERY COUNT). > +The result is a list of plists each of which includes the > +pairs :name NAME, :query QUERY and :count COUNT, together with > +any pairs in the original saved-search. "Pair" can be synonymous with "cons", which is not what you mean here. "Properties"? > > The values :show-empty-searches, :filter and :filter-count from > options will be handled as specified for > @@ -455,23 +457,26 @@ (defun notmuch-hello-query-counts (query-list &rest > options) > #'identity > (mapcar >(lambda (elem) > - (let ((name (notmuch-saved-search-get elem :name)) > - (search-query (notmuch-saved-search-get elem :query)) > - (message-count (prog1 (read (current-buffer)) > + (let* ((elem-plist (notmuch-hello-saved-search-to-plist elem)) > +(search-query (plist-get elem-plist :query)) > +(filtered-query (notmuch-hello-filtered-query > + search-query (plist-get options :filter))) > +(message-count (prog1 (read (current-buffer)) > (forward-line 1 > (and (or (plist-get options :show-empty-searches) (> message-count 0)) > -(list name (notmuch-hello-filtered-query > -search-query (plist-get options :filter)) > - message-count > +(setq elem-plist (plist-put elem-plist :query filtered-query)) This technically works, but `setq' is a strange thing to see in an `and'. But the problem isn't the `setq'; it's that crazy `and'. I'd replace the `and' with `when', keep the `setq' and `plist-put' in the body, and squint a lot less at this code. > +(plist-put elem-plist :count message-count >query-list > > (defun notmuch-hello-insert-buttons (searches) >"Insert buttons for SEARCHES. > > -SEARCHES must be a list containing lists of the form (NAME QUERY COUNT), > where > -QUERY is the query to start when the button for the corresponding entry is > -activated. COUNT should be the number of messages matching the query. > -Such a list can be computed with `notmuch-hello-query-counts'." > +SEARCHES must be a list of plists each of which should contain at > +least pairs for :name NAME :query QUERY and :count COUNT, where Same comment about "pairs". > +QUERY is the query to start when the button for the corresponding > +entry is activated, and COUNT should be the number of messages > +matching the query. Such a plist can be computed with > +`notmuch-hello-query-counts'." >(let* ((widest (notmuch-hello-longest-label searches)) >(tags-and-width (notmuch-hello-tags-per-line widest)) >(tags-per-line (car tags-and-width)) > @@ -489,9 +494,9 @@ (defun notmuch-hello-insert-buttons (searches) > (when elem > (if (> column-indent 0) > (widget-insert (make-string column-indent ? ))) > - (let* ((name (first elem)) > - (query (second elem)) > - (msg-count (third elem))) > + (let* ((name (plist-get elem :name)) > + (query (plist-get elem :query)) > + (msg-count (plist-get elem :count))) > (widget-insert (format "%8s " > (notmuch-hello-nice-number msg-count))) > (widget-create 'push-button ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 2/5] emacs: hello: use the saved-search helper functions
Quoth Mark Walters on Apr 05 at 10:24 pm: > This uses the helper functions: the saved searches format has not > changed yet but backwards compatibility means everything still works. > --- > emacs/notmuch-hello.el | 48 > ++-- > emacs/notmuch.el |6 +++--- > 2 files changed, 25 insertions(+), 29 deletions(-) > > diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el > index 0b9ed16..733208b 100644 > --- a/emacs/notmuch-hello.el > +++ b/emacs/notmuch-hello.el > @@ -319,7 +319,7 @@ (defun notmuch-hello-add-saved-search (widget) > (setq notmuch-saved-searches > (loop for elem in notmuch-saved-searches > if (not (equal name > -(car elem))) > +(notmuch-saved-search-get elem :name))) > collect elem)) > ;; Add the new one. > (customize-save-variable 'notmuch-saved-searches > @@ -339,7 +339,7 @@ (defun notmuch-hello-delete-search-from-history (widget) > > (defun notmuch-hello-longest-label (searches-alist) >(or (loop for elem in searches-alist > - maximize (length (car elem))) > + maximize (length (notmuch-saved-search-get elem :name))) >0)) > > (defun notmuch-hello-reflect-generate-row (ncols nrows row list) > @@ -418,13 +418,12 @@ (defun notmuch-hello-filtered-query (query filter) > (concat "(" query ") and (" filter ")")) > (t query))) > > -(defun notmuch-hello-query-counts (query-alist &rest options) > - "Compute list of counts of matched messages from QUERY-ALIST. > +(defun notmuch-hello-query-counts (query-list &rest options) > + "Compute list of counts of matched messages from QUERY-LIST. > > -QUERY-ALIST must be a list containing elements of the form (NAME . QUERY) > -or (NAME QUERY COUNT-QUERY). If the latter form is used, > -COUNT-QUERY specifies an alternate query to be used to generate > -the count for the associated query. > +QUERY-LIST must be a list of saved-searches. Ideally each of > +these is a plist but other options are available for backwards > +compatibility: see notmuch-saved-search-get for details. s/:/./ Also `'s around notmuch-saved-search-get. Actually, the accepted formats (including the understood keys in plist form) should be documented in `notmuch-saved-searches' and this information should be cited elsewhere and not duplicated. > > The result is the list of elements of the form (NAME QUERY COUNT). > > @@ -432,11 +431,9 @@ (defun notmuch-hello-query-counts (query-alist &rest > options) > options will be handled as specified for > `notmuch-hello-insert-searches'." >(with-temp-buffer > -(dolist (elem query-alist nil) > - (let ((count-query (if (consp (cdr elem)) > - ;; do we have a different query for the message > count? > - (third elem) > -(cdr elem > +(dolist (elem query-list nil) > + (let ((count-query (or (notmuch-saved-search-get elem :count-query) > + (notmuch-saved-search-get elem :query > (insert >(replace-regexp-in-string > "\n" " " > @@ -458,18 +455,15 @@ (defun notmuch-hello-query-counts (query-alist &rest > options) > #'identity > (mapcar >(lambda (elem) > - (let ((name (car elem)) > - (search-query (if (consp (cdr elem)) > - ;; do we have a different query for the > message count? > - (second elem) > - (cdr elem))) > + (let ((name (notmuch-saved-search-get elem :name)) > + (search-query (notmuch-saved-search-get elem :query)) > (message-count (prog1 (read (current-buffer)) > (forward-line 1 > (and (or (plist-get options :show-empty-searches) (> message-count 0)) > (list name (notmuch-hello-filtered-query > search-query (plist-get options :filter)) >message-count > - query-alist > + query-list > > (defun notmuch-hello-insert-buttons (searches) >"Insert buttons for SEARCHES. > @@ -728,13 +722,15 @@ (defun notmuch-hello-insert-recent-searches () >(indent-rigidly start (point) notmuch-hello-indent)) > nil)) > > -(defun notmuch-hello-insert-searches (title query-alist &rest options) > - "Insert a section with TITLE showing a list of buttons made from > QUERY-ALIST. > +(defun notmuch-hello-insert-searches (title query-list &rest options) > + "Insert a section with TITLE showing a list of buttons made from > QUERY-LIST. > > -QUERY-ALIST must be a list containing elements of the form (NAME . QUERY) > -or (NAME QUERY COUNT-QUERY). If the latter form is used, > -COUNT-QUERY specifies an alternate query to be used to generate > -the count for the associated item. > +QUERY-LIST should ideally be a plist but for backw
Re: [PATCH 1/5] emacs: hello: add helper functions for saved-searches
Quoth Mark Walters on Apr 05 at 10:24 pm: > Add helper functions to for saved searches to ease the transition to > the new plist form while maintaining backwards compatibility. They > will be used in the next patch. > --- > emacs/notmuch-hello.el | 39 +++ > 1 file changed, 39 insertions(+) > > diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el > index e325cd3..0b9ed16 100644 > --- a/emacs/notmuch-hello.el > +++ b/emacs/notmuch-hello.el > @@ -269,6 +269,45 @@ (defun notmuch-hello-search (&optional search) >(add-to-history 'notmuch-search-history search))) >(notmuch-search search notmuch-search-oldest-first)) > > +(defun notmuch-saved-search-get (saved-search field) > + "Get FIELD from SAVED-SEARCH. > + > +In the new style saved-search (a plist) this is just plist-get It won't be "new style" once this has been in for a while. Perhaps "If SAVED-SEARCH is a plist, this is just `plist-get', but for backwards compatibility, ..." > +but, for backwards compatibility, this deals with the two > +old-style forms: cons cells (NAME . QUERY) and lists (NAME QUERY > +COUNT-QUERY)." > + (cond > + ((plist-get saved-search :name) Rather than depending on :name, maybe this should be a more generic plist test like (keywordp (car saved-search))? > +(plist-get saved-search field)) > + ;; It is not a plist so it is an old-style entry. > + ((consp (cdr saved-search)) ;; It is a list (NAME QUERY COUNT-QUERY) > +(case field > + (:name (car saved-search)) Use `first' for consistency with the other case cases? > + (:query (second saved-search)) > + (:count-query (third saved-search)) > + (t nil))) > + (t ;; It is a cons-cell (NAME . QUERY) > +(case field > + (:name (car saved-search)) > + (:query (cdr saved-search)) > + (t nil) > + > +(defun notmuch-hello-saved-search-to-plist (saved-search) > + "Convert a saved-search variable into plist form. This takes a value, not a variable. But it could be more succinct and more accurate: "Return a copy of SAVED-SEARCH in plist form." > + > +The new style saved search is just a plist, but for backwards Same comment about "new style". > +compatatibility we use this function to give them in > +plist-form. In all cases a new copy is returned so it is safe to Grammar error? > +modify the returned value." > + (if (and (listp (cdr saved-search)) (plist-member saved-search :name)) > + (copy-seq saved-search) > +(let ((fields (list :name :query :count-query)) > + (plist-search)) Personally I prefer to either explicitly initialize nil variables or to list them without the parenthesis at all (for some reason my brain automatically reads this as an application), but if you prefer this, that's fine, too. > + (dolist (field fields plist-search) > + (let ((string (notmuch-saved-search-get saved-search field))) > + (when string > + (setq plist-search (append plist-search (list field string) > + > (defun notmuch-hello-add-saved-search (widget) >(interactive) >(let ((search (widget-value ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 7/7] doc/INSTALL: Remove rst2man reference and other updates
"W. Trevor King" writes: > The rst2man target was removed in 9d9a700 (doc: build man pages at > build time; introduce HAVE_SPHINX, HAVE_RST2MAN, 2014-03-13), but a > reference in the install docs slipped through. While I was removing > that reference, I also: > > * Converted doc/INSTALL to reStructuredText, so I can link to Sphinx > and Docutils directly. Not everyone has access to Debian's > python-docutils, so it's better to be genric here. > * Converted from an unordered list to paragraphs, because I think it > flows better. > * Dropped the rst2man no-automatic-install caveat. I don't think this > applies to the current code, although I haven't tried to track down > a commit that adds the automatic-install support. Anyhow, > > $ make HAVE_SPHINX=0 RST2MAN=/usr/bin/rst2man.py DESTDIR=/tmp/ install-man > > works for me. > --- > doc/INSTALL | 34 -- > 1 file changed, 20 insertions(+), 14 deletions(-) > > diff --git a/doc/INSTALL b/doc/INSTALL > index e37c2b9..91222f9 100644 > --- a/doc/INSTALL > +++ b/doc/INSTALL > @@ -1,24 +1,30 @@ > This file contains some more detailed information about building and > installing the documentation. > > -Building with sphinx. > -- > +Building with Sphinx > + > > -- You need sphinx at least version 1.0. > +With Sphinx_ version 1.0 or greater, you can build man, info, html, > +and pdf versions of the docs (currently only the man pages) with:: > > -- You can build build and install man pages with 'make install-man' > + make build-{man|info|html|pdf} most of those those targets now start with sphinx- > > -- You can build man, info, html, and pdf versions of the docs > - (currently only the man pages) with > +You can build build and install the docs (currently only the man > +pages) with:: build build > > - 'make install-{man|info|html|pdf}' > + make install-{man|info|html|pdf} > this is not your bug per se, but while we're fixing docs, most of those targets don't exist. > -Building the man pages > --- > +Building the man Docutils > +- > + with > -- You can build the man pages with rst2man (from python-docutils) with > - 'make rst2man'. > +If you don't have Sphinx installed, you can still build the man-page > +version of the docs using rst2man (from Docutils_):: > > -- Currently there is no support to automagically install the resulting > - nroff files, but it should work to modify the target install-man > - in doc/Makefile.local. This should mention the relevant variables, since the targets are the same in both cases Finally, I don't really object to rewriting doc/INSTALL in rst, but I wonder if we should rename it to INSTALL.rst d
Re: [PATCH 7/7] doc/INSTALL: Remove rst2man reference and other updates
"W. Trevor King" writes: > {build|install}-man, which is backend (Sphinx/Docutils) agnostic > sphinx-{html|texinfo|info}, which doesn't have an install target > > Is that distinction intentional? Personally I prefer the consistency > of: > > {build|install}-{man|html|texinfo|info} > I think the sphinx- prefix is a historical accident, from when we tried to control backend with targets, so I don't really mind those switching (back?) to build- install-man is backend agnostic. Similar targets could be written for html and info, but no-one did yet. I guess we'd need variables to specify destinations. Installing info is a bit tricky because of the need to use install-info(1) to update directory files ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 5/5] emacs: Add a sort-order option to saved-searches
This adds a sort-order option to saved-searches, stores it in the saved-search buttons (widgets), and uses the stored value when the button is pressed. Storing the sort-order in the widget was suggested by Jani in id:4c3876274126985683e888641b29cf18142a5eb8.1391771337.git.j...@nikula.org. --- emacs/notmuch-hello.el | 11 ++- emacs/notmuch-lib.el |7 ++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index aa40e6f..6a28372 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -364,7 +364,8 @@ (defun notmuch-hello-reflect (list ncols) (defun notmuch-hello-widget-search (widget &rest ignore) (notmuch-search (widget-get widget :notmuch-search-terms) - notmuch-search-oldest-first)) + (widget-get widget + :notmuch-search-oldest-first))) (defun notmuch-saved-search-count (search) (car (process-lines notmuch-command "count" search))) @@ -496,12 +497,20 @@ (defun notmuch-hello-insert-buttons (searches) (widget-insert (make-string column-indent ? ))) (let* ((name (plist-get elem :name)) (query (plist-get elem :query)) +(oldest-first (cond + ((eq (plist-get elem :sort-order) 'newest-first) +nil) + ((eq (plist-get elem :sort-order) 'oldest-first) +t) + (t +notmuch-search-oldest-first))) (msg-count (plist-get elem :count))) (widget-insert (format "%8s " (notmuch-hello-nice-number msg-count))) (widget-create 'push-button :notify #'notmuch-hello-widget-search :notmuch-search-terms query + :notmuch-search-oldest-first oldest-first name) (setq column-indent (1+ (max 0 (- column-width (length name))) diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 8a12f91..8aa8cfc 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -125,7 +125,12 @@ (define-widget 'notmuch-saved-search-plist 'list (group :format "%v" :inline t (const :format " Query: " :query) (string :format "%v"))) (checklist :inline t :format "%v" -(group :format "%v" :inline t (const :format "Count-Query: " :count-query) (string :format "%v") +(group :format "%v" :inline t (const :format "Count-Query: " :count-query) (string :format "%v")) +(group :format "%v" :inline t (const :format "" :sort-order) + (choice :tag " Sort Order" + (const :tag "Default" nil) + (const :tag "Oldest-first" oldest-first) + (const :tag "Newest-first" newest-first)) (defcustom notmuch-saved-searches '((:name "inbox" :query "tag:inbox") (:name "unread" :query "tag:unread")) -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 1/5] emacs: hello: add helper functions for saved-searches
Add helper functions to for saved searches to ease the transition to the new plist form while maintaining backwards compatibility. They will be used in the next patch. --- emacs/notmuch-hello.el | 39 +++ 1 file changed, 39 insertions(+) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index e325cd3..0b9ed16 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -269,6 +269,45 @@ (defun notmuch-hello-search (&optional search) (add-to-history 'notmuch-search-history search))) (notmuch-search search notmuch-search-oldest-first)) +(defun notmuch-saved-search-get (saved-search field) + "Get FIELD from SAVED-SEARCH. + +In the new style saved-search (a plist) this is just plist-get +but, for backwards compatibility, this deals with the two +old-style forms: cons cells (NAME . QUERY) and lists (NAME QUERY +COUNT-QUERY)." + (cond + ((plist-get saved-search :name) +(plist-get saved-search field)) + ;; It is not a plist so it is an old-style entry. + ((consp (cdr saved-search)) ;; It is a list (NAME QUERY COUNT-QUERY) +(case field + (:name (car saved-search)) + (:query (second saved-search)) + (:count-query (third saved-search)) + (t nil))) + (t ;; It is a cons-cell (NAME . QUERY) +(case field + (:name (car saved-search)) + (:query (cdr saved-search)) + (t nil) + +(defun notmuch-hello-saved-search-to-plist (saved-search) + "Convert a saved-search variable into plist form. + +The new style saved search is just a plist, but for backwards +compatatibility we use this function to give them in +plist-form. In all cases a new copy is returned so it is safe to +modify the returned value." + (if (and (listp (cdr saved-search)) (plist-member saved-search :name)) + (copy-seq saved-search) +(let ((fields (list :name :query :count-query)) + (plist-search)) + (dolist (field fields plist-search) + (let ((string (notmuch-saved-search-get saved-search field))) + (when string + (setq plist-search (append plist-search (list field string) + (defun notmuch-hello-add-saved-search (widget) (interactive) (let ((search (widget-value -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 4/5] emacs: hello: switch notmuch-hello-insert-buttons to plists
Switching notmuch-hello-insert-buttons to plists means we can easily pass extra options through to the buttons. --- emacs/notmuch-hello.el | 33 +++-- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index c729af2..aa40e6f 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -425,7 +425,9 @@ (defun notmuch-hello-query-counts (query-list &rest options) these is a plist but other options are available for backwards compatibility: see notmuch-saved-search-get for details. -The result is the list of elements of the form (NAME QUERY COUNT). +The result is a list of plists each of which includes the +pairs :name NAME, :query QUERY and :count COUNT, together with +any pairs in the original saved-search. The values :show-empty-searches, :filter and :filter-count from options will be handled as specified for @@ -455,23 +457,26 @@ (defun notmuch-hello-query-counts (query-list &rest options) #'identity (mapcar (lambda (elem) - (let ((name (notmuch-saved-search-get elem :name)) - (search-query (notmuch-saved-search-get elem :query)) - (message-count (prog1 (read (current-buffer)) + (let* ((elem-plist (notmuch-hello-saved-search-to-plist elem)) + (search-query (plist-get elem-plist :query)) + (filtered-query (notmuch-hello-filtered-query + search-query (plist-get options :filter))) + (message-count (prog1 (read (current-buffer)) (forward-line 1 (and (or (plist-get options :show-empty-searches) (> message-count 0)) - (list name (notmuch-hello-filtered-query - search-query (plist-get options :filter)) -message-count + (setq elem-plist (plist-put elem-plist :query filtered-query)) + (plist-put elem-plist :count message-count query-list (defun notmuch-hello-insert-buttons (searches) "Insert buttons for SEARCHES. -SEARCHES must be a list containing lists of the form (NAME QUERY COUNT), where -QUERY is the query to start when the button for the corresponding entry is -activated. COUNT should be the number of messages matching the query. -Such a list can be computed with `notmuch-hello-query-counts'." +SEARCHES must be a list of plists each of which should contain at +least pairs for :name NAME :query QUERY and :count COUNT, where +QUERY is the query to start when the button for the corresponding +entry is activated, and COUNT should be the number of messages +matching the query. Such a plist can be computed with +`notmuch-hello-query-counts'." (let* ((widest (notmuch-hello-longest-label searches)) (tags-and-width (notmuch-hello-tags-per-line widest)) (tags-per-line (car tags-and-width)) @@ -489,9 +494,9 @@ (defun notmuch-hello-insert-buttons (searches) (when elem (if (> column-indent 0) (widget-insert (make-string column-indent ? ))) - (let* ((name (first elem)) -(query (second elem)) -(msg-count (third elem))) + (let* ((name (plist-get elem :name)) +(query (plist-get elem :query)) +(msg-count (plist-get elem :count))) (widget-insert (format "%8s " (notmuch-hello-nice-number msg-count))) (widget-create 'push-button -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 2/5] emacs: hello: use the saved-search helper functions
This uses the helper functions: the saved searches format has not changed yet but backwards compatibility means everything still works. --- emacs/notmuch-hello.el | 48 ++-- emacs/notmuch.el |6 +++--- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 0b9ed16..733208b 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -319,7 +319,7 @@ (defun notmuch-hello-add-saved-search (widget) (setq notmuch-saved-searches (loop for elem in notmuch-saved-searches if (not (equal name - (car elem))) + (notmuch-saved-search-get elem :name))) collect elem)) ;; Add the new one. (customize-save-variable 'notmuch-saved-searches @@ -339,7 +339,7 @@ (defun notmuch-hello-delete-search-from-history (widget) (defun notmuch-hello-longest-label (searches-alist) (or (loop for elem in searches-alist - maximize (length (car elem))) + maximize (length (notmuch-saved-search-get elem :name))) 0)) (defun notmuch-hello-reflect-generate-row (ncols nrows row list) @@ -418,13 +418,12 @@ (defun notmuch-hello-filtered-query (query filter) (concat "(" query ") and (" filter ")")) (t query))) -(defun notmuch-hello-query-counts (query-alist &rest options) - "Compute list of counts of matched messages from QUERY-ALIST. +(defun notmuch-hello-query-counts (query-list &rest options) + "Compute list of counts of matched messages from QUERY-LIST. -QUERY-ALIST must be a list containing elements of the form (NAME . QUERY) -or (NAME QUERY COUNT-QUERY). If the latter form is used, -COUNT-QUERY specifies an alternate query to be used to generate -the count for the associated query. +QUERY-LIST must be a list of saved-searches. Ideally each of +these is a plist but other options are available for backwards +compatibility: see notmuch-saved-search-get for details. The result is the list of elements of the form (NAME QUERY COUNT). @@ -432,11 +431,9 @@ (defun notmuch-hello-query-counts (query-alist &rest options) options will be handled as specified for `notmuch-hello-insert-searches'." (with-temp-buffer -(dolist (elem query-alist nil) - (let ((count-query (if (consp (cdr elem)) -;; do we have a different query for the message count? -(third elem) - (cdr elem +(dolist (elem query-list nil) + (let ((count-query (or (notmuch-saved-search-get elem :count-query) +(notmuch-saved-search-get elem :query (insert (replace-regexp-in-string "\n" " " @@ -458,18 +455,15 @@ (defun notmuch-hello-query-counts (query-alist &rest options) #'identity (mapcar (lambda (elem) - (let ((name (car elem)) - (search-query (if (consp (cdr elem)) -;; do we have a different query for the message count? -(second elem) - (cdr elem))) + (let ((name (notmuch-saved-search-get elem :name)) + (search-query (notmuch-saved-search-get elem :query)) (message-count (prog1 (read (current-buffer)) (forward-line 1 (and (or (plist-get options :show-empty-searches) (> message-count 0)) (list name (notmuch-hello-filtered-query search-query (plist-get options :filter)) message-count - query-alist + query-list (defun notmuch-hello-insert-buttons (searches) "Insert buttons for SEARCHES. @@ -728,13 +722,15 @@ (defun notmuch-hello-insert-recent-searches () (indent-rigidly start (point) notmuch-hello-indent)) nil)) -(defun notmuch-hello-insert-searches (title query-alist &rest options) - "Insert a section with TITLE showing a list of buttons made from QUERY-ALIST. +(defun notmuch-hello-insert-searches (title query-list &rest options) + "Insert a section with TITLE showing a list of buttons made from QUERY-LIST. -QUERY-ALIST must be a list containing elements of the form (NAME . QUERY) -or (NAME QUERY COUNT-QUERY). If the latter form is used, -COUNT-QUERY specifies an alternate query to be used to generate -the count for the associated item. +QUERY-LIST should ideally be a plist but for backwards +compatibility other forms are also accepted (see +`notmuch-saved-search-get' for details). The plist should +contain keys :name and :query; if :count-query is also present +then it specifies an alternate query to be used to generate the +count for the associated search. Supports the following entries in OPTIONS as a plist: :initially-hidden - if non-nil, section will be hidden on startup @@ -768,7 +764,7 @@ (defun notmuch-hello-insert
[PATCH 3/5] emacs: hello: add a customize for saved-searches
Make the defcustom for notmuch-saved-searches use the new plist format. It should still work with oldstyle saved-searches but will write the newstyle form. --- emacs/notmuch-hello.el |2 +- emacs/notmuch-lib.el | 28 +--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 733208b..c729af2 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -324,7 +324,7 @@ (defun notmuch-hello-add-saved-search (widget) ;; Add the new one. (customize-save-variable 'notmuch-saved-searches (add-to-list 'notmuch-saved-searches - (cons name search) t)) + (list :name name :query search) t)) (message "Saved '%s' as '%s'." search name) (notmuch-hello-update))) diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 959764e..8a12f91 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -107,10 +107,32 @@ (defcustom notmuch-poll-script nil (defvar notmuch-search-history nil "Variable to store notmuch searches history.") -(defcustom notmuch-saved-searches '(("inbox" . "tag:inbox") - ("unread" . "tag:unread")) +(defun notmuch--saved-searches-to-plist (symbol) + "Extract a saved-search variable into plist form. + +The new style saved search is just a plist, but for backwards +compatatibility we use this function to extract old style saved +searches so they still work in customize." + (let ((saved-searches (default-value symbol))) +(mapcar #'notmuch-hello-saved-search-to-plist saved-searches))) + +(define-widget 'notmuch-saved-search-plist 'list + "A single saved search property list." + :tag "Saved Search" + :args '((list :inline t + :format "%v" + (group :format "%v" :inline t (const :format " Name: " :name) (string :format "%v")) + (group :format "%v" :inline t (const :format " Query: " :query) (string :format "%v"))) + (checklist :inline t +:format "%v" +(group :format "%v" :inline t (const :format "Count-Query: " :count-query) (string :format "%v") + +(defcustom notmuch-saved-searches '((:name "inbox" :query "tag:inbox") + (:name "unread" :query "tag:unread")) "A list of saved searches to display." - :type '(alist :key-type string :value-type string) + :get 'notmuch--saved-searches-to-plist + :type '(repeat notmuch-saved-search-plist) + :tag "List of Saved Searches" :group 'notmuch-hello) (defcustom notmuch-archive-tags '("-inbox") -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 0/5] emacs: hello: convert saved-searches to plists
This series converts the saved-search format to plists. This should make it much easier to extend their functionality. The final patch illustrates this by adding a sort-order option to the saved searches. It also exposes the count-query functionality that is already present internally, and could be used to store keyboard shortcuts for searches. The series tries hard to be backwardly compatible and seems to work in most cases. However, notmuch-hello is very interconnected so some corner cases may fail: for example if people are doing strange things with notmuch-saved-search-sort-function then it may break. Also note that the functions used for saved-searches are also used for the "all tags" section: I have not converted them as they are purely internal. Since we have backwards compatibility they still work. Best wishes Mark Mark Walters (5): emacs: hello: add helper functions for saved-searches emacs: hello: use the saved-search helper functions emacs: hello: add a customize for saved-searches emacs: hello: switch notmuch-hello-insert-buttons to plists emacs: Add a sort-order option to saved-searches emacs/notmuch-hello.el | 129 +--- emacs/notmuch-lib.el | 33 +++-- emacs/notmuch.el |6 +-- 3 files changed, 122 insertions(+), 46 deletions(-) -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 7/7] doc/INSTALL: Remove rst2man reference and other updates
On Sat, Apr 05, 2014 at 05:35:49PM -0300, David Bremner wrote: > W. Trevor King writes: > > > -- You can build build and install man pages with 'make install-man' > > + make build-{man|info|html|pdf} > > most of those those targets now start with sphinx- Ah, looks like that happended in with the original Sphinx code in d736260 (doc: convert sphinx based docs, 2014-01-28). It looks like the current usage is (from the .PHONY entries): {build|install}-man, which is backend (Sphinx/Docutils) agnostic sphinx-{html|texinfo|info}, which doesn't have an install target Is that distinction intentional? Personally I prefer the consistency of: {build|install}-{man|html|texinfo|info} if the configured backend (Sphinx/Docutils) doesn't support the requested target, we should error out. If no backend is detected, build-man and install-man should be pulled from the default dependency tree (but they would still error out if you called them directly). If that sounds reasonable, I can work up a patch. > > -- You can build man, info, html, and pdf versions of the docs > > - (currently only the man pages) with > > +You can build build and install the docs (currently only the man > > +pages) with:: > > build build Oops, thanks. > > -Building the man pages > > --- > > +Building the man Docutils > > +- > > > > + with Thanks again :p. > > -- You can build the man pages with rst2man (from python-docutils) with > > - 'make rst2man'. > > +If you don't have Sphinx installed, you can still build the man-page > > +version of the docs using rst2man (from Docutils_):: > > > > -- Currently there is no support to automagically install the resulting > > - nroff files, but it should work to modify the target install-man > > - in doc/Makefile.local. > > This should mention the relevant variables, since the targets are > the same in both cases Ok. > Finally, I don't really object to rewriting doc/INSTALL in rst, but > I wonder if we should rename it to INSTALL.rst Sure (I don't really mind). Cheers, Trevor -- This email may be signed or encrypted with GnuPG (http://www.gnupg.org). For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy signature.asc Description: OpenPGP digital signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 7/7] doc/INSTALL: Remove rst2man reference and other updates
On Sat, Apr 05, 2014 at 05:35:49PM -0300, David Bremner wrote: > W. Trevor King writes: > > > -- You can build build and install man pages with 'make install-man' > > + make build-{man|info|html|pdf} > > most of those those targets now start with sphinx- Ah, looks like that happended in with the original Sphinx code in d736260 (doc: convert sphinx based docs, 2014-01-28). It looks like the current usage is (from the .PHONY entries): {build|install}-man, which is backend (Sphinx/Docutils) agnostic sphinx-{html|texinfo|info}, which doesn't have an install target Is that distinction intentional? Personally I prefer the consistency of: {build|install}-{man|html|texinfo|info} if the configured backend (Sphinx/Docutils) doesn't support the requested target, we should error out. If no backend is detected, build-man and install-man should be pulled from the default dependency tree (but they would still error out if you called them directly). If that sounds reasonable, I can work up a patch. > > -- You can build man, info, html, and pdf versions of the docs > > - (currently only the man pages) with > > +You can build build and install the docs (currently only the man > > +pages) with:: > > build build Oops, thanks. > > -Building the man pages > > --- > > +Building the man Docutils > > +- > > > > + with Thanks again :p. > > -- You can build the man pages with rst2man (from python-docutils) with > > - 'make rst2man'. > > +If you don't have Sphinx installed, you can still build the man-page > > +version of the docs using rst2man (from Docutils_):: > > > > -- Currently there is no support to automagically install the resulting > > - nroff files, but it should work to modify the target install-man > > - in doc/Makefile.local. > > This should mention the relevant variables, since the targets are > the same in both cases Ok. > Finally, I don't really object to rewriting doc/INSTALL in rst, but > I wonder if we should rename it to INSTALL.rst Sure (I don't really mind). Cheers, Trevor -- This email may be signed or encrypted with GnuPG (http://www.gnupg.org). For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy -- next part -- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: OpenPGP digital signature URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20140405/b7335327/attachment-0001.pgp>
Feature suggestion. Indexing encrypted mail?
john.wyzer at gmx.de writes: > Would it be possible to add the configurable option to also decrypt > encrypted messages on the fly while indexing to make them searchable, > too? > > That would be really great for people that consider gnupg mainly an > encryption for transport or have their complete hard drive encrypted... As far I understand an attacker could reconstruct the message from the index, so one question is whether the extra complexity in notmuch is worth the minimal extra security over decrypting on delivery and storing plaintext on the (presumably encrypted) disk. Of course decrypting on delivery may be inconvenient (or impossible). I have CCed the two people who have implemented most of the crypto related stuff in notmuch so they can comment. d
Re: [PATCH 7/7] doc/INSTALL: Remove rst2man reference and other updates
"W. Trevor King" writes: > The rst2man target was removed in 9d9a700 (doc: build man pages at > build time; introduce HAVE_SPHINX, HAVE_RST2MAN, 2014-03-13), but a > reference in the install docs slipped through. While I was removing > that reference, I also: > > * Converted doc/INSTALL to reStructuredText, so I can link to Sphinx > and Docutils directly. Not everyone has access to Debian's > python-docutils, so it's better to be genric here. > * Converted from an unordered list to paragraphs, because I think it > flows better. > * Dropped the rst2man no-automatic-install caveat. I don't think this > applies to the current code, although I haven't tried to track down > a commit that adds the automatic-install support. Anyhow, > > $ make HAVE_SPHINX=0 RST2MAN=/usr/bin/rst2man.py DESTDIR=/tmp/ install-man > > works for me. > --- > doc/INSTALL | 34 -- > 1 file changed, 20 insertions(+), 14 deletions(-) > > diff --git a/doc/INSTALL b/doc/INSTALL > index e37c2b9..91222f9 100644 > --- a/doc/INSTALL > +++ b/doc/INSTALL > @@ -1,24 +1,30 @@ > This file contains some more detailed information about building and > installing the documentation. > > -Building with sphinx. > -- > +Building with Sphinx > + > > -- You need sphinx at least version 1.0. > +With Sphinx_ version 1.0 or greater, you can build man, info, html, > +and pdf versions of the docs (currently only the man pages) with:: > > -- You can build build and install man pages with 'make install-man' > + make build-{man|info|html|pdf} most of those those targets now start with sphinx- > > -- You can build man, info, html, and pdf versions of the docs > - (currently only the man pages) with > +You can build build and install the docs (currently only the man > +pages) with:: build build > > - 'make install-{man|info|html|pdf}' > + make install-{man|info|html|pdf} > this is not your bug per se, but while we're fixing docs, most of those targets don't exist. > -Building the man pages > --- > +Building the man Docutils > +- > + with > -- You can build the man pages with rst2man (from python-docutils) with > - 'make rst2man'. > +If you don't have Sphinx installed, you can still build the man-page > +version of the docs using rst2man (from Docutils_):: > > -- Currently there is no support to automagically install the resulting > - nroff files, but it should work to modify the target install-man > - in doc/Makefile.local. This should mention the relevant variables, since the targets are the same in both cases Finally, I don't really object to rewriting doc/INSTALL in rst, but I wonder if we should rename it to INSTALL.rst d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] debian: ignore performance corpus when making source package
David Bremner writes: > Currently "make debian-snapshot" will include the performance corpus > tarball in the source package, which slows things down and wastes disk > space. tar-ignore is needed twice to keep the default exclude rules > (e.g. to exclude .git) Pushed this. I'm thinking it would be good to treat test databases the same way, and have a new level of cleaning to remove them all. d
[PATCH v5 1/2] lib: drop support for single-message mbox files
Jani Nikula writes: > We've supported mbox files containing a single message for historical > reasons, but the support has been deprecated, with a warning message > while indexing, since Notmuch 0.15. Finally drop the support, and > consider all mbox files non-email. series pushed. d
[PATCH 1/1] release-checks: removed manual page version check
Manual pages are now generated and during the generation the version string is read from `version` file, so this (currently failing) test checking manual page versions can be removed. While at it, changed the case pattern *[^0-9.]* to its portable alternative *[!0-9.]* --- devel/release-checks.sh | 42 +- 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/devel/release-checks.sh b/devel/release-checks.sh index 8938905..797d62a 100755 --- a/devel/release-checks.sh +++ b/devel/release-checks.sh @@ -68,7 +68,7 @@ verfail () echo -n "Checking that '$VERSION' is good with digits and periods... " case $VERSION in - *[^0-9.]*) + *[!0-9.]*) verfail "'$VERSION' contains other characters than digits and periods" ;; .*) verfail "'$VERSION' begins with a period" ;; *.) verfail "'$VERSION' ends with a period" ;; @@ -196,46 +196,6 @@ case $news_date in append_emsg "Date '$news_date' in NEWS file is not in format (-mm-dd)" esac -readonly DATE=${news_date//[()]/} # bash feature -manthdata () -{ - set x $* - if [ $# != 7 ] - then - append_emsg "'$mp' has too many '.TH' lines" - man_mismatch=1 - fi - man_date=${5-} man_version=${7-} -} - -echo -n "Checking that manual page dates and versions are $DATE and $VERSION... " -manfiles=`find man -type f | sort` -man_pages_ok=Yes -for mp in $manfiles -do - case $mp in - *.[0-9]) ;; # fall below this 'case ... esac' - - */Makefile.local | */Makefile ) continue ;; - */.gitignore) continue ;; - *.bak) continue ;; - - *) append_emsg "'$mp': extra file" - man_pages_ok=No - continue - esac - manthdata `sed -n '/^[.]TH NOTMUCH/ { y/"/ /; p; }' "$mp"` - if [ "$man_version" != "$VERSION" ] - thenappend_emsg "Version '$man_version' is not '$VERSION' in $mp" - mman_pages_ok=No - fi - if [ "$man_date" != "$DATE" ] - thenappend_emsg "DATE '$man_date' is not '$DATE' in $mp" - man_pages_ok=No - fi -done -echo $man_pages_ok. - if [ -n "$emsgs" ] then echo -- 1.8.0
[PATCH v4 0/4] nmbug-status: Python-3-compatibility and general refactoring
"W. Trevor King" writes: > On Sun, Feb 16, 2014 at 07:46:29PM -0400, David Bremner wrote: >> pushed the last 4. > > It looks like there's still a nmbug-status branch on > git://notmuchmail.org/git/notmuch. It's an ancestor of debian/0.17-4, > and nmbug-status development seems to have calmed back down, so that > branch can probably be removed. done. d
[Patch v7 6/6] test: verify tag backup generated by database upgrade
'pre upgrade dump' is not much of a test, but at least this way we get somewhat sensible behaviour if it fails. --- test/T530-upgrade.sh | 6 ++ 1 file changed, 6 insertions(+) diff --git a/test/T530-upgrade.sh b/test/T530-upgrade.sh index d46e3d1..7d5d5aa 100755 --- a/test/T530-upgrade.sh +++ b/test/T530-upgrade.sh @@ -25,6 +25,8 @@ test_begin_subtest "path: search does not work with old database version" output=$(notmuch search path:foo) test_expect_equal "$output" "" +test_expect_success 'pre upgrade dump' 'notmuch dump | sort > pre-upgrade-dump' + test_begin_subtest "database upgrade from format version 1" output=$(notmuch new | sed -e 's/^Backing up tags to .*$/Backing up tags to FILENAME/') test_expect_equal "$output" "\ @@ -34,6 +36,10 @@ Backing up tags to FILENAME Your notmuch database has now been upgraded to database format version 2. No new mail." +test_begin_subtest "tag backup matches pre-upgrade dump" +gunzip -c ${MAIL_DIR}/.notmuch/dump-*.gz | sort > backup-dump +test_expect_equal_file pre-upgrade-dump backup-dump + test_begin_subtest "folder: no longer matches in the middle of path" output=$(notmuch search folder:baz) test_expect_equal "$output" "" -- 1.9.0
[Patch v7 5/6] notmuch-new: backup tags before database upgrade
All we do here is calculate the backup filename, and call the existing dump routine. Also take the opportity to add a message about being safe to interrupt. --- notmuch-new.c| 29 - test/T530-upgrade.sh | 4 +++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/notmuch-new.c b/notmuch-new.c index 82acf69..d269c7c 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -989,8 +989,35 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[]) return EXIT_FAILURE; if (notmuch_database_needs_upgrade (notmuch)) { - if (add_files_state.verbosity >= VERBOSITY_NORMAL) + time_t now = time (NULL); + struct tm *gm_time = gmtime (&now); + + /* since dump files are written atomically, the amount of +* harm from overwriting one within a second seems +* relatively small. */ + + const char *backup_name = + talloc_asprintf (notmuch, "%s/dump-%04d%02d%02dT%02d%02d%02d.gz", +dot_notmuch_path, +gm_time->tm_year + 1900, +gm_time->tm_mon + 1, +gm_time->tm_mday, +gm_time->tm_hour, +gm_time->tm_min, +gm_time->tm_sec); + + if (add_files_state.verbosity >= VERBOSITY_NORMAL) { printf ("Welcome to a new version of notmuch! Your database will now be upgraded.\n"); + printf ("This process is safe to interrupt.\n"); + printf ("Backing up tags to %s...\n", backup_name); + } + + if (notmuch_database_dump (notmuch, backup_name, "", + DUMP_FORMAT_BATCH_TAG, TRUE)) { + fprintf (stderr, "Backup failed. Aborting upgrade."); + return EXIT_FAILURE; + } + gettimeofday (&add_files_state.tv_start, NULL); notmuch_database_upgrade (notmuch, add_files_state.verbosity >= VERBOSITY_NORMAL ? upgrade_print_progress : NULL, diff --git a/test/T530-upgrade.sh b/test/T530-upgrade.sh index 67bbf31..d46e3d1 100755 --- a/test/T530-upgrade.sh +++ b/test/T530-upgrade.sh @@ -26,9 +26,11 @@ output=$(notmuch search path:foo) test_expect_equal "$output" "" test_begin_subtest "database upgrade from format version 1" -output=$(notmuch new) +output=$(notmuch new | sed -e 's/^Backing up tags to .*$/Backing up tags to FILENAME/') test_expect_equal "$output" "\ Welcome to a new version of notmuch! Your database will now be upgraded. +This process is safe to interrupt. +Backing up tags to FILENAME Your notmuch database has now been upgraded to database format version 2. No new mail." -- 1.9.0
[Patch v7 4/6] restore: transparently support gzipped input
We rely completely on zlib to do the right thing in detecting gzipped input. Since our dump format is chosen to be 7 bit ascii, this should be fine. --- doc/man1/notmuch-restore.rst | 8 notmuch-restore.c| 93 +--- test/T240-dump-restore.sh| 14 +++ 3 files changed, 92 insertions(+), 23 deletions(-) diff --git a/doc/man1/notmuch-restore.rst b/doc/man1/notmuch-restore.rst index d6cf19a..936b138 100644 --- a/doc/man1/notmuch-restore.rst +++ b/doc/man1/notmuch-restore.rst @@ -50,6 +50,14 @@ Supported options for **restore** include format, this heuristic, based the fact that batch-tag format contains no parentheses, should be accurate. +GZIPPED INPUT += + +\ **notmuch restore** will detect if the input is compressed in +**gzip(1)** format and automatically decompress it while reading. This +detection does not depend on file naming and in particular works for +standard input. + SEE ALSO diff --git a/notmuch-restore.c b/notmuch-restore.c index c54d513..7abee0a 100644 --- a/notmuch-restore.c +++ b/notmuch-restore.c @@ -22,6 +22,7 @@ #include "hex-escape.h" #include "tag-util.h" #include "string-util.h" +#include "zlib-extra.h" static regex_t regex; @@ -128,10 +129,10 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) tag_op_list_t *tag_ops; char *input_file_name = NULL; -FILE *input = stdin; +const char *name_for_error = NULL; +gzFile input = NULL; char *line = NULL; void *line_ctx = NULL; -size_t line_size; ssize_t line_len; int ret = 0; @@ -157,39 +158,69 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) }; opt_index = parse_arguments (argc, argv, options, 1); -if (opt_index < 0) - return EXIT_FAILURE; +if (opt_index < 0) { + ret = EXIT_FAILURE; + goto DONE; +} + +name_for_error = input_file_name ? input_file_name : "stdin"; if (! accumulate) flags |= TAG_FLAG_REMOVE_ALL; -if (input_file_name) { - input = fopen (input_file_name, "r"); - if (input == NULL) { - fprintf (stderr, "Error opening %s for reading: %s\n", -input_file_name, strerror (errno)); - return EXIT_FAILURE; +errno = 0; +if (input_file_name) + input = gzopen (input_file_name, "r"); +else { + int infd = dup (STDIN_FILENO); + if (infd < 0) { + fprintf (stderr, "Error duping stdin: %s\n", +strerror (errno)); + ret = EXIT_FAILURE; + goto DONE; } + input = gzdopen (infd, "r"); + if (! input) + close (infd); +} + +if (input == NULL) { + fprintf (stderr, "Error opening %s for (gzip) reading: %s\n", +name_for_error, strerror (errno)); + ret = EXIT_FAILURE; + goto DONE; } if (opt_index < argc) { fprintf (stderr, "Unused positional parameter: %s\n", argv[opt_index]); - return EXIT_FAILURE; + ret = EXIT_FAILURE; + goto DONE; } tag_ops = tag_op_list_create (config); if (tag_ops == NULL) { fprintf (stderr, "Out of memory.\n"); - return EXIT_FAILURE; + ret = EXIT_FAILURE; + goto DONE; } do { - line_len = getline (&line, &line_size, input); + util_status_t status; + + status = gz_getline (line_ctx, &line, &line_len, input); /* empty input file not considered an error */ - if (line_len < 0) - return EXIT_SUCCESS; + if (status == UTIL_EOF) { + ret = EXIT_SUCCESS; + goto DONE; + } + if (status) { + fprintf (stderr, "Error reading (gzipped) input: %s\n", +gz_error_string(status, input)); + ret = EXIT_FAILURE; + goto DONE; + } } while ((line_len == 0) || (line[0] == '#') || /* the cast is safe because we checked about for line_len < 0 */ @@ -254,21 +285,37 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) if (ret) break; -} while ((line_len = getline (&line, &line_size, input)) != -1); +} while (! (ret = gz_getline (line_ctx, &line, &line_len, input))); + -if (line_ctx != NULL) - talloc_free (line_ctx); +/* EOF is normal loop termination condition, UTIL_SUCCESS is + * impossible here */ +if (ret == UTIL_EOF) { + ret = UTIL_SUCCESS; +} else { + fprintf (stderr, "Error reading (gzipped) input: %s\n", +gz_error_string (ret, input)); +} + +/* currently this should not be after DONE: since we don't + * know if the xregcomp was reached + */ if (input_format == DUMP_FORMAT_SUP) regfree (®ex); -if (line) - free (line); + DONE: +if (line_ctx != NULL) + talloc_free
[Patch v7 3/6] test: restore with missing final newline
Recent proposed patches for gzipped input had a bug with handling missing newlines that was not caught by the current test suite --- test/T240-dump-restore.sh | 9 + 1 file changed, 9 insertions(+) diff --git a/test/T240-dump-restore.sh b/test/T240-dump-restore.sh index d79aca8..b6d8602 100755 --- a/test/T240-dump-restore.sh +++ b/test/T240-dump-restore.sh @@ -110,6 +110,15 @@ notmuch dump --format=batch-tag from:cworth | sed 's/^.*-- id://' | \ sort > OUTPUT.$test_count test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count +test_begin_subtest "format=batch-tag, missing newline" +printf "+a_tag_without_newline -- id:20091117232137.GA7669 at griffis1.net" > IN +notmuch restore --accumulate < IN +notmuch dump id:20091117232137.GA7669 at griffis1.net > OUT +cat < EXPECTED ++a_tag_without_newline +inbox +unread -- id:20091117232137.GA7669 at griffis1.net +EOF +test_expect_equal_file EXPECTED OUT + test_begin_subtest "format=batch-tag, # round-trip" notmuch dump --format=sup | sort > EXPECTED.$test_count notmuch dump --format=batch-tag | notmuch restore --format=batch-tag -- 1.9.0
[Patch v7 2/6] util: add gz_readline
The idea is to provide a more or less drop in replacement for readline to read from zlib/gzip streams. Take the opportunity to replace malloc with talloc. --- util/Makefile.local | 3 +- util/util.c | 24 +++ util/util.h | 29 ++ util/zlib-extra.c | 85 + util/zlib-extra.h | 25 5 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 util/util.c create mode 100644 util/util.h create mode 100644 util/zlib-extra.c create mode 100644 util/zlib-extra.h diff --git a/util/Makefile.local b/util/Makefile.local index 29c0ce6..905f237 100644 --- a/util/Makefile.local +++ b/util/Makefile.local @@ -4,7 +4,8 @@ dir := util extra_cflags += -I$(srcdir)/$(dir) libutil_c_srcs := $(dir)/xutil.c $(dir)/error_util.c $(dir)/hex-escape.c \ - $(dir)/string-util.c $(dir)/talloc-extra.c + $(dir)/string-util.c $(dir)/talloc-extra.c $(dir)/zlib-extra.c \ + $(dir)/util.c libutil_modules := $(libutil_c_srcs:.c=.o) diff --git a/util/util.c b/util/util.c new file mode 100644 index 000..3bd305d --- /dev/null +++ b/util/util.c @@ -0,0 +1,24 @@ +#include "util.h" +#include "error_util.h" +#include +#include + +const char * +util_error_string (util_status_t errnum) +{ +switch (errnum) { +case UTIL_SUCCESS: + return "none"; +case UTIL_OUT_OF_MEMORY: + return "out of memory"; +case UTIL_EOF: + return "end of file"; +case UTIL_ERRNO: + return strerror (errno); +case UTIL_GZERROR: + /* we lack context to be more informative here */ + return "zlib error"; +default: + INTERNAL_ERROR("unexpected error status %d", errnum); +} +} diff --git a/util/util.h b/util/util.h new file mode 100644 index 000..d12fadb --- /dev/null +++ b/util/util.h @@ -0,0 +1,29 @@ +#ifndef _UTIL_H +#define _UTIL_H + +typedef enum util_status { +/** + * No error occurred. + */ +UTIL_SUCCESS = 0, +/** + * Out of memory. + */ +UTIL_OUT_OF_MEMORY, +/** + * End of stream reached while attempting to read. + */ +UTIL_EOF, +/** + * Low level error occured, consult errno. + */ +UTIL_ERRNO, +/** + * Zlib error occured, call gzerror for details. + */ +UTIL_GZERROR +} util_status_t; + +const char * +util_error_string (util_status_t status); +#endif diff --git a/util/zlib-extra.c b/util/zlib-extra.c new file mode 100644 index 000..cb34845 --- /dev/null +++ b/util/zlib-extra.c @@ -0,0 +1,85 @@ +/* zlib-extra.c - Extra or enhanced routines for compressed I/O. + * + * Copyright (c) 2014 David Bremner + * + * This program 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. + * + * This program 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 this program. If not, see http://www.gnu.org/licenses/ . + * + * Author: David Bremner + */ + +#include "zlib-extra.h" +#include +#include +#include + +/* mimic POSIX/glibc getline, but on a zlib gzFile stream, and using talloc */ +util_status_t +gz_getline (void *talloc_ctx, char **bufptr, ssize_t *bytes_read, gzFile stream) +{ +char *buf = *bufptr; +unsigned int len; +size_t offset = 0; + +if (buf) { + len = talloc_array_length (buf); +} else { + /* same as getdelim from gnulib */ + len = 120; + buf = talloc_array (talloc_ctx, char, len); + if (buf == NULL) + return UTIL_OUT_OF_MEMORY; +} + +while (1) { + if (! gzgets (stream, buf + offset, len - offset)) { + /* Null indicates EOF or error */ + int zlib_status = 0; + (void) gzerror (stream, &zlib_status); + switch (zlib_status) { + case Z_OK: + /* no data read before EOF */ + if (offset == 0) + return UTIL_EOF; + else + goto SUCCESS; + case Z_ERRNO: + return UTIL_ERRNO; + default: + return UTIL_GZERROR; + } + } + + offset += strlen (buf + offset); + + if (buf[offset - 1] == '\n') + goto SUCCESS; + + len *= 2; + buf = talloc_realloc (talloc_ctx, buf, char, len); + if (buf == NULL) + return UTIL_OUT_OF_MEMORY; +} + SUCCESS: +*bufptr = buf; +*bytes_read = offset; +return UTIL_SUCCESS; +} + +const char *gz_error_string (util_status_t status, gzFile file) +{ +if (sta
[Patch v7 1/6] dump: support gzipped and atomic output
The main goal is to support gzipped output for future internal calls (e.g. from notmuch-new) to notmuch_database_dump. The additional dependency is not very heavy since xapian already pulls in zlib. We want the dump to be "atomic", in the sense that after running the dump file is either present and complete, or not present. This avoids certain classes of mishaps involving overwriting a good backup with a bad or partial one. --- INSTALL | 20 +++-- Makefile.local| 2 +- configure | 28 +++-- doc/man1/notmuch-dump.rst | 3 ++ notmuch-client.h | 4 +- notmuch-dump.c| 101 +- test/T240-dump-restore.sh | 12 ++ 7 files changed, 142 insertions(+), 28 deletions(-) diff --git a/INSTALL b/INSTALL index 690b0ef..b543c50 100644 --- a/INSTALL +++ b/INSTALL @@ -20,8 +20,8 @@ configure stage. Dependencies -Notmuch depends on three libraries: Xapian, GMime 2.4 or 2.6, and -Talloc which are each described below: +Notmuch depends on four libraries: Xapian, GMime 2.4 or 2.6, +Talloc, and zlib which are each described below: Xapian -- @@ -60,6 +60,18 @@ Talloc which are each described below: Talloc is available from http://talloc.samba.org/ + zlib + + + zlib is an extremely popular compression library. It is used + by Xapian, so if you installed that you will already have + zlib. You may need to install the zlib headers separately. + + Notmuch needs the transparent write feature of zlib introduced + in version 1.2.5.2 (Dec. 2011). + + zlib is available from http://zlib.net + Building Documentation -- @@ -79,11 +91,11 @@ dependencies with a simple simple command line. For example: For Debian and similar: -sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev python-sphinx +sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev zlib1g-dev python-sphinx For Fedora and similar: - sudo yum install xapian-core-devel gmime-devel libtalloc-devel python-sphinx + sudo yum install xapian-core-devel gmime-devel libtalloc-devel zlib-devel python-sphinx On other systems, a similar command can be used, but the details of the package names may be different. diff --git a/Makefile.local b/Makefile.local index cb7b106..e5a20a7 100644 --- a/Makefile.local +++ b/Makefile.local @@ -41,7 +41,7 @@ PV_FILE=bindings/python/notmuch/version.py # Smash together user's values with our extra values FINAL_CFLAGS = -DNOTMUCH_VERSION=$(VERSION) $(CPPFLAGS) $(CFLAGS) $(WARN_CFLAGS) $(extra_cflags) $(CONFIGURE_CFLAGS) FINAL_CXXFLAGS = $(CPPFLAGS) $(CXXFLAGS) $(WARN_CXXFLAGS) $(extra_cflags) $(extra_cxxflags) $(CONFIGURE_CXXFLAGS) -FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Lutil -lutil -Llib -lnotmuch $(AS_NEEDED_LDFLAGS) $(GMIME_LDFLAGS) $(TALLOC_LDFLAGS) +FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Lutil -lutil -Llib -lnotmuch $(AS_NEEDED_LDFLAGS) $(GMIME_LDFLAGS) $(TALLOC_LDFLAGS) $(ZLIB_LDFLAGS) FINAL_NOTMUCH_LINKER = CC ifneq ($(LINKER_RESOLVES_LIBRARY_DEPENDENCIES),1) FINAL_NOTMUCH_LDFLAGS += $(CONFIGURE_LDFLAGS) diff --git a/configure b/configure index 1d430b9..83b4af7 100755 --- a/configure +++ b/configure @@ -340,6 +340,18 @@ else errors=$((errors + 1)) fi +printf "Checking for zlib (>= 1.2.5.2)... " +have_zlib=0 +if pkg-config --atleast-version=1.2.5.2 zlib; then +printf "Yes.\n" +have_zlib=1 +zlib_cflags=$(pkg-config --cflags zlib) +zlib_ldflags=$(pkg-config --libs zlib) +else +printf "No.\n" +errors=$((errors + 1)) +fi + printf "Checking for talloc development files... " if pkg-config --exists talloc; then printf "Yes.\n" @@ -496,6 +508,11 @@ EOF echo " Xapian library (including development files such as headers)" echo " http://xapian.org/"; fi +if [ $have_zlib -eq 0 ]; then + echo " zlib library (>= version 1.2.5.2, including development files such as headers)" + echo " http://zlib.net/"; + echo +fi if [ $have_gmime -eq 0 ]; then echo " Either GMime 2.4 library" $GMIME_24_VERSION_CTR "or GMime 2.6 library" $GMIME_26_VERSION_CTR echo " (including development files such as headers)" @@ -519,11 +536,11 @@ case a simple command will install everything you need. For example: On Debian and similar systems: - sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev + sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev zlib1g-dev Or on Fedora and similar systems: - sudo yum install xapian-core-devel gmime-devel libtalloc-devel + sudo yum install xapian-core-devel gmime-devel libtalloc-devel zlib-devel On other systems, similar commands can be used, but the details of the package names may be different. @@ -844,6 +861,10 @@ XAPIAN_LDFLAGS = ${xapian_ldflags} GMIME_
v7 gzip dump restore patches
Supercedes id:1396554083-3892-2-git-send-email-david at tethera.net - adds new analogues of strerror - util_error_string - gz_error_string Interdiff: diff --git a/configure b/configure index 1d624f7..83b4af7 100755 --- a/configure +++ b/configure @@ -509,7 +509,7 @@ EOF echo " http://xapian.org/"; fi if [ $have_zlib -eq 0 ]; then - echo " zlib library (including development files such as headers)" + echo " zlib library (>= version 1.2.5.2, including development files such as headers)" echo " http://zlib.net/"; echo fi diff --git a/notmuch-dump.c b/notmuch-dump.c index 2a7252a..2849eab 100644 --- a/notmuch-dump.c +++ b/notmuch-dump.c @@ -127,7 +127,7 @@ notmuch_database_dump (notmuch_database_t *notmuch, dump_format_t output_format, notmuch_bool_t gzip_output) { -gzFile output; +gzFile output = NULL; const char *mode = gzip_output ? "w9" : "wT"; const char *name_for_error = output_file_name ? output_file_name : "stdout"; @@ -178,7 +178,10 @@ notmuch_database_dump (notmuch_database_t *notmuch, } if (gzclose_w (output) != Z_OK) { + fprintf (stderr, "Error closing %s: %s\n", name_for_error, +gzerror (output, NULL)); ret = EXIT_FAILURE; + output = NULL; goto DONE; } @@ -192,6 +195,9 @@ notmuch_database_dump (notmuch_database_t *notmuch, } DONE: +if (ret != EXIT_SUCCESS && output) + (void) gzclose_w (output); + if (ret != EXIT_SUCCESS && output_file_name) (void) unlink (tempname); diff --git a/notmuch-restore.c b/notmuch-restore.c index eb5b7b2..7abee0a 100644 --- a/notmuch-restore.c +++ b/notmuch-restore.c @@ -129,7 +129,8 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) tag_op_list_t *tag_ops; char *input_file_name = NULL; -gzFile input; +const char *name_for_error = NULL; +gzFile input = NULL; char *line = NULL; void *line_ctx = NULL; ssize_t line_len; @@ -157,19 +158,26 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) }; opt_index = parse_arguments (argc, argv, options, 1); -if (opt_index < 0) - return EXIT_FAILURE; +if (opt_index < 0) { + ret = EXIT_FAILURE; + goto DONE; +} + +name_for_error = input_file_name ? input_file_name : "stdin"; if (! accumulate) flags |= TAG_FLAG_REMOVE_ALL; +errno = 0; if (input_file_name) input = gzopen (input_file_name, "r"); else { int infd = dup (STDIN_FILENO); if (infd < 0) { - fprintf (stderr, "Error duping stdin\n"); - return EXIT_FAILURE; + fprintf (stderr, "Error duping stdin: %s\n", +strerror (errno)); + ret = EXIT_FAILURE; + goto DONE; } input = gzdopen (infd, "r"); if (! input) @@ -178,19 +186,22 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) if (input == NULL) { fprintf (stderr, "Error opening %s for (gzip) reading: %s\n", -input_file_name ? input_file_name : "stdin", strerror (errno)); - return EXIT_FAILURE; +name_for_error, strerror (errno)); + ret = EXIT_FAILURE; + goto DONE; } if (opt_index < argc) { fprintf (stderr, "Unused positional parameter: %s\n", argv[opt_index]); - return EXIT_FAILURE; + ret = EXIT_FAILURE; + goto DONE; } tag_ops = tag_op_list_create (config); if (tag_ops == NULL) { fprintf (stderr, "Out of memory.\n"); - return EXIT_FAILURE; + ret = EXIT_FAILURE; + goto DONE; } do { @@ -199,12 +210,17 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) status = gz_getline (line_ctx, &line, &line_len, input); /* empty input file not considered an error */ - if (status == UTIL_EOF) - return EXIT_SUCCESS; - - if (status) - return EXIT_FAILURE; + if (status == UTIL_EOF) { + ret = EXIT_SUCCESS; + goto DONE; + } + if (status) { + fprintf (stderr, "Error reading (gzipped) input: %s\n", +gz_error_string(status, input)); + ret = EXIT_FAILURE; + goto DONE; + } } while ((line_len == 0) || (line[0] == '#') || /* the cast is safe because we checked about for line_len < 0 */ @@ -269,17 +285,37 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) if (ret) break; -} while (gz_getline (line_ctx, &line, &line_len, input) == UTIL_SUCCESS); +} while (! (ret = gz_getline (line_ctx, &line, &line_len, input))); + -if (line_ctx != NULL) - talloc_free (line_ctx); +/* EOF is normal loop termination condition, UTIL_SUC
Feature suggestion. Indexing encrypted mail?
Off the top of my head, you could have an encrypted index too, which you can only search while able to decrypt. Certainly another level of complexity. On Sat, Apr 5, 2014 at 11:10 AM, David Bremner wrote: > john.wyzer at gmx.de writes: > > > Would it be possible to add the configurable option to also decrypt > > encrypted messages on the fly while indexing to make them searchable, > > too? > > > > That would be really great for people that consider gnupg mainly an > > encryption for transport or have their complete hard drive encrypted... > > As far I understand an attacker could reconstruct the message from the > index, so one question is whether the extra complexity in notmuch is > worth the minimal extra security over decrypting on delivery and storing > plaintext on the (presumably encrypted) disk. Of course decrypting on > delivery may be inconvenient (or impossible). I have CCed the two people > who have implemented most of the crypto related stuff in notmuch so they > can comment. > > d > ___ > notmuch mailing list > notmuch at notmuchmail.org > http://notmuchmail.org/mailman/listinfo/notmuch > -- next part -- An HTML attachment was scrubbed... URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20140405/4cbd66bf/attachment-0001.html>
[PATCH 5/7] doc: Allow rst2man.py as an alternative to rst2man
On Sat, Apr 05, 2014 at 10:05:31PM +0300, Tomi Ollila wrote: > On Sat, Apr 05 2014, W. Trevor King wrote: > > I use POSIX's 'command -v' [1] to find the path to rst2man? > > > > [1]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/command.html > > ? > Except the reference to _POSIX_ page. One knows how consistent these > specifications are; alternative: > > http://pubs.opengroup.org/onlinepubs/009695399/utilities/command.html > > mentions additionally that -v flag > "(On systems supporting the User Portability Utilities option.)" It's been a decade since POSIX 2004 ;). I'm not sure when the ?User Portability Utilities? caveat was removed, but I imagine most POSIX-aspiring shells have -v support. Short of citing POSIX 2013, I think I'd have to survey likely shells, and that seems even less reliable. Maybe I'm missunderstanding your suggested change? > Also, we don't give such a treatment to other command either; I'd rather > see RST2MAN=rst2man, RST2MAN=rst2man.py *and* RST2MAN= lines used > instead -- the last to set RST2MAN to empty string instead of being unset. I'm fine with that. Alternatively, we could add an: if -n "${RST2MAN}" clause to the front of the detection code to allow users with oddball scripts (maybe a null set) to override RST2MAN at configure time: $ RST2MAN=/my/custom/rst_to_man_converter ./configure $ make instead of at make-invocation time: $ ./configure $ make RST2MAN=/my/custom/rst_to_man_converter That would consolidate configuration around the 'config' call, and make explicitly emptying the RST2MAN variable more clearly superfluous (although I'm still fine with an explicit empty). Thoughts? Trevor -- This email may be signed or encrypted with GnuPG (http://www.gnupg.org). For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy -- next part -- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: OpenPGP digital signature URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20140405/2de77e22/attachment.pgp>
[PATCH] emacs: sign/encrypt replies to signed/encrypted messages
This is a simple approach to improving security when replying to signed or encrypted messages. If the message being replied to was signed, add mml tag to sign the reply. If the message being replied to was encrypted, add mml tag to sign and encrypt the reply. This may need configuration; I for one might want to encrypt replies to encrypted messages, but not always sign replies to signed messages. This still includes a slight bug: if any mml tags are added, they are included in the region containing the quoted parts. Killing the region will kill the mml tags too. --- emacs/notmuch-mua.el | 14 +- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el index ba3ef275ec5e..9fb84b57b030 100644 --- a/emacs/notmuch-mua.el +++ b/emacs/notmuch-mua.el @@ -115,6 +115,15 @@ list." (push header message-hidden-headers))) notmuch-mua-hidden-headers)) +(defun notmuch-mua-reply-crypto (parts) + (loop for part in parts + if (notmuch-match-content-type (plist-get part :content-type) "multipart/signed") + do (mml-secure-message-sign) + else if (notmuch-match-content-type (plist-get part :content-type) "multipart/encrypted") + do (mml-secure-message-sign-encrypt) + else if (notmuch-match-content-type (plist-get part :content-type) "multipart/*") + do (notmuch-mua-reply-crypto (plist-get part :content + (defun notmuch-mua-get-quotable-parts (parts) (loop for part in parts if (notmuch-match-content-type (plist-get part :content-type) "multipart/alternative") @@ -224,7 +233,10 @@ list." (set-mark (point)) (goto-char start) ;; Quote the original message according to the user's configured style. - (message-cite-original + (message-cite-original))) + +;; Sign and/or encrypt replies to signed and/or encrypted messages. +(notmuch-mua-reply-crypto (plist-get original :body))) ;; Push mark right before signature, if any. (message-goto-signature) -- 1.9.1
Re: Feature suggestion. Indexing encrypted mail?
On Sat, Apr 05 2014, David Bremner wrote: > john.wy...@gmx.de writes: > >> Would it be possible to add the configurable option to also decrypt >> encrypted messages on the fly while indexing to make them searchable, >> too? >> >> That would be really great for people that consider gnupg mainly an >> encryption for transport or have their complete hard drive encrypted... > > As far I understand an attacker could reconstruct the message from the > index, so one question is whether the extra complexity in notmuch is > worth the minimal extra security over decrypting on delivery and storing > plaintext on the (presumably encrypted) disk. Of course decrypting on > delivery may be inconvenient (or impossible). I have CCed the two people > who have implemented most of the crypto related stuff in notmuch so they > can comment. Indexing encrypted email is a bit of a foot-gun, since, as David mentions, it is apparently possible to reconstruct encrypted messages From the index. It therefore needs to be approached with care. I think decrypting on "delivery" (or mail fetch or whatever) sounds difficult and unwieldy. In either event, it seems out of the scope of notmuch. If a user figured out how to have that done, no changes to notmuch would be needed afaict. I don't think it would be difficult modify notmuch new to decrypt at indexing time. Given that gnupg agent would be used for accessing the users private key for decryption, the interface would be fairly straightforward. A couple of decryption options could be added to notmuch new: * don't decrypt: don't attempt to decrypt and index any encrypted message (default) * decrypt always: fail if any encrypted message could not be decrypted * decrypt opportunistically: attempt to decrypt, but continue indexing if an encrypted message could not be decrypted If something like this is enabled, we should make sure we make the dangers clear to the users. jamie. pgpBorqLfuOX2.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Feature suggestion. Indexing encrypted mail?
On Sat, Apr 05 2014, David Bremner wrote: > john.wyzer at gmx.de writes: > >> Would it be possible to add the configurable option to also decrypt >> encrypted messages on the fly while indexing to make them searchable, >> too? >> >> That would be really great for people that consider gnupg mainly an >> encryption for transport or have their complete hard drive encrypted... > > As far I understand an attacker could reconstruct the message from the > index, so one question is whether the extra complexity in notmuch is > worth the minimal extra security over decrypting on delivery and storing > plaintext on the (presumably encrypted) disk. Of course decrypting on > delivery may be inconvenient (or impossible). I have CCed the two people > who have implemented most of the crypto related stuff in notmuch so they > can comment. Indexing encrypted email is a bit of a foot-gun, since, as David mentions, it is apparently possible to reconstruct encrypted messages
Re: Feature suggestion. Indexing encrypted mail?
Jeremy Nickurak writes: > Off the top of my head, you could have an encrypted index too, which you > can only search while able to decrypt. Certainly another level of > complexity. > But why add so much complexity? If a user decides that either transport security is enough or additionally the hard disk is encrypted (why store an encrypted index on an encrypted hard disk?), said user could just switch on an option in the notmuch configuration that causes notmuch to ask for the password before or while indexing new messages and to add decrypted messages to the normal index as well. The level of security would be up to the user by means of said configuration option and those that want the convenience of searching encrypted messages could have it. Personally I would argue that if an attacker has the means to access the content of my hard disk either via the network or physically, there is no difference between having whole disk encryption and storing an encrypted index... ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: Feature suggestion. Indexing encrypted mail?
Off the top of my head, you could have an encrypted index too, which you can only search while able to decrypt. Certainly another level of complexity. On Sat, Apr 5, 2014 at 11:10 AM, David Bremner wrote: > john.wy...@gmx.de writes: > > > Would it be possible to add the configurable option to also decrypt > > encrypted messages on the fly while indexing to make them searchable, > > too? > > > > That would be really great for people that consider gnupg mainly an > > encryption for transport or have their complete hard drive encrypted... > > As far I understand an attacker could reconstruct the message from the > index, so one question is whether the extra complexity in notmuch is > worth the minimal extra security over decrypting on delivery and storing > plaintext on the (presumably encrypted) disk. Of course decrypting on > delivery may be inconvenient (or impossible). I have CCed the two people > who have implemented most of the crypto related stuff in notmuch so they > can comment. > > d > ___ > notmuch mailing list > notmuch@notmuchmail.org > http://notmuchmail.org/mailman/listinfo/notmuch > ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v5 1/2] lib: drop support for single-message mbox files
On Sat, Apr 05 2014, David Bremner wrote: > Jani Nikula writes: > >> We've supported mbox files containing a single message for historical >> reasons, but the support has been deprecated, with a warning message >> while indexing, since Notmuch 0.15. Finally drop the support, and >> consider all mbox files non-email. > > series pushed. For now, anyone who wants to check their mail storage whether this have any effect: $ find . -type f | xargs head -1 | grep -B1 '^From ' (I got zero results :D on this machine; have to test on another...) Quickly crafted other test: regexp (and head -1) may be incomplete... $ find . -type f | xargs head -1 | grep -B1 -v -e '^[a-zA-Z_-]*:' -e '==.*==' -e '^$' The first one will find any emails that were found last time but would not be found (as emails) after e.g. dump-restore-reindex. Second one would find (some/most?) emails that weren't indexed in the first place... > d Tomi ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 3/7] doc/prerst2man.py: Use Python-3-compatible octal notation
Python 3 only supports the 0oXXX notation for octal literals [1,2], which have also been supported in 2.x since 2.6 [2]. [1]: https://docs.python.org/3.0/whatsnew/3.0.html#integers [2]: http://legacy.python.org/dev/peps/pep-3127/ --- doc/prerst2man.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/prerst2man.py b/doc/prerst2man.py index 4591264..108f4a3 100644 --- a/doc/prerst2man.py +++ b/doc/prerst2man.py @@ -8,7 +8,7 @@ sourcedir = argv[1] outdir = argv[2] if not isdir(outdir): -makedirs(outdir, 0755) +makedirs(outdir, 0o755) execfile(sourcedir + "/conf.py") @@ -34,7 +34,7 @@ blankre = re.compile("^\s*$") for page in man_pages: outdirname = outdir + '/' + dirname(page[0]) if not isdir(outdirname): -makedirs(outdirname, 0755) +makedirs(outdirname, 0o755) filename = outdir + '/' + page[0] + '.rst' outfile = open(filename, 'w') infile = open(sourcedir + '/' + page[0] + '.rst', 'r') -- 1.9.1.353.gc66d89d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 6/7] doc/prerst2man.py: Convert execfile to import
excefile is gone in Python 3 [1]. Instead of exec-ing the configuration, it's easier to insert the source directory in Python's path [2], and just import the configuration. With this change, prerst2man.py is compatible with both Python 2 and 3. [1]: https://docs.python.org/3.0/whatsnew/3.0.html#builtins [2]: https://docs.python.org/3/library/sys.html#sys.path --- doc/prerst2man.py | 18 ++ 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/doc/prerst2man.py b/doc/prerst2man.py index 81ce817..7d78e9b 100644 --- a/doc/prerst2man.py +++ b/doc/prerst2man.py @@ -1,18 +1,20 @@ -from sys import argv +import sys from datetime import date from os.path import dirname, isdir from os import makedirs, system import re -rst2man = argv[1] -sourcedir = argv[2] -outdir = argv[3] +rst2man = sys.argv[1] +sourcedir = sys.argv[2] +outdir = sys.argv[3] + +sys.path.insert(0, sourcedir) +import conf + if not isdir(outdir): makedirs(outdir, 0o755) -execfile(sourcedir + "/conf.py") - def header(file, startdocname, command, description, authors, section): file.write(""" @@ -29,10 +31,10 @@ def header(file, startdocname, command, description, authors, section): '-' * len(description), description, '-' * len(description), -date.today().isoformat(), release, section, project)) +date.today().isoformat(), conf.release, section, conf.project)) blankre = re.compile("^\s*$") -for page in man_pages: +for page in conf.man_pages: outdirname = outdir + '/' + dirname(page[0]) if not isdir(outdirname): makedirs(outdirname, 0o755) -- 1.9.1.353.gc66d89d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 7/7] doc/INSTALL: Remove rst2man reference and other updates
The rst2man target was removed in 9d9a700 (doc: build man pages at build time; introduce HAVE_SPHINX, HAVE_RST2MAN, 2014-03-13), but a reference in the install docs slipped through. While I was removing that reference, I also: * Converted doc/INSTALL to reStructuredText, so I can link to Sphinx and Docutils directly. Not everyone has access to Debian's python-docutils, so it's better to be genric here. * Converted from an unordered list to paragraphs, because I think it flows better. * Dropped the rst2man no-automatic-install caveat. I don't think this applies to the current code, although I haven't tried to track down a commit that adds the automatic-install support. Anyhow, $ make HAVE_SPHINX=0 RST2MAN=/usr/bin/rst2man.py DESTDIR=/tmp/ install-man works for me. --- doc/INSTALL | 34 -- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/doc/INSTALL b/doc/INSTALL index e37c2b9..91222f9 100644 --- a/doc/INSTALL +++ b/doc/INSTALL @@ -1,24 +1,30 @@ This file contains some more detailed information about building and installing the documentation. -Building with sphinx. -- +Building with Sphinx + -- You need sphinx at least version 1.0. +With Sphinx_ version 1.0 or greater, you can build man, info, html, +and pdf versions of the docs (currently only the man pages) with:: -- You can build build and install man pages with 'make install-man' + make build-{man|info|html|pdf} -- You can build man, info, html, and pdf versions of the docs - (currently only the man pages) with +You can build build and install the docs (currently only the man +pages) with:: - 'make install-{man|info|html|pdf}' + make install-{man|info|html|pdf} -Building the man pages --- +Building the man Docutils +- -- You can build the man pages with rst2man (from python-docutils) with - 'make rst2man'. +If you don't have Sphinx installed, you can still build the man-page +version of the docs using rst2man (from Docutils_):: -- Currently there is no support to automagically install the resulting - nroff files, but it should work to modify the target install-man - in doc/Makefile.local. + make build-man + +and install with:: + + make install-man + +.. _Sphinx: http://sphinx-doc.org/ +.. _Docutils: http://docutils.sourceforge.net/ -- 1.9.1.353.gc66d89d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 2/7] doc/mkdocdeps.py: Use "with" statement for the output file
Before this patch, the open was unnecessarily early and relied on the process cleanup to close. Neither one of these was a real problem, but PEP 343's context managers (which landed in Python 2.5) make proper cleanup very easy. [1]: http://legacy.python.org/dev/peps/pep-0343/ --- doc/mkdocdeps.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/mkdocdeps.py b/doc/mkdocdeps.py index de1cbb8..b87fe3e 100644 --- a/doc/mkdocdeps.py +++ b/doc/mkdocdeps.py @@ -9,10 +9,10 @@ import conf roff_files = [] rst_files = [] -out=open(outfile,'w') for page in conf.man_pages: rst_files = rst_files + ["{0:s}/{1:s}.rst".format(srcdir,page[0])] roff_files = roff_files + ["{0:s}/man/{1:s}.{2:d}".format(builddir,page[0],page[4])] -out.write ('MAN_ROFF_FILES := ' + ' \\\n\t'.join(roff_files)+'\n') -out.write ('MAN_RST_FILES := ' + ' \\\n\t'.join(rst_files)+'\n') +with open(outfile, 'w') as out: +out.write('MAN_ROFF_FILES := ' + ' \\\n\t'.join(roff_files) + '\n') +out.write('MAN_RST_FILES := ' + ' \\\n\t'.join(rst_files) + '\n') -- 1.9.1.353.gc66d89d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 4/7] doc/prerst2man.py: Fix 'os.system' -> 'system' typo
Avoid: $ make HAVE_SPHINX=0 HAVE_RST2MAN=1 build-man python ./doc/prerst2man.py ./doc doc/_build/man Traceback (most recent call last): File "./doc/prerst2man.py", line 65, in os.system('set -x; rst2man {0} {1}/{2}.{3}' NameError: name 'os' is not defined make: *** [doc/_build/man/man1/notmuch.1] Error 1 by using system directly. We don't need the 'os.' namespacing, because the function was imported with: from os import makedirs, system --- doc/prerst2man.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/prerst2man.py b/doc/prerst2man.py index 108f4a3..437dea9 100644 --- a/doc/prerst2man.py +++ b/doc/prerst2man.py @@ -59,5 +59,5 @@ for page in man_pages: outfile.write("".join(lines)) outfile.close() -os.system('set -x; rst2man {0} {1}/{2}.{3}' - .format(filename, outdir, page[0],page[4])) +system('set -x; rst2man {0} {1}/{2}.{3}' + .format(filename, outdir, page[0], page[4])) -- 1.9.1.353.gc66d89d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 0/7] doc: Python 3 compat, rst2man.py support, etc.
I just bumped into this today while testing v2 of my content-description series: $ ./configure … $ make … python ./doc/mkdocdeps.py ./doc doc/_build doc/docdeps.mk Traceback (most recent call last): File "./doc/mkdocdeps.py", line 6, in execfile(srcdir + '/conf.py') NameError: name 'execfile' is not defined … The first patch in this series fixes that issue, and the rest of the series fixes some other issues I bumped into while working on that. Sorry I missed these in the initial series. Note that while mkdocdeps.py and prerst2man.py are now Python 3 compatible (with this series), the build will fail for Python's 3.0 through 3.2 because of the explicit unicode literals in conf.py [1]. It's likely that conf.py could use [2] from __future__ import unicode_literals drop the u'' prefixes, and be compatible with all Python's ≥2.6 (including all 3s). I haven't checked the logic though, and I'm not running 3.2 locally anymore, so it's not a big priority for me. Cheers, Trevor [1]: https://docs.python.org/3/whatsnew/3.3.html#pep-414-explicit-unicode-literals [2]: from __future__ import unicode_literals W. Trevor King (7): doc/mkdocdeps.py: Convert execfile to import doc/mkdocdeps.py: Use "with" statement for the output file doc/prerst2man.py: Use Python-3-compatible octal notation doc/prerst2man.py: Fix 'os.system' -> 'system' typo doc: Allow rst2man.py as an alternative to rst2man doc/prerst2man.py: Convert execfile to import doc/INSTALL: Remove rst2man reference and other updates configure | 12 +++- doc/INSTALL| 34 -- doc/Makefile.local | 6 +++--- doc/mkdocdeps.py | 19 ++- doc/prerst2man.py | 25 ++--- 5 files changed, 54 insertions(+), 42 deletions(-) -- 1.9.1.353.gc66d89d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 1/7] doc/mkdocdeps.py: Convert execfile to import
excefile is gone in Python 3 [1]. Instead of exec-ing the configuration, it's easier to insert the source directory in Python's path [2], and just import the configuration. With this change, mkdocdeps.py is compatible with both Python 2 and 3. [1]: https://docs.python.org/3.0/whatsnew/3.0.html#builtins [2]: https://docs.python.org/3/library/sys.html#sys.path --- doc/mkdocdeps.py | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/mkdocdeps.py b/doc/mkdocdeps.py index 71bd135..de1cbb8 100644 --- a/doc/mkdocdeps.py +++ b/doc/mkdocdeps.py @@ -1,15 +1,16 @@ -from sys import argv -srcdir = argv[1] -builddir = argv[2] -outfile = argv[3] +import sys -execfile(srcdir + '/conf.py') +srcdir = sys.argv[1] +builddir = sys.argv[2] +outfile = sys.argv[3] +sys.path.insert(0, srcdir) +import conf roff_files = [] rst_files = [] out=open(outfile,'w') -for page in man_pages: +for page in conf.man_pages: rst_files = rst_files + ["{0:s}/{1:s}.rst".format(srcdir,page[0])] roff_files = roff_files + ["{0:s}/man/{1:s}.{2:d}".format(builddir,page[0],page[4])] -- 1.9.1.353.gc66d89d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 7/7] doc/INSTALL: Remove rst2man reference and other updates
The rst2man target was removed in 9d9a700 (doc: build man pages at build time; introduce HAVE_SPHINX, HAVE_RST2MAN, 2014-03-13), but a reference in the install docs slipped through. While I was removing that reference, I also: * Converted doc/INSTALL to reStructuredText, so I can link to Sphinx and Docutils directly. Not everyone has access to Debian's python-docutils, so it's better to be genric here. * Converted from an unordered list to paragraphs, because I think it flows better. * Dropped the rst2man no-automatic-install caveat. I don't think this applies to the current code, although I haven't tried to track down a commit that adds the automatic-install support. Anyhow, $ make HAVE_SPHINX=0 RST2MAN=/usr/bin/rst2man.py DESTDIR=/tmp/ install-man works for me. --- doc/INSTALL | 34 -- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/doc/INSTALL b/doc/INSTALL index e37c2b9..91222f9 100644 --- a/doc/INSTALL +++ b/doc/INSTALL @@ -1,24 +1,30 @@ This file contains some more detailed information about building and installing the documentation. -Building with sphinx. -- +Building with Sphinx + -- You need sphinx at least version 1.0. +With Sphinx_ version 1.0 or greater, you can build man, info, html, +and pdf versions of the docs (currently only the man pages) with:: -- You can build build and install man pages with 'make install-man' + make build-{man|info|html|pdf} -- You can build man, info, html, and pdf versions of the docs - (currently only the man pages) with +You can build build and install the docs (currently only the man +pages) with:: - 'make install-{man|info|html|pdf}' + make install-{man|info|html|pdf} -Building the man pages --- +Building the man Docutils +- -- You can build the man pages with rst2man (from python-docutils) with - 'make rst2man'. +If you don't have Sphinx installed, you can still build the man-page +version of the docs using rst2man (from Docutils_):: -- Currently there is no support to automagically install the resulting - nroff files, but it should work to modify the target install-man - in doc/Makefile.local. + make build-man + +and install with:: + + make install-man + +.. _Sphinx: http://sphinx-doc.org/ +.. _Docutils: http://docutils.sourceforge.net/ -- 1.9.1.353.gc66d89d
[PATCH 6/7] doc/prerst2man.py: Convert execfile to import
excefile is gone in Python 3 [1]. Instead of exec-ing the configuration, it's easier to insert the source directory in Python's path [2], and just import the configuration. With this change, prerst2man.py is compatible with both Python 2 and 3. [1]: https://docs.python.org/3.0/whatsnew/3.0.html#builtins [2]: https://docs.python.org/3/library/sys.html#sys.path --- doc/prerst2man.py | 18 ++ 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/doc/prerst2man.py b/doc/prerst2man.py index 81ce817..7d78e9b 100644 --- a/doc/prerst2man.py +++ b/doc/prerst2man.py @@ -1,18 +1,20 @@ -from sys import argv +import sys from datetime import date from os.path import dirname, isdir from os import makedirs, system import re -rst2man = argv[1] -sourcedir = argv[2] -outdir = argv[3] +rst2man = sys.argv[1] +sourcedir = sys.argv[2] +outdir = sys.argv[3] + +sys.path.insert(0, sourcedir) +import conf + if not isdir(outdir): makedirs(outdir, 0o755) -execfile(sourcedir + "/conf.py") - def header(file, startdocname, command, description, authors, section): file.write(""" @@ -29,10 +31,10 @@ def header(file, startdocname, command, description, authors, section): '-' * len(description), description, '-' * len(description), -date.today().isoformat(), release, section, project)) +date.today().isoformat(), conf.release, section, conf.project)) blankre = re.compile("^\s*$") -for page in man_pages: +for page in conf.man_pages: outdirname = outdir + '/' + dirname(page[0]) if not isdir(outdirname): makedirs(outdirname, 0o755) -- 1.9.1.353.gc66d89d
[PATCH 5/7] doc: Allow rst2man.py as an alternative to rst2man
Gentoo's dev-python/docutils-0.10 installs Docutils scripts with a *.py extension, so I have /usr/bin/rst2man.py and no rst2man script. This patch supports users with both types of systems by checking for rst2man, falling back on rst2man.py, and giving up only if neither is found. Users can also set the new RST2MAN path variable explicitly when they call Make: make RST2MAN=/my/custom/rst_to_man_converter build-man I use POSIX's 'command -v' [1] to find the path to rst2man or rst2man.py, and save that as RST2MAN in Makefile.config. We can use a non-empty RST2MAN to check for the availability of an rst2man program, so there's no need for a separate HAVE_RST2MAN. Then pass the configured RST2MAN path through to prerst2man.py to use in its system call. [1]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/command.html --- configure | 12 +++- doc/Makefile.local | 6 +++--- doc/prerst2man.py | 9 + 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/configure b/configure index 1d430b9..81c286b 100755 --- a/configure +++ b/configure @@ -400,7 +400,6 @@ printf "Checking if sphinx is available and supports nroff output... " if hash sphinx-build > /dev/null 2>&1 && python -m sphinx.writers.manpage > /dev/null 2>&1 ; then printf "Yes.\n" have_sphinx=1 -have_rst2man=0 else printf "No (falling back to rst2man).\n" have_sphinx=0 @@ -408,10 +407,12 @@ else printf "Checking if rst2man is available... " if rst2man -V > /dev/null 2>&1; then printf "Yes.\n" - have_rst2man=1 + RST2MAN=$(command -v rst2man) +elif rst2man.py -V > /dev/null 2>&1; then + printf "Yes.\n" + RST2MAN=$(command -v rst2man.py) else printf "No (so will not install man pages).\n" - have_rst2man=0 fi fi @@ -788,8 +789,9 @@ HAVE_EMACS = ${have_emacs} # Whether there's a sphinx-build binary available for building documentation HAVE_SPHINX=${have_sphinx} -# Whether there's a rst2man binary available for building documentation -HAVE_RST2MAN=${have_rst2man} +# The path to the rst2man program for building documentation. Set to +# an empty string if no such program is available. +RST2MAN=${RST2MAN} # The directory to which desktop files should be installed desktop_dir = \$(prefix)/share/applications diff --git a/doc/Makefile.local b/doc/Makefile.local index 0980c71..e08fc99 100644 --- a/doc/Makefile.local +++ b/doc/Makefile.local @@ -42,8 +42,8 @@ ifeq ($(HAVE_SPHINX),1) mkdir -p $(DOCBUILDDIR)/man/man$${section}; \ mv $(DOCBUILDDIR)/man/*.$${section} $(DOCBUILDDIR)/man/man$${section}; \ done -else ifeq ($(HAVE_RST2MAN),1) - $(prerst2man) $(srcdir)/doc $(DOCBUILDDIR)/man +else ifdef RST2MAN + $(prerst2man) "$(RST2MAN)" $(srcdir)/doc $(DOCBUILDDIR)/man else @echo "Fatal: build dependency fail." @false @@ -51,7 +51,7 @@ endif # Do not try to build or install man pages if a man page converter is # not available. -ifeq ($(HAVE_SPHINX)$(HAVE_RST2MAN),00) +ifeq ($(HAVE_SPHINX)$(RST2MAN),0) build-man: install-man: @echo "No sphinx or rst2man, will not install man pages." diff --git a/doc/prerst2man.py b/doc/prerst2man.py index 437dea9..81ce817 100644 --- a/doc/prerst2man.py +++ b/doc/prerst2man.py @@ -4,8 +4,9 @@ from os.path import dirname, isdir from os import makedirs, system import re -sourcedir = argv[1] -outdir = argv[2] +rst2man = argv[1] +sourcedir = argv[2] +outdir = argv[3] if not isdir(outdir): makedirs(outdir, 0o755) @@ -59,5 +60,5 @@ for page in man_pages: outfile.write("".join(lines)) outfile.close() -system('set -x; rst2man {0} {1}/{2}.{3}' - .format(filename, outdir, page[0], page[4])) +system('set -x; {0} {1} {2}/{3}.{4}' + .format(rst2man, filename, outdir, page[0], page[4])) -- 1.9.1.353.gc66d89d
[PATCH 4/7] doc/prerst2man.py: Fix 'os.system' -> 'system' typo
Avoid: $ make HAVE_SPHINX=0 HAVE_RST2MAN=1 build-man python ./doc/prerst2man.py ./doc doc/_build/man Traceback (most recent call last): File "./doc/prerst2man.py", line 65, in os.system('set -x; rst2man {0} {1}/{2}.{3}' NameError: name 'os' is not defined make: *** [doc/_build/man/man1/notmuch.1] Error 1 by using system directly. We don't need the 'os.' namespacing, because the function was imported with: from os import makedirs, system --- doc/prerst2man.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/prerst2man.py b/doc/prerst2man.py index 108f4a3..437dea9 100644 --- a/doc/prerst2man.py +++ b/doc/prerst2man.py @@ -59,5 +59,5 @@ for page in man_pages: outfile.write("".join(lines)) outfile.close() -os.system('set -x; rst2man {0} {1}/{2}.{3}' - .format(filename, outdir, page[0],page[4])) +system('set -x; rst2man {0} {1}/{2}.{3}' + .format(filename, outdir, page[0], page[4])) -- 1.9.1.353.gc66d89d
[PATCH 3/7] doc/prerst2man.py: Use Python-3-compatible octal notation
Python 3 only supports the 0oXXX notation for octal literals [1,2], which have also been supported in 2.x since 2.6 [2]. [1]: https://docs.python.org/3.0/whatsnew/3.0.html#integers [2]: http://legacy.python.org/dev/peps/pep-3127/ --- doc/prerst2man.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/prerst2man.py b/doc/prerst2man.py index 4591264..108f4a3 100644 --- a/doc/prerst2man.py +++ b/doc/prerst2man.py @@ -8,7 +8,7 @@ sourcedir = argv[1] outdir = argv[2] if not isdir(outdir): -makedirs(outdir, 0755) +makedirs(outdir, 0o755) execfile(sourcedir + "/conf.py") @@ -34,7 +34,7 @@ blankre = re.compile("^\s*$") for page in man_pages: outdirname = outdir + '/' + dirname(page[0]) if not isdir(outdirname): -makedirs(outdirname, 0755) +makedirs(outdirname, 0o755) filename = outdir + '/' + page[0] + '.rst' outfile = open(filename, 'w') infile = open(sourcedir + '/' + page[0] + '.rst', 'r') -- 1.9.1.353.gc66d89d
[PATCH 2/7] doc/mkdocdeps.py: Use "with" statement for the output file
Before this patch, the open was unnecessarily early and relied on the process cleanup to close. Neither one of these was a real problem, but PEP 343's context managers (which landed in Python 2.5) make proper cleanup very easy. [1]: http://legacy.python.org/dev/peps/pep-0343/ --- doc/mkdocdeps.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/mkdocdeps.py b/doc/mkdocdeps.py index de1cbb8..b87fe3e 100644 --- a/doc/mkdocdeps.py +++ b/doc/mkdocdeps.py @@ -9,10 +9,10 @@ import conf roff_files = [] rst_files = [] -out=open(outfile,'w') for page in conf.man_pages: rst_files = rst_files + ["{0:s}/{1:s}.rst".format(srcdir,page[0])] roff_files = roff_files + ["{0:s}/man/{1:s}.{2:d}".format(builddir,page[0],page[4])] -out.write ('MAN_ROFF_FILES := ' + ' \\\n\t'.join(roff_files)+'\n') -out.write ('MAN_RST_FILES := ' + ' \\\n\t'.join(rst_files)+'\n') +with open(outfile, 'w') as out: +out.write('MAN_ROFF_FILES := ' + ' \\\n\t'.join(roff_files) + '\n') +out.write('MAN_RST_FILES := ' + ' \\\n\t'.join(rst_files) + '\n') -- 1.9.1.353.gc66d89d
[PATCH 1/7] doc/mkdocdeps.py: Convert execfile to import
excefile is gone in Python 3 [1]. Instead of exec-ing the configuration, it's easier to insert the source directory in Python's path [2], and just import the configuration. With this change, mkdocdeps.py is compatible with both Python 2 and 3. [1]: https://docs.python.org/3.0/whatsnew/3.0.html#builtins [2]: https://docs.python.org/3/library/sys.html#sys.path --- doc/mkdocdeps.py | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/mkdocdeps.py b/doc/mkdocdeps.py index 71bd135..de1cbb8 100644 --- a/doc/mkdocdeps.py +++ b/doc/mkdocdeps.py @@ -1,15 +1,16 @@ -from sys import argv -srcdir = argv[1] -builddir = argv[2] -outfile = argv[3] +import sys -execfile(srcdir + '/conf.py') +srcdir = sys.argv[1] +builddir = sys.argv[2] +outfile = sys.argv[3] +sys.path.insert(0, srcdir) +import conf roff_files = [] rst_files = [] out=open(outfile,'w') -for page in man_pages: +for page in conf.man_pages: rst_files = rst_files + ["{0:s}/{1:s}.rst".format(srcdir,page[0])] roff_files = roff_files + ["{0:s}/man/{1:s}.{2:d}".format(builddir,page[0],page[4])] -- 1.9.1.353.gc66d89d
[PATCH 0/7] doc: Python 3 compat, rst2man.py support, etc.
I just bumped into this today while testing v2 of my content-description series: $ ./configure ? $ make ? python ./doc/mkdocdeps.py ./doc doc/_build doc/docdeps.mk Traceback (most recent call last): File "./doc/mkdocdeps.py", line 6, in execfile(srcdir + '/conf.py') NameError: name 'execfile' is not defined ? The first patch in this series fixes that issue, and the rest of the series fixes some other issues I bumped into while working on that. Sorry I missed these in the initial series. Note that while mkdocdeps.py and prerst2man.py are now Python 3 compatible (with this series), the build will fail for Python's 3.0 through 3.2 because of the explicit unicode literals in conf.py [1]. It's likely that conf.py could use [2] from __future__ import unicode_literals drop the u'' prefixes, and be compatible with all Python's ?2.6 (including all 3s). I haven't checked the logic though, and I'm not running 3.2 locally anymore, so it's not a big priority for me. Cheers, Trevor [1]: https://docs.python.org/3/whatsnew/3.3.html#pep-414-explicit-unicode-literals [2]: from __future__ import unicode_literals W. Trevor King (7): doc/mkdocdeps.py: Convert execfile to import doc/mkdocdeps.py: Use "with" statement for the output file doc/prerst2man.py: Use Python-3-compatible octal notation doc/prerst2man.py: Fix 'os.system' -> 'system' typo doc: Allow rst2man.py as an alternative to rst2man doc/prerst2man.py: Convert execfile to import doc/INSTALL: Remove rst2man reference and other updates configure | 12 +++- doc/INSTALL| 34 -- doc/Makefile.local | 6 +++--- doc/mkdocdeps.py | 19 ++- doc/prerst2man.py | 25 ++--- 5 files changed, 54 insertions(+), 42 deletions(-) -- 1.9.1.353.gc66d89d
Re: Feature suggestion. Indexing encrypted mail?
john.wy...@gmx.de writes: > Would it be possible to add the configurable option to also decrypt > encrypted messages on the fly while indexing to make them searchable, > too? > > That would be really great for people that consider gnupg mainly an > encryption for transport or have their complete hard drive encrypted... As far I understand an attacker could reconstruct the message from the index, so one question is whether the extra complexity in notmuch is worth the minimal extra security over decrypting on delivery and storing plaintext on the (presumably encrypted) disk. Of course decrypting on delivery may be inconvenient (or impossible). I have CCed the two people who have implemented most of the crypto related stuff in notmuch so they can comment. d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Feature suggestion. Indexing encrypted mail?
Hello! Would it be possible to add the configurable option to also decrypt encrypted messages on the fly while indexing to make them searchable, too? That would be really great for people that consider gnupg mainly an encryption for transport or have their complete hard drive encrypted... Best regards! John ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v5 1/2] lib: drop support for single-message mbox files
Jani Nikula writes: > We've supported mbox files containing a single message for historical > reasons, but the support has been deprecated, with a warning message > while indexing, since Notmuch 0.15. Finally drop the support, and > consider all mbox files non-email. series pushed. d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH] debian: ignore performance corpus when making source package
David Bremner writes: > Currently "make debian-snapshot" will include the performance corpus > tarball in the source package, which slows things down and wastes disk > space. tar-ignore is needed twice to keep the default exclude rules > (e.g. to exclude .git) Pushed this. I'm thinking it would be good to treat test databases the same way, and have a new level of cleaning to remove them all. d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v4 0/4] nmbug-status: Python-3-compatibility and general refactoring
"W. Trevor King" writes: > On Sun, Feb 16, 2014 at 07:46:29PM -0400, David Bremner wrote: >> pushed the last 4. > > It looks like there's still a nmbug-status branch on > git://notmuchmail.org/git/notmuch. It's an ancestor of debian/0.17-4, > and nmbug-status development seems to have calmed back down, so that > branch can probably be removed. done. d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[Patch v7 2/6] util: add gz_readline
The idea is to provide a more or less drop in replacement for readline to read from zlib/gzip streams. Take the opportunity to replace malloc with talloc. --- util/Makefile.local | 3 +- util/util.c | 24 +++ util/util.h | 29 ++ util/zlib-extra.c | 85 + util/zlib-extra.h | 25 5 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 util/util.c create mode 100644 util/util.h create mode 100644 util/zlib-extra.c create mode 100644 util/zlib-extra.h diff --git a/util/Makefile.local b/util/Makefile.local index 29c0ce6..905f237 100644 --- a/util/Makefile.local +++ b/util/Makefile.local @@ -4,7 +4,8 @@ dir := util extra_cflags += -I$(srcdir)/$(dir) libutil_c_srcs := $(dir)/xutil.c $(dir)/error_util.c $(dir)/hex-escape.c \ - $(dir)/string-util.c $(dir)/talloc-extra.c + $(dir)/string-util.c $(dir)/talloc-extra.c $(dir)/zlib-extra.c \ + $(dir)/util.c libutil_modules := $(libutil_c_srcs:.c=.o) diff --git a/util/util.c b/util/util.c new file mode 100644 index 000..3bd305d --- /dev/null +++ b/util/util.c @@ -0,0 +1,24 @@ +#include "util.h" +#include "error_util.h" +#include +#include + +const char * +util_error_string (util_status_t errnum) +{ +switch (errnum) { +case UTIL_SUCCESS: + return "none"; +case UTIL_OUT_OF_MEMORY: + return "out of memory"; +case UTIL_EOF: + return "end of file"; +case UTIL_ERRNO: + return strerror (errno); +case UTIL_GZERROR: + /* we lack context to be more informative here */ + return "zlib error"; +default: + INTERNAL_ERROR("unexpected error status %d", errnum); +} +} diff --git a/util/util.h b/util/util.h new file mode 100644 index 000..d12fadb --- /dev/null +++ b/util/util.h @@ -0,0 +1,29 @@ +#ifndef _UTIL_H +#define _UTIL_H + +typedef enum util_status { +/** + * No error occurred. + */ +UTIL_SUCCESS = 0, +/** + * Out of memory. + */ +UTIL_OUT_OF_MEMORY, +/** + * End of stream reached while attempting to read. + */ +UTIL_EOF, +/** + * Low level error occured, consult errno. + */ +UTIL_ERRNO, +/** + * Zlib error occured, call gzerror for details. + */ +UTIL_GZERROR +} util_status_t; + +const char * +util_error_string (util_status_t status); +#endif diff --git a/util/zlib-extra.c b/util/zlib-extra.c new file mode 100644 index 000..cb34845 --- /dev/null +++ b/util/zlib-extra.c @@ -0,0 +1,85 @@ +/* zlib-extra.c - Extra or enhanced routines for compressed I/O. + * + * Copyright (c) 2014 David Bremner + * + * This program 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. + * + * This program 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 this program. If not, see http://www.gnu.org/licenses/ . + * + * Author: David Bremner + */ + +#include "zlib-extra.h" +#include +#include +#include + +/* mimic POSIX/glibc getline, but on a zlib gzFile stream, and using talloc */ +util_status_t +gz_getline (void *talloc_ctx, char **bufptr, ssize_t *bytes_read, gzFile stream) +{ +char *buf = *bufptr; +unsigned int len; +size_t offset = 0; + +if (buf) { + len = talloc_array_length (buf); +} else { + /* same as getdelim from gnulib */ + len = 120; + buf = talloc_array (talloc_ctx, char, len); + if (buf == NULL) + return UTIL_OUT_OF_MEMORY; +} + +while (1) { + if (! gzgets (stream, buf + offset, len - offset)) { + /* Null indicates EOF or error */ + int zlib_status = 0; + (void) gzerror (stream, &zlib_status); + switch (zlib_status) { + case Z_OK: + /* no data read before EOF */ + if (offset == 0) + return UTIL_EOF; + else + goto SUCCESS; + case Z_ERRNO: + return UTIL_ERRNO; + default: + return UTIL_GZERROR; + } + } + + offset += strlen (buf + offset); + + if (buf[offset - 1] == '\n') + goto SUCCESS; + + len *= 2; + buf = talloc_realloc (talloc_ctx, buf, char, len); + if (buf == NULL) + return UTIL_OUT_OF_MEMORY; +} + SUCCESS: +*bufptr = buf; +*bytes_read = offset; +return UTIL_SUCCESS; +} + +const char *gz_error_string (util_status_t status, gzFile file) +{ +if (
[Patch v7 1/6] dump: support gzipped and atomic output
The main goal is to support gzipped output for future internal calls (e.g. from notmuch-new) to notmuch_database_dump. The additional dependency is not very heavy since xapian already pulls in zlib. We want the dump to be "atomic", in the sense that after running the dump file is either present and complete, or not present. This avoids certain classes of mishaps involving overwriting a good backup with a bad or partial one. --- INSTALL | 20 +++-- Makefile.local| 2 +- configure | 28 +++-- doc/man1/notmuch-dump.rst | 3 ++ notmuch-client.h | 4 +- notmuch-dump.c| 101 +- test/T240-dump-restore.sh | 12 ++ 7 files changed, 142 insertions(+), 28 deletions(-) diff --git a/INSTALL b/INSTALL index 690b0ef..b543c50 100644 --- a/INSTALL +++ b/INSTALL @@ -20,8 +20,8 @@ configure stage. Dependencies -Notmuch depends on three libraries: Xapian, GMime 2.4 or 2.6, and -Talloc which are each described below: +Notmuch depends on four libraries: Xapian, GMime 2.4 or 2.6, +Talloc, and zlib which are each described below: Xapian -- @@ -60,6 +60,18 @@ Talloc which are each described below: Talloc is available from http://talloc.samba.org/ + zlib + + + zlib is an extremely popular compression library. It is used + by Xapian, so if you installed that you will already have + zlib. You may need to install the zlib headers separately. + + Notmuch needs the transparent write feature of zlib introduced + in version 1.2.5.2 (Dec. 2011). + + zlib is available from http://zlib.net + Building Documentation -- @@ -79,11 +91,11 @@ dependencies with a simple simple command line. For example: For Debian and similar: -sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev python-sphinx +sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev zlib1g-dev python-sphinx For Fedora and similar: - sudo yum install xapian-core-devel gmime-devel libtalloc-devel python-sphinx + sudo yum install xapian-core-devel gmime-devel libtalloc-devel zlib-devel python-sphinx On other systems, a similar command can be used, but the details of the package names may be different. diff --git a/Makefile.local b/Makefile.local index cb7b106..e5a20a7 100644 --- a/Makefile.local +++ b/Makefile.local @@ -41,7 +41,7 @@ PV_FILE=bindings/python/notmuch/version.py # Smash together user's values with our extra values FINAL_CFLAGS = -DNOTMUCH_VERSION=$(VERSION) $(CPPFLAGS) $(CFLAGS) $(WARN_CFLAGS) $(extra_cflags) $(CONFIGURE_CFLAGS) FINAL_CXXFLAGS = $(CPPFLAGS) $(CXXFLAGS) $(WARN_CXXFLAGS) $(extra_cflags) $(extra_cxxflags) $(CONFIGURE_CXXFLAGS) -FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Lutil -lutil -Llib -lnotmuch $(AS_NEEDED_LDFLAGS) $(GMIME_LDFLAGS) $(TALLOC_LDFLAGS) +FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Lutil -lutil -Llib -lnotmuch $(AS_NEEDED_LDFLAGS) $(GMIME_LDFLAGS) $(TALLOC_LDFLAGS) $(ZLIB_LDFLAGS) FINAL_NOTMUCH_LINKER = CC ifneq ($(LINKER_RESOLVES_LIBRARY_DEPENDENCIES),1) FINAL_NOTMUCH_LDFLAGS += $(CONFIGURE_LDFLAGS) diff --git a/configure b/configure index 1d430b9..83b4af7 100755 --- a/configure +++ b/configure @@ -340,6 +340,18 @@ else errors=$((errors + 1)) fi +printf "Checking for zlib (>= 1.2.5.2)... " +have_zlib=0 +if pkg-config --atleast-version=1.2.5.2 zlib; then +printf "Yes.\n" +have_zlib=1 +zlib_cflags=$(pkg-config --cflags zlib) +zlib_ldflags=$(pkg-config --libs zlib) +else +printf "No.\n" +errors=$((errors + 1)) +fi + printf "Checking for talloc development files... " if pkg-config --exists talloc; then printf "Yes.\n" @@ -496,6 +508,11 @@ EOF echo " Xapian library (including development files such as headers)" echo " http://xapian.org/"; fi +if [ $have_zlib -eq 0 ]; then + echo " zlib library (>= version 1.2.5.2, including development files such as headers)" + echo " http://zlib.net/"; + echo +fi if [ $have_gmime -eq 0 ]; then echo " Either GMime 2.4 library" $GMIME_24_VERSION_CTR "or GMime 2.6 library" $GMIME_26_VERSION_CTR echo " (including development files such as headers)" @@ -519,11 +536,11 @@ case a simple command will install everything you need. For example: On Debian and similar systems: - sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev + sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev zlib1g-dev Or on Fedora and similar systems: - sudo yum install xapian-core-devel gmime-devel libtalloc-devel + sudo yum install xapian-core-devel gmime-devel libtalloc-devel zlib-devel On other systems, similar commands can be used, but the details of the package names may be different. @@ -844,6 +861,10 @@ XAPIAN_LDFLAGS = ${xapian_
[Patch v7 3/6] test: restore with missing final newline
Recent proposed patches for gzipped input had a bug with handling missing newlines that was not caught by the current test suite --- test/T240-dump-restore.sh | 9 + 1 file changed, 9 insertions(+) diff --git a/test/T240-dump-restore.sh b/test/T240-dump-restore.sh index d79aca8..b6d8602 100755 --- a/test/T240-dump-restore.sh +++ b/test/T240-dump-restore.sh @@ -110,6 +110,15 @@ notmuch dump --format=batch-tag from:cworth | sed 's/^.*-- id://' | \ sort > OUTPUT.$test_count test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count +test_begin_subtest "format=batch-tag, missing newline" +printf "+a_tag_without_newline -- id:20091117232137.ga7...@griffis1.net" > IN +notmuch restore --accumulate < IN +notmuch dump id:20091117232137.ga7...@griffis1.net > OUT +cat < EXPECTED ++a_tag_without_newline +inbox +unread -- id:20091117232137.ga7...@griffis1.net +EOF +test_expect_equal_file EXPECTED OUT + test_begin_subtest "format=batch-tag, # round-trip" notmuch dump --format=sup | sort > EXPECTED.$test_count notmuch dump --format=batch-tag | notmuch restore --format=batch-tag -- 1.9.0 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[Patch v7 4/6] restore: transparently support gzipped input
We rely completely on zlib to do the right thing in detecting gzipped input. Since our dump format is chosen to be 7 bit ascii, this should be fine. --- doc/man1/notmuch-restore.rst | 8 notmuch-restore.c| 93 +--- test/T240-dump-restore.sh| 14 +++ 3 files changed, 92 insertions(+), 23 deletions(-) diff --git a/doc/man1/notmuch-restore.rst b/doc/man1/notmuch-restore.rst index d6cf19a..936b138 100644 --- a/doc/man1/notmuch-restore.rst +++ b/doc/man1/notmuch-restore.rst @@ -50,6 +50,14 @@ Supported options for **restore** include format, this heuristic, based the fact that batch-tag format contains no parentheses, should be accurate. +GZIPPED INPUT += + +\ **notmuch restore** will detect if the input is compressed in +**gzip(1)** format and automatically decompress it while reading. This +detection does not depend on file naming and in particular works for +standard input. + SEE ALSO diff --git a/notmuch-restore.c b/notmuch-restore.c index c54d513..7abee0a 100644 --- a/notmuch-restore.c +++ b/notmuch-restore.c @@ -22,6 +22,7 @@ #include "hex-escape.h" #include "tag-util.h" #include "string-util.h" +#include "zlib-extra.h" static regex_t regex; @@ -128,10 +129,10 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) tag_op_list_t *tag_ops; char *input_file_name = NULL; -FILE *input = stdin; +const char *name_for_error = NULL; +gzFile input = NULL; char *line = NULL; void *line_ctx = NULL; -size_t line_size; ssize_t line_len; int ret = 0; @@ -157,39 +158,69 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) }; opt_index = parse_arguments (argc, argv, options, 1); -if (opt_index < 0) - return EXIT_FAILURE; +if (opt_index < 0) { + ret = EXIT_FAILURE; + goto DONE; +} + +name_for_error = input_file_name ? input_file_name : "stdin"; if (! accumulate) flags |= TAG_FLAG_REMOVE_ALL; -if (input_file_name) { - input = fopen (input_file_name, "r"); - if (input == NULL) { - fprintf (stderr, "Error opening %s for reading: %s\n", -input_file_name, strerror (errno)); - return EXIT_FAILURE; +errno = 0; +if (input_file_name) + input = gzopen (input_file_name, "r"); +else { + int infd = dup (STDIN_FILENO); + if (infd < 0) { + fprintf (stderr, "Error duping stdin: %s\n", +strerror (errno)); + ret = EXIT_FAILURE; + goto DONE; } + input = gzdopen (infd, "r"); + if (! input) + close (infd); +} + +if (input == NULL) { + fprintf (stderr, "Error opening %s for (gzip) reading: %s\n", +name_for_error, strerror (errno)); + ret = EXIT_FAILURE; + goto DONE; } if (opt_index < argc) { fprintf (stderr, "Unused positional parameter: %s\n", argv[opt_index]); - return EXIT_FAILURE; + ret = EXIT_FAILURE; + goto DONE; } tag_ops = tag_op_list_create (config); if (tag_ops == NULL) { fprintf (stderr, "Out of memory.\n"); - return EXIT_FAILURE; + ret = EXIT_FAILURE; + goto DONE; } do { - line_len = getline (&line, &line_size, input); + util_status_t status; + + status = gz_getline (line_ctx, &line, &line_len, input); /* empty input file not considered an error */ - if (line_len < 0) - return EXIT_SUCCESS; + if (status == UTIL_EOF) { + ret = EXIT_SUCCESS; + goto DONE; + } + if (status) { + fprintf (stderr, "Error reading (gzipped) input: %s\n", +gz_error_string(status, input)); + ret = EXIT_FAILURE; + goto DONE; + } } while ((line_len == 0) || (line[0] == '#') || /* the cast is safe because we checked about for line_len < 0 */ @@ -254,21 +285,37 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) if (ret) break; -} while ((line_len = getline (&line, &line_size, input)) != -1); +} while (! (ret = gz_getline (line_ctx, &line, &line_len, input))); + -if (line_ctx != NULL) - talloc_free (line_ctx); +/* EOF is normal loop termination condition, UTIL_SUCCESS is + * impossible here */ +if (ret == UTIL_EOF) { + ret = UTIL_SUCCESS; +} else { + fprintf (stderr, "Error reading (gzipped) input: %s\n", +gz_error_string (ret, input)); +} + +/* currently this should not be after DONE: since we don't + * know if the xregcomp was reached + */ if (input_format == DUMP_FORMAT_SUP) regfree (®ex); -if (line) - free (line); + DONE: +if (line_ctx != NULL) +
[Patch v7 6/6] test: verify tag backup generated by database upgrade
'pre upgrade dump' is not much of a test, but at least this way we get somewhat sensible behaviour if it fails. --- test/T530-upgrade.sh | 6 ++ 1 file changed, 6 insertions(+) diff --git a/test/T530-upgrade.sh b/test/T530-upgrade.sh index d46e3d1..7d5d5aa 100755 --- a/test/T530-upgrade.sh +++ b/test/T530-upgrade.sh @@ -25,6 +25,8 @@ test_begin_subtest "path: search does not work with old database version" output=$(notmuch search path:foo) test_expect_equal "$output" "" +test_expect_success 'pre upgrade dump' 'notmuch dump | sort > pre-upgrade-dump' + test_begin_subtest "database upgrade from format version 1" output=$(notmuch new | sed -e 's/^Backing up tags to .*$/Backing up tags to FILENAME/') test_expect_equal "$output" "\ @@ -34,6 +36,10 @@ Backing up tags to FILENAME Your notmuch database has now been upgraded to database format version 2. No new mail." +test_begin_subtest "tag backup matches pre-upgrade dump" +gunzip -c ${MAIL_DIR}/.notmuch/dump-*.gz | sort > backup-dump +test_expect_equal_file pre-upgrade-dump backup-dump + test_begin_subtest "folder: no longer matches in the middle of path" output=$(notmuch search folder:baz) test_expect_equal "$output" "" -- 1.9.0 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[Patch v7 5/6] notmuch-new: backup tags before database upgrade
All we do here is calculate the backup filename, and call the existing dump routine. Also take the opportity to add a message about being safe to interrupt. --- notmuch-new.c| 29 - test/T530-upgrade.sh | 4 +++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/notmuch-new.c b/notmuch-new.c index 82acf69..d269c7c 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -989,8 +989,35 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[]) return EXIT_FAILURE; if (notmuch_database_needs_upgrade (notmuch)) { - if (add_files_state.verbosity >= VERBOSITY_NORMAL) + time_t now = time (NULL); + struct tm *gm_time = gmtime (&now); + + /* since dump files are written atomically, the amount of +* harm from overwriting one within a second seems +* relatively small. */ + + const char *backup_name = + talloc_asprintf (notmuch, "%s/dump-%04d%02d%02dT%02d%02d%02d.gz", +dot_notmuch_path, +gm_time->tm_year + 1900, +gm_time->tm_mon + 1, +gm_time->tm_mday, +gm_time->tm_hour, +gm_time->tm_min, +gm_time->tm_sec); + + if (add_files_state.verbosity >= VERBOSITY_NORMAL) { printf ("Welcome to a new version of notmuch! Your database will now be upgraded.\n"); + printf ("This process is safe to interrupt.\n"); + printf ("Backing up tags to %s...\n", backup_name); + } + + if (notmuch_database_dump (notmuch, backup_name, "", + DUMP_FORMAT_BATCH_TAG, TRUE)) { + fprintf (stderr, "Backup failed. Aborting upgrade."); + return EXIT_FAILURE; + } + gettimeofday (&add_files_state.tv_start, NULL); notmuch_database_upgrade (notmuch, add_files_state.verbosity >= VERBOSITY_NORMAL ? upgrade_print_progress : NULL, diff --git a/test/T530-upgrade.sh b/test/T530-upgrade.sh index 67bbf31..d46e3d1 100755 --- a/test/T530-upgrade.sh +++ b/test/T530-upgrade.sh @@ -26,9 +26,11 @@ output=$(notmuch search path:foo) test_expect_equal "$output" "" test_begin_subtest "database upgrade from format version 1" -output=$(notmuch new) +output=$(notmuch new | sed -e 's/^Backing up tags to .*$/Backing up tags to FILENAME/') test_expect_equal "$output" "\ Welcome to a new version of notmuch! Your database will now be upgraded. +This process is safe to interrupt. +Backing up tags to FILENAME Your notmuch database has now been upgraded to database format version 2. No new mail." -- 1.9.0 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
v7 gzip dump restore patches
Supercedes id:1396554083-3892-2-git-send-email-da...@tethera.net - adds new analogues of strerror - util_error_string - gz_error_string Interdiff: diff --git a/configure b/configure index 1d624f7..83b4af7 100755 --- a/configure +++ b/configure @@ -509,7 +509,7 @@ EOF echo " http://xapian.org/"; fi if [ $have_zlib -eq 0 ]; then - echo " zlib library (including development files such as headers)" + echo " zlib library (>= version 1.2.5.2, including development files such as headers)" echo " http://zlib.net/"; echo fi diff --git a/notmuch-dump.c b/notmuch-dump.c index 2a7252a..2849eab 100644 --- a/notmuch-dump.c +++ b/notmuch-dump.c @@ -127,7 +127,7 @@ notmuch_database_dump (notmuch_database_t *notmuch, dump_format_t output_format, notmuch_bool_t gzip_output) { -gzFile output; +gzFile output = NULL; const char *mode = gzip_output ? "w9" : "wT"; const char *name_for_error = output_file_name ? output_file_name : "stdout"; @@ -178,7 +178,10 @@ notmuch_database_dump (notmuch_database_t *notmuch, } if (gzclose_w (output) != Z_OK) { + fprintf (stderr, "Error closing %s: %s\n", name_for_error, +gzerror (output, NULL)); ret = EXIT_FAILURE; + output = NULL; goto DONE; } @@ -192,6 +195,9 @@ notmuch_database_dump (notmuch_database_t *notmuch, } DONE: +if (ret != EXIT_SUCCESS && output) + (void) gzclose_w (output); + if (ret != EXIT_SUCCESS && output_file_name) (void) unlink (tempname); diff --git a/notmuch-restore.c b/notmuch-restore.c index eb5b7b2..7abee0a 100644 --- a/notmuch-restore.c +++ b/notmuch-restore.c @@ -129,7 +129,8 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) tag_op_list_t *tag_ops; char *input_file_name = NULL; -gzFile input; +const char *name_for_error = NULL; +gzFile input = NULL; char *line = NULL; void *line_ctx = NULL; ssize_t line_len; @@ -157,19 +158,26 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) }; opt_index = parse_arguments (argc, argv, options, 1); -if (opt_index < 0) - return EXIT_FAILURE; +if (opt_index < 0) { + ret = EXIT_FAILURE; + goto DONE; +} + +name_for_error = input_file_name ? input_file_name : "stdin"; if (! accumulate) flags |= TAG_FLAG_REMOVE_ALL; +errno = 0; if (input_file_name) input = gzopen (input_file_name, "r"); else { int infd = dup (STDIN_FILENO); if (infd < 0) { - fprintf (stderr, "Error duping stdin\n"); - return EXIT_FAILURE; + fprintf (stderr, "Error duping stdin: %s\n", +strerror (errno)); + ret = EXIT_FAILURE; + goto DONE; } input = gzdopen (infd, "r"); if (! input) @@ -178,19 +186,22 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) if (input == NULL) { fprintf (stderr, "Error opening %s for (gzip) reading: %s\n", -input_file_name ? input_file_name : "stdin", strerror (errno)); - return EXIT_FAILURE; +name_for_error, strerror (errno)); + ret = EXIT_FAILURE; + goto DONE; } if (opt_index < argc) { fprintf (stderr, "Unused positional parameter: %s\n", argv[opt_index]); - return EXIT_FAILURE; + ret = EXIT_FAILURE; + goto DONE; } tag_ops = tag_op_list_create (config); if (tag_ops == NULL) { fprintf (stderr, "Out of memory.\n"); - return EXIT_FAILURE; + ret = EXIT_FAILURE; + goto DONE; } do { @@ -199,12 +210,17 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) status = gz_getline (line_ctx, &line, &line_len, input); /* empty input file not considered an error */ - if (status == UTIL_EOF) - return EXIT_SUCCESS; - - if (status) - return EXIT_FAILURE; + if (status == UTIL_EOF) { + ret = EXIT_SUCCESS; + goto DONE; + } + if (status) { + fprintf (stderr, "Error reading (gzipped) input: %s\n", +gz_error_string(status, input)); + ret = EXIT_FAILURE; + goto DONE; + } } while ((line_len == 0) || (line[0] == '#') || /* the cast is safe because we checked about for line_len < 0 */ @@ -269,17 +285,37 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) if (ret) break; -} while (gz_getline (line_ctx, &line, &line_len, input) == UTIL_SUCCESS); +} while (! (ret = gz_getline (line_ctx, &line, &line_len, input))); + -if (line_ctx != NULL) - talloc_free (line_ctx); +/* EOF is normal loop termination condi
Re: [PATCH v4 0/4] nmbug-status: Python-3-compatibility and general refactoring
On Sun, Feb 16, 2014 at 07:46:29PM -0400, David Bremner wrote: > pushed the last 4. It looks like there's still a nmbug-status branch on git://notmuchmail.org/git/notmuch. It's an ancestor of debian/0.17-4, and nmbug-status development seems to have calmed back down, so that branch can probably be removed. Cheers, Trevor -- This email may be signed or encrypted with GnuPG (http://www.gnupg.org). For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy signature.asc Description: OpenPGP digital signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v4 0/4] nmbug-status: Python-3-compatibility and general refactoring
On Sun, Feb 16, 2014 at 07:46:29PM -0400, David Bremner wrote: > pushed the last 4. It looks like there's still a nmbug-status branch on git://notmuchmail.org/git/notmuch. It's an ancestor of debian/0.17-4, and nmbug-status development seems to have calmed back down, so that branch can probably be removed. Cheers, Trevor -- This email may be signed or encrypted with GnuPG (http://www.gnupg.org). For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy -- next part -- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: OpenPGP digital signature URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20140405/97ea6436/attachment.pgp>
[PATCH 1/1] release-checks: removed manual page version check
Manual pages are now generated and during the generation the version string is read from `version` file, so this (currently failing) test checking manual page versions can be removed. While at it, changed the case pattern *[^0-9.]* to its portable alternative *[!0-9.]* --- devel/release-checks.sh | 42 +- 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/devel/release-checks.sh b/devel/release-checks.sh index 8938905..797d62a 100755 --- a/devel/release-checks.sh +++ b/devel/release-checks.sh @@ -68,7 +68,7 @@ verfail () echo -n "Checking that '$VERSION' is good with digits and periods... " case $VERSION in - *[^0-9.]*) + *[!0-9.]*) verfail "'$VERSION' contains other characters than digits and periods" ;; .*) verfail "'$VERSION' begins with a period" ;; *.) verfail "'$VERSION' ends with a period" ;; @@ -196,46 +196,6 @@ case $news_date in append_emsg "Date '$news_date' in NEWS file is not in format (-mm-dd)" esac -readonly DATE=${news_date//[()]/} # bash feature -manthdata () -{ - set x $* - if [ $# != 7 ] - then - append_emsg "'$mp' has too many '.TH' lines" - man_mismatch=1 - fi - man_date=${5-} man_version=${7-} -} - -echo -n "Checking that manual page dates and versions are $DATE and $VERSION... " -manfiles=`find man -type f | sort` -man_pages_ok=Yes -for mp in $manfiles -do - case $mp in - *.[0-9]) ;; # fall below this 'case ... esac' - - */Makefile.local | */Makefile ) continue ;; - */.gitignore) continue ;; - *.bak) continue ;; - - *) append_emsg "'$mp': extra file" - man_pages_ok=No - continue - esac - manthdata `sed -n '/^[.]TH NOTMUCH/ { y/"/ /; p; }' "$mp"` - if [ "$man_version" != "$VERSION" ] - thenappend_emsg "Version '$man_version' is not '$VERSION' in $mp" - mman_pages_ok=No - fi - if [ "$man_date" != "$DATE" ] - thenappend_emsg "DATE '$man_date' is not '$DATE' in $mp" - man_pages_ok=No - fi -done -echo $man_pages_ok. - if [ -n "$emsgs" ] then echo -- 1.8.0 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] emacs: sign/encrypt replies to signed/encrypted messages
This is a simple approach to improving security when replying to signed or encrypted messages. If the message being replied to was signed, add mml tag to sign the reply. If the message being replied to was encrypted, add mml tag to sign and encrypt the reply. This may need configuration; I for one might want to encrypt replies to encrypted messages, but not always sign replies to signed messages. This still includes a slight bug: if any mml tags are added, they are included in the region containing the quoted parts. Killing the region will kill the mml tags too. --- emacs/notmuch-mua.el | 14 +- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el index ba3ef275ec5e..9fb84b57b030 100644 --- a/emacs/notmuch-mua.el +++ b/emacs/notmuch-mua.el @@ -115,6 +115,15 @@ list." (push header message-hidden-headers))) notmuch-mua-hidden-headers)) +(defun notmuch-mua-reply-crypto (parts) + (loop for part in parts + if (notmuch-match-content-type (plist-get part :content-type) "multipart/signed") + do (mml-secure-message-sign) + else if (notmuch-match-content-type (plist-get part :content-type) "multipart/encrypted") + do (mml-secure-message-sign-encrypt) + else if (notmuch-match-content-type (plist-get part :content-type) "multipart/*") + do (notmuch-mua-reply-crypto (plist-get part :content + (defun notmuch-mua-get-quotable-parts (parts) (loop for part in parts if (notmuch-match-content-type (plist-get part :content-type) "multipart/alternative") @@ -224,7 +233,10 @@ list." (set-mark (point)) (goto-char start) ;; Quote the original message according to the user's configured style. - (message-cite-original + (message-cite-original))) + +;; Sign and/or encrypt replies to signed and/or encrypted messages. +(notmuch-mua-reply-crypto (plist-get original :body))) ;; Push mark right before signature, if any. (message-goto-signature) -- 1.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch