Re: [PATCH v5 1/5] cli: command line parsing: allow default for keyword options
On Sat, 26 May 2012 16:54:50 +0100, Mark Walters wrote: > This changes the parsing for "keyword" options so that if the option > is specified with no argument the first possible argument is > chosen. This make it easier to add options to existing boolean > arguments (the existing --option can default to TRUE). This has the side-effect of allowing defaults for all keyword options, right? I'm not sure that's desirable when the default is non-obvious. Maybe keyword options which allow an optional argument should have an explicit entry in the notmuch_keyword_t[] array, e.g. under "" or "default". > diff --git a/command-line-arguments.c b/command-line-arguments.c > index 76b185f..d40c7e6 100644 > --- a/command-line-arguments.c > +++ b/command-line-arguments.c > @@ -11,10 +11,16 @@ > */ > > static notmuch_bool_t > -_process_keyword_arg (const notmuch_opt_desc_t *arg_desc, const char > *arg_str) { > +_process_keyword_arg (const notmuch_opt_desc_t *arg_desc, char next, const > char *arg_str) { > > const notmuch_keyword_t *keywords = arg_desc->keywords; > > +if (next == 0) { > +/* No keyword given so return first option as default */ > + *((int *)arg_desc->output_var) = keywords->value; > + return TRUE; > +} Indentation. Peter ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 2/2] Makefile.local: added verify-version-news to verify-no-dirty-code deps.
Added `verify-version-news` to the end of `verify-no-dirty-code` dependencies so it is part of release testing checks. --- Tested by executing the following commands: make verify-source-tree-and-version make verify-source-tree-and-version VERSION=0.13 make verify-source-tree-and-version VERSION=0.12 Makefile.local |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Makefile.local b/Makefile.local index 1b34c00..94a3a70 100644 --- a/Makefile.local +++ b/Makefile.local @@ -187,7 +187,7 @@ release-message: verify-source-tree-and-version: verify-no-dirty-code .PHONY: verify-no-dirty-code -verify-no-dirty-code: verify-version-debian verify-version-python verify-version-manpage +verify-no-dirty-code: verify-version-debian verify-version-python verify-version-manpage verify-version-news ifeq ($(IS_GIT),yes) @printf "Checking that source tree is clean..." ifneq ($(shell git ls-files -m),) -- 1.7.1
[PATCH 1/2] Makefile.local: added checks for latest NEWS title
Added target `verify-version-news` which checks that the first line in NEWS file has the following properties: First word is 'Notmuch' Second "word" matches the current version Rest of line is in format (201[2-9]-[01][0-9]-[0-3][0-9] --- Tested by executing the following commands: make verify-version-news make verify-version-news VERSION=0.13 make verify-version-news VERSION=0.12 Makefile.local | 15 +++ 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/Makefile.local b/Makefile.local index 53b4a0d..1b34c00 100644 --- a/Makefile.local +++ b/Makefile.local @@ -220,6 +220,21 @@ verify-version-python: verify-version-components echo "Please edit version and $(PV_FILE) to have consistent versions." && false) @echo "Good." +.PHONY: verify-version-news +verify-version-news: verify-version-components + @read notmuch version date < NEWS ;\ + ev=0 ;\ + echo -n "Checking that this is 'Notmuch' NEWS..." ;\ + if [ "$$notmuch" = 'Notmuch' ]; then echo 'Good.' ;\ + else echo 'No.'; ev=1; fi ;\ + echo -n "Checking that NEWS version is $(VERSION)..." ;\ + if [ "$$version" = '$(VERSION)' ]; then echo 'Good.' ;\ + else echo 'No.'; ev=1; fi ;\ + echo -n "Checking that NEWS date is in correct format..." ;\ + case $$date in '('201[2-9]-[0-1][0-9]-[0-3][0-9]')') echo 'Good.' ;;\ + *) echo 'No.'; ev=1; esac ;\ + if [ $$ev -ne 0 ]; then echo "Please edit NEWS file to have Notmuch header line in correct format."; false; fi + .PHONY: verify-version-components verify-version-components: @echo -n "Checking that $(VERSION) consists only of digits and periods..." -- 1.7.1
[PATCH v5 5/5] emacs: make elide messages use notmuch-show for omitting messages.
Previously the elide messages code got the entire-thread from notmuch-show.c and then threw away all non-matching messages. This version calls notmuch-show.c without the --entire-thread flag so it never receives the non-matching messages in the first place. This makes it substantially faster. --- emacs/notmuch-show.el | 18 ++ 1 files changed, 10 insertions(+), 8 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index d318430..9cc68be 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -958,9 +958,9 @@ message at DEPTH in the current thread." "Insert the message tree TREE at depth DEPTH in the current thread." (let ((msg (car tree)) (replies (cadr tree))) -(if (or (not notmuch-show-elide-non-matching-messages) - (plist-get msg :match)) - (notmuch-show-insert-msg msg depth)) +;; We test whether there is a message or just some replies. +(when msg + (notmuch-show-insert-msg msg depth)) (notmuch-show-insert-thread replies (1+ depth (defun notmuch-show-insert-thread (thread depth) @@ -1041,16 +1041,18 @@ function is used." (args (if notmuch-show-query-context (append (list "\'") basic-args (list "and (" notmuch-show-query-context ")\'")) -(append (list "\'") basic-args (list "\'") - (notmuch-show-insert-forest (notmuch-query-get-threads -(cons "--exclude=false" args))) +(append (list "\'") basic-args (list "\'" +(cli-args (cons "--exclude=false" +(when notmuch-show-elide-non-matching-messages + (list "--entire-thread=false") + + (notmuch-show-insert-forest (notmuch-query-get-threads (append cli-args args))) ;; If the query context reduced the results to nothing, run ;; the basic query. (when (and (eq (buffer-size) 0) notmuch-show-query-context) (notmuch-show-insert-forest - (notmuch-query-get-threads - (cons "--exclude=false" basic-args) + (notmuch-query-get-threads (append cli-args basic-args) (jit-lock-register #'notmuch-show-buttonise-links) -- 1.7.9.1
[PATCH v5 4/5] Update devel/schemata for --entire-thread=false
Also remove the Json --entire-thread item from devel/TODO. --- devel/TODO |2 -- devel/schemata |2 +- 2 files changed, 1 insertions(+), 3 deletions(-) diff --git a/devel/TODO b/devel/TODO index 7b750af..eb757af 100644 --- a/devel/TODO +++ b/devel/TODO @@ -92,8 +92,6 @@ and email address in the From: line. We could also then easily support "notmuch compose --from " to support getting at alternate email addresses. -Fix the --format=json option to not imply --entire-thread. - Implement "notmuch search --exclude-threads=" to allow for excluding muted threads, (and any other negative, thread-based filtering that the user wants to do). diff --git a/devel/schemata b/devel/schemata index 977cea7..8fcab8e 100644 --- a/devel/schemata +++ b/devel/schemata @@ -32,7 +32,7 @@ thread = [thread_node*] # A message and its replies (show_messages) thread_node = [ -message?, # present if --entire-thread or matched +message?, # null if not matched and not --entire-thread [thread_node*]# children of message ] -- 1.7.9.1
[PATCH v5 3/5] cli: make --entire-thread=false work for format=json.
The --entire-thread option in notmuch-show.c defaults to true when format=json. Previously there was no way to turn this off. This patch makes it respect --entire-thread=false. To do this the patch moves the --entire-thread option to be a keyword option using the new command line parsing to allow the existing --entire-thread syntax to keep working. --- notmuch-show.c | 25 +++-- 1 files changed, 23 insertions(+), 2 deletions(-) diff --git a/notmuch-show.c b/notmuch-show.c index 97da5cc..207093a 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -981,6 +981,12 @@ enum { NOTMUCH_FORMAT_RAW }; +enum { +ENTIRE_THREAD_DEFAULT, +ENTIRE_THREAD_TRUE, +ENTIRE_THREAD_FALSE, +}; + /* The following is to allow future options to be added more easily */ enum { EXCLUDE_TRUE, @@ -1000,6 +1006,7 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) int format_sel = NOTMUCH_FORMAT_NOT_SPECIFIED; notmuch_bool_t verify = FALSE; int exclude = EXCLUDE_TRUE; +int entire_thread = ENTIRE_THREAD_DEFAULT; notmuch_opt_desc_t options[] = { { NOTMUCH_OPT_KEYWORD, &format_sel, "format", 'f', @@ -1012,8 +1019,11 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) (notmuch_keyword_t []){ { "true", EXCLUDE_TRUE }, { "false", EXCLUDE_FALSE }, { 0, 0 } } }, +{ NOTMUCH_OPT_KEYWORD, &entire_thread, "entire-thread", 't', + (notmuch_keyword_t []){ { "true", ENTIRE_THREAD_TRUE }, + { "false", ENTIRE_THREAD_FALSE }, + { 0, 0 } } }, { NOTMUCH_OPT_INT, ¶ms.part, "part", 'p', 0 }, - { NOTMUCH_OPT_BOOLEAN, ¶ms.entire_thread, "entire-thread", 't', 0 }, { NOTMUCH_OPT_BOOLEAN, ¶ms.decrypt, "decrypt", 'd', 0 }, { NOTMUCH_OPT_BOOLEAN, &verify, "verify", 'v', 0 }, { 0, 0, 0, 0, 0 } @@ -1036,7 +1046,9 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) switch (format_sel) { case NOTMUCH_FORMAT_JSON: format = &format_json; - params.entire_thread = TRUE; + /* JSON defaults to entire-thread TRUE */ + if (entire_thread == ENTIRE_THREAD_DEFAULT) + entire_thread = ENTIRE_THREAD_TRUE; break; case NOTMUCH_FORMAT_TEXT: format = &format_text; @@ -1058,6 +1070,15 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) params.raw = TRUE; break; } +/* Default is entire-thread = FALSE except for format=json which + * is dealt with above. */ +if (entire_thread == ENTIRE_THREAD_DEFAULT) + entire_thread = ENTIRE_THREAD_FALSE; + +if (entire_thread == ENTIRE_THREAD_TRUE) + params.entire_thread = TRUE; +else + params.entire_thread = FALSE; if (params.decrypt || verify) { #ifdef GMIME_ATLEAST_26 -- 1.7.9.1
[PATCH v5 2/5] cli: Let json output "null" messages for non --entire-thread
All formats except Json can output empty messages for non entire-thread, but in Json format we output "null" to keep the other elements (e.g. the replies to the omitted message) in the correct place. --- notmuch-client.h |1 + notmuch-show.c | 20 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/notmuch-client.h b/notmuch-client.h index 19b7f01..08540a7 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -72,6 +72,7 @@ typedef struct notmuch_show_format { const struct notmuch_show_params *params); const char *message_set_sep; const char *message_set_end; +const char *null_message; } notmuch_show_format_t; typedef struct notmuch_show_params { diff --git a/notmuch-show.c b/notmuch-show.c index 95427d4..97da5cc 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -37,7 +37,8 @@ static const notmuch_show_format_t format_json = { .message_set_start = "[", .part = format_part_json_entry, .message_set_sep = ", ", -.message_set_end = "]" +.message_set_end = "]", +.null_message = "null" }; static notmuch_status_t @@ -800,6 +801,15 @@ format_part_raw (unused (const void *ctx), mime_node_t *node, } static notmuch_status_t +show_null_message (const notmuch_show_format_t *format) +{ +/* Output a null message. Currently empty for all formats except Json */ +if (format->null_message) + printf ("%s", format->null_message); +return NOTMUCH_STATUS_SUCCESS; +} + +static notmuch_status_t show_message (void *ctx, const notmuch_show_format_t *format, notmuch_message_t *message, @@ -862,11 +872,13 @@ show_messages (void *ctx, if (status && !res) res = status; next_indent = indent + 1; - - if (!status && format->message_set_sep) - fputs (format->message_set_sep, stdout); + } else { + status = show_null_message (format); } + if (!status && format->message_set_sep) + fputs (format->message_set_sep, stdout); + status = show_messages (ctx, format, notmuch_message_get_replies (message), -- 1.7.9.1
[PATCH v5 1/5] cli: command line parsing: allow default for keyword options
This changes the parsing for "keyword" options so that if the option is specified with no argument the first possible argument is chosen. This make it easier to add options to existing boolean arguments (the existing --option can default to TRUE). --- command-line-arguments.c | 13 ++--- 1 files changed, 10 insertions(+), 3 deletions(-) diff --git a/command-line-arguments.c b/command-line-arguments.c index 76b185f..d40c7e6 100644 --- a/command-line-arguments.c +++ b/command-line-arguments.c @@ -11,10 +11,16 @@ */ static notmuch_bool_t -_process_keyword_arg (const notmuch_opt_desc_t *arg_desc, const char *arg_str) { +_process_keyword_arg (const notmuch_opt_desc_t *arg_desc, char next, const char *arg_str) { const notmuch_keyword_t *keywords = arg_desc->keywords; +if (next == 0) { +/* No keyword given so return first option as default */ + *((int *)arg_desc->output_var) = keywords->value; + return TRUE; +} + while (keywords->name) { if (strcmp (arg_str, keywords->name) == 0) { if (arg_desc->output_var) { @@ -99,7 +105,8 @@ parse_option (const char *arg, */ if (next != '=' && next != ':' && next != 0) return FALSE; if (next == 0) { - if (try->opt_type != NOTMUCH_OPT_BOOLEAN) + if (try->opt_type != NOTMUCH_OPT_BOOLEAN && + try->opt_type != NOTMUCH_OPT_KEYWORD) return FALSE; } else { if (value[0] == 0) return FALSE; @@ -110,7 +117,7 @@ parse_option (const char *arg, switch (try->opt_type) { case NOTMUCH_OPT_KEYWORD: - return _process_keyword_arg (try, value); + return _process_keyword_arg (try, next, value); break; case NOTMUCH_OPT_BOOLEAN: return _process_boolean_arg (try, next, value); -- 1.7.9.1
[PATCH v5 0/5] Allow JSON to use non-entire thread, and use for elide
This is version 5 of this patch series: version 4 is at id:"1335258675-29439-1-git-send-email-markwalters1009 at gmail.com". This version changes the way the command-line parser deals with keywords so that specifying --option without an = returns the first option. This means that boolean options can easily have extra options added without breaking the existing syntax. Patch 3/5 takes advantage of this new feature to implement the --entire-thread option to notmuch-show in a non-hacky way. Best wishes Mark Mark Walters (5): cli: command line parsing: allow default for keyword options cli: Let json output "null" messages for non --entire-thread cli: make --entire-thread=false work for format=json. Update devel/schemata for --entire-thread=false emacs: make elide messages use notmuch-show for omitting messages. command-line-arguments.c | 13 ++--- devel/TODO |2 -- devel/schemata |2 +- emacs/notmuch-show.el| 18 ++ notmuch-client.h |1 + notmuch-show.c | 45 +++-- 6 files changed, 61 insertions(+), 20 deletions(-) -- 1.7.9.1
[PATCH 1/2] Makefile.local: added checks for latest NEWS title
Tomi Ollila writes: > Added target `verify-version-news` which checks that the first line > in NEWS file has the following properties: > First word is 'Notmuch' > Second "word" matches the current version > Rest of line is in format (201[2-9]-[01][0-9]-[0-3][0-9] I appreciate the effort, but I wonder if it is worth complicating the build system further? I'm willing to be swayed either way. d
[PATCH 03/10] Fix compilation of smtp-dummy on FreeBSD
On May 25, 2012 4:44 PM, "Mike Kelly" wrote: > > --- > test/smtp-dummy.c |5 - > 1 file changed, 4 insertions(+), 1 deletion(-) > > diff --git a/test/smtp-dummy.c b/test/smtp-dummy.c > index 3801a5e..aa82fa1 100644 > --- a/test/smtp-dummy.c > +++ b/test/smtp-dummy.c > @@ -33,11 +33,14 @@ > * have been warned. > */ > > +#define _GNU_SOURCE /* for getline */ First of all, thanks for sharing your work. Independent of this patch, I've been thinking about defining _GNU_SOURCE in the makefile. I don't think it's very elegant to #define it everywhere. It would also pave the way towards building with -pedantic (and possibly -std=c99) in a portable way. For example, the compat test code #defines _GNU_SOURCE while the actual code does not, which I think is an error. I'll look into this after the weekend (unless you beat me to it). BR, Jani. > #include > #include > #include > #include > -#include > +#include > +#include > +#include > #include > #include > > -- > 1.7.10.2 > > ___ > 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/20120526/2226a245/attachment.html>
[PATCH 06/10] Fix test/count on FreeBSD
On Fri, 25 May 2012 09:43:27 -0400, Mike Kelly wrote: > FreeBSD's `wc -l` includes some white space in front of the number, so > trim it off. > --- > test/count |8 > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/test/count b/test/count > index 300b171..618dbb9 100755 > --- a/test/count > +++ b/test/count > @@ -8,22 +8,22 @@ SEARCH="\"*\"" > > test_begin_subtest "message count is the default for notmuch count" > test_expect_equal \ > -"`notmuch search --output=messages ${SEARCH} | wc -l`" \ > +"`notmuch search --output=messages ${SEARCH} | wc -l |sed > 's/^[[:space:]]*//'`" \ > "`notmuch count ${SEARCH}`" You could perform a proper integer comparison like: test_expect_success "message count is the default for notmuch count" ' test "`notmuch search --output=messages ${SEARCH} | wc -l`" \ -eq "`notmuch count ${SEARCH}`" ' Peter
[PATCH v4 2/4] cli: make --entire-thread=false work for format=json.
On Tue, 24 Apr 2012 10:11:13 +0100, Mark Walters wrote: > The --entire-thread option in notmuch-show.c defaults to true when > format=json. Previously there was no way to turn this off. This patch > makes it respect --entire-thread=false. > > The one subtlety is that we initialise a notmuch_bool_t to -1 to > indicate that the option parsing has not set it. This allows the code > to distinguish between the option being omitted from the command line, > and the option being set to false on the command line. > --- > notmuch-show.c | 16 ++-- > 1 files changed, 14 insertions(+), 2 deletions(-) > > diff --git a/notmuch-show.c b/notmuch-show.c > index 0d21f1a..48551bb 100644 > --- a/notmuch-show.c > +++ b/notmuch-show.c > @@ -996,7 +996,13 @@ notmuch_show_command (void *ctx, unused (int argc), > unused (char *argv[])) > char *query_string; > int opt_index, ret; > const notmuch_show_format_t *format = &format_text; > -notmuch_show_params_t params = { .part = -1, .omit_excluded = TRUE }; > + > +/* We abuse the notmuch_bool_t variable params.entire-thread by > + * setting it to -1 to denote that the command line parsing has > + * not set it. We ensure it is set to TRUE or FALSE before passing > + * it to any other function.*/ > +notmuch_show_params_t params = { .part = -1, .entire_thread = -1 }; > + > int format_sel = NOTMUCH_FORMAT_NOT_SPECIFIED; > notmuch_bool_t verify = FALSE; > int exclude = EXCLUDE_TRUE; Hi Mark, As an alternative to the abuse, could you just treat it as with exclude, using an enum with three values (TRUE|FALSE|DEFAULT)? Then set params.entire_thread afterwards. Peter
[PATCH v5 6/7] cli: new crypto verify flag to handle verification
Use this flag rather than depend on the existence of an initialized gpgctx, to determine whether we should verify a multipart/signed. We will be moving to create the ctx lazily, so we don't want to depend on it being previously initialized if it's not needed. --- mime-node.c |5 ++--- notmuch-client.h |8 notmuch-reply.c |1 + notmuch-show.c | 14 +++--- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/mime-node.c b/mime-node.c index a838224..73e28c5 100644 --- a/mime-node.c +++ b/mime-node.c @@ -183,8 +183,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) } /* Handle PGP/MIME parts */ -if (GMIME_IS_MULTIPART_ENCRYPTED (part) - && node->ctx->crypto->gpgctx && node->ctx->crypto->decrypt) { +if (GMIME_IS_MULTIPART_ENCRYPTED (part) && node->ctx->crypto->decrypt) { if (node->nchildren != 2) { /* this violates RFC 3156 section 4, so we won't bother with it. */ fprintf (stderr, "Error: %d part(s) for a multipart/encrypted " @@ -218,7 +217,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) (err ? err->message : "no error explanation given")); } } -} else if (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->gpgctx) { +} else if (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->verify) { if (node->nchildren != 2) { /* this violates RFC 3156 section 5, so we won't bother with it. */ fprintf (stderr, "Error: %d part(s) for a multipart/signed message " diff --git a/notmuch-client.h b/notmuch-client.h index 962c747..0f29a83 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -79,6 +79,7 @@ typedef struct notmuch_show_format { typedef struct notmuch_crypto { notmuch_crypto_context_t* gpgctx; +notmuch_bool_t verify; notmuch_bool_t decrypt; } notmuch_crypto_t; @@ -350,10 +351,9 @@ struct mime_node { }; /* Construct a new MIME node pointing to the root message part of - * message. If crypto->gpgctx is non-NULL, it will be used to verify - * signatures on any child parts. If crypto->decrypt is true, then - * crypto.gpgctx will additionally be used to decrypt any encrypted - * child parts. + * message. If crypto->verify is true, signed child parts will be + * verified. If crypto->decrypt is true, encrypted child parts will be + * decrypted. * * Return value: * diff --git a/notmuch-reply.c b/notmuch-reply.c index 6f368c9..1ab3db9 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -707,6 +707,7 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) notmuch_show_params_t params = { .part = -1, .crypto = { + .verify = FALSE, .decrypt = FALSE } }; diff --git a/notmuch-show.c b/notmuch-show.c index fb5e9b6..3c06792 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -987,11 +987,11 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) .part = -1, .omit_excluded = TRUE, .crypto = { + .verify = FALSE, .decrypt = FALSE } }; int format_sel = NOTMUCH_FORMAT_NOT_SPECIFIED; -notmuch_bool_t verify = FALSE; int exclude = EXCLUDE_TRUE; notmuch_opt_desc_t options[] = { @@ -1008,7 +1008,7 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) { NOTMUCH_OPT_INT, ¶ms.part, "part", 'p', 0 }, { NOTMUCH_OPT_BOOLEAN, ¶ms.entire_thread, "entire-thread", 't', 0 }, { NOTMUCH_OPT_BOOLEAN, ¶ms.crypto.decrypt, "decrypt", 'd', 0 }, - { NOTMUCH_OPT_BOOLEAN, &verify, "verify", 'v', 0 }, + { NOTMUCH_OPT_BOOLEAN, ¶ms.crypto.verify, "verify", 'v', 0 }, { 0, 0, 0, 0, 0 } }; @@ -1018,6 +1018,10 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) return 1; } +/* decryption implies verification */ +if (params.crypto.decrypt) + params.crypto.verify = TRUE; + if (format_sel == NOTMUCH_FORMAT_NOT_SPECIFIED) { /* if part was requested and format was not specified, use format=raw */ if (params.part >= 0) @@ -1052,7 +1056,7 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) break; } -if (params.crypto.decrypt || verify) { +if (params.crypto.decrypt || params.crypto.verify) { #ifdef GMIME_ATLEAST_26 /* TODO: GMimePasswordRequestFunc */ params.crypto.gpgctx = g_mime_gpg_context_new (NULL, "gpg"); @@ -1063,6 +1067,10 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) if (params.crypto.gpgctx) { g_mime_gpg_context_set_always_trust ((GMimeGpgContext*) params.crypto.gpgctx, FALSE); } else { + /* If we fail to create the gpgctx set the verify and +* decrypt flags to FALSE so we don't try to do any +* further verification or decryption
[PATCH v5 2/7] cli: new crypto structure to store crypto contexts and parameters, and functions to support it
This new structure, notmuch_crypto_t, keeps all relevant crypto contexts and parameters together, and will make it easier to pass the stuff around and clean it up. The name of the crypto context inside this new struct will change, to reflect that it is actually a GPG context, which is a sub type of Crypto context. There are other types of Crypto contexts (Pkcs7 in particular, which we hope to support) so we want to be clear. The new crypto.c contains functions to return the proper context from the struct for a given protocol (and initialize it if needed), and to cleanup a struct by releasing the crypto contexts. --- Makefile.local |1 + crypto.c | 71 ++ notmuch-client.h | 11 + 3 files changed, 83 insertions(+) create mode 100644 crypto.c diff --git a/Makefile.local b/Makefile.local index 53b4a0d..a890df2 100644 --- a/Makefile.local +++ b/Makefile.local @@ -292,6 +292,7 @@ notmuch_client_srcs = \ notmuch-time.c \ query-string.c \ mime-node.c \ + crypto.c\ json.c notmuch_client_modules = $(notmuch_client_srcs:.c=.o) diff --git a/crypto.c b/crypto.c new file mode 100644 index 000..fbe5aeb --- /dev/null +++ b/crypto.c @@ -0,0 +1,71 @@ +/* notmuch - Not much of an email program, (just index and search) + * + * Copyright © 2012 Jameson Rollins + * + * 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/ . + * + * Authors: Jameson Rollins + */ + +#include "notmuch-client.h" + +/* for the specified protocol return the context pointer (initializing + * if needed) */ +notmuch_crypto_context_t * +notmuch_crypto_get_context (notmuch_crypto_t *crypto, const char *protocol) +{ +notmuch_crypto_context_t *cryptoctx = NULL; + +/* As per RFC 1847 section 2.1: "the [protocol] value token is + * comprised of the type and sub-type tokens of the Content-Type". + * As per RFC 1521 section 2: "Content-Type values, subtypes, and + * parameter names as defined in this document are + * case-insensitive." Thus, we use strcasecmp for the protocol. + */ +if ((strcasecmp (protocol, "application/pgp-signature") == 0) + || (strcasecmp (protocol, "application/pgp-encrypted") == 0)) { + if (!crypto->gpgctx) { +#ifdef GMIME_ATLEAST_26 + /* TODO: GMimePasswordRequestFunc */ + crypto->gpgctx = g_mime_gpg_context_new (NULL, "gpg"); +#else + GMimeSession* session = g_object_new (g_mime_session_get_type(), NULL); + crypto->gpgctx = g_mime_gpg_context_new (session, "gpg"); + g_object_unref (session); +#endif + if (crypto->gpgctx) { + g_mime_gpg_context_set_always_trust ((GMimeGpgContext*) crypto->gpgctx, FALSE); + } else { + fprintf (stderr, "Failed to construct gpg context.\n"); + } + } + cryptoctx = crypto->gpgctx; + +} else { + fprintf (stderr, "Unknown or unsupported cryptographic protocol.\n"); +} + +return cryptoctx; +} + +int +notmuch_crypto_cleanup (notmuch_crypto_t *crypto) +{ +if (crypto->gpgctx) { + g_object_unref (crypto->gpgctx); + crypto->gpgctx = NULL; +} + +return 0; +} diff --git a/notmuch-client.h b/notmuch-client.h index d377b04..6664075 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -77,6 +77,11 @@ typedef struct notmuch_show_format { const char *message_set_end; } notmuch_show_format_t; +typedef struct notmuch_crypto { +notmuch_crypto_context_t* gpgctx; +notmuch_bool_t decrypt; +} notmuch_crypto_t; + typedef struct notmuch_show_params { notmuch_bool_t entire_thread; notmuch_bool_t omit_excluded; @@ -112,6 +117,12 @@ chomp_newline (char *str) str[strlen(str)-1] = '\0'; } +notmuch_crypto_context_t * +notmuch_crypto_get_context (notmuch_crypto_t *crypto, const char *protocol); + +int +notmuch_crypto_cleanup (notmuch_crypto_t *crypto); + int notmuch_count_command (void *ctx, int argc, char *argv[]); -- 1.7.10 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v5 4/7] cli: modify mime_node_open to take new crypto struct as argument
This simplifies the interface considerably. --- mime-node.c |7 +++ notmuch-client.h | 10 +- notmuch-reply.c |6 ++ notmuch-show.c |3 +-- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/mime-node.c b/mime-node.c index a5645e5..67f4b16 100644 --- a/mime-node.c +++ b/mime-node.c @@ -57,8 +57,7 @@ _mime_node_context_free (mime_node_context_t *res) notmuch_status_t mime_node_open (const void *ctx, notmuch_message_t *message, - notmuch_crypto_context_t *cryptoctx, - notmuch_bool_t decrypt, mime_node_t **root_out) + notmuch_crypto_t *crypto, mime_node_t **root_out) { const char *filename = notmuch_message_get_filename (message); mime_node_context_t *mctx; @@ -110,8 +109,8 @@ mime_node_open (const void *ctx, notmuch_message_t *message, goto DONE; } -mctx->cryptoctx = cryptoctx; -mctx->decrypt = decrypt; +mctx->cryptoctx = crypto->gpgctx; +mctx->decrypt = crypto->decrypt; /* Create the root node */ root->part = GMIME_OBJECT (mctx->mime_message); diff --git a/notmuch-client.h b/notmuch-client.h index ead7fbd..962c747 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -350,9 +350,10 @@ struct mime_node { }; /* Construct a new MIME node pointing to the root message part of - * message. If cryptoctx is non-NULL, it will be used to verify - * signatures on any child parts. If decrypt is true, then cryptoctx - * will additionally be used to decrypt any encrypted child parts. + * message. If crypto->gpgctx is non-NULL, it will be used to verify + * signatures on any child parts. If crypto->decrypt is true, then + * crypto.gpgctx will additionally be used to decrypt any encrypted + * child parts. * * Return value: * @@ -364,8 +365,7 @@ struct mime_node { */ notmuch_status_t mime_node_open (const void *ctx, notmuch_message_t *message, - notmuch_crypto_context_t *cryptoctx, - notmuch_bool_t decrypt, mime_node_t **node_out); + notmuch_crypto_t *crypto, mime_node_t **node_out); /* Return a new MIME node for the requested child part of parent. * parent will be used as the talloc context for the returned child diff --git a/notmuch-reply.c b/notmuch-reply.c index 11f269f..6f368c9 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -575,8 +575,7 @@ notmuch_reply_format_default(void *ctx, g_object_unref (G_OBJECT (reply)); reply = NULL; - if (mime_node_open (ctx, message, params->crypto.gpgctx, params->crypto.decrypt, - &root) == NOTMUCH_STATUS_SUCCESS) { + if (mime_node_open (ctx, message, &(params->crypto), &root) == NOTMUCH_STATUS_SUCCESS) { format_part_reply (root); talloc_free (root); } @@ -605,8 +604,7 @@ notmuch_reply_format_json(void *ctx, messages = notmuch_query_search_messages (query); message = notmuch_messages_get (messages); -if (mime_node_open (ctx, message, params->crypto.gpgctx, params->crypto.decrypt, - &node) != NOTMUCH_STATUS_SUCCESS) +if (mime_node_open (ctx, message, &(params->crypto), &node) != NOTMUCH_STATUS_SUCCESS) return 1; reply = create_reply_message (ctx, config, message, reply_all); diff --git a/notmuch-show.c b/notmuch-show.c index cc509a6..fb5e9b6 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -810,8 +810,7 @@ show_message (void *ctx, mime_node_t *root, *part; notmuch_status_t status; -status = mime_node_open (local, message, params->crypto.gpgctx, -params->crypto.decrypt, &root); +status = mime_node_open (local, message, &(params->crypto), &root); if (status) goto DONE; part = mime_node_seek_dfs (root, (params->part < 0 ? 0 : params->part)); -- 1.7.10 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v5 7/7] cli: use new notmuch_crypto_get_context in mime-node.c
This has the affect of lazily creating the crypto contexts only when needed. This removes code duplication from notmuch-show and notmuch-reply, and should speed up these functions considerably if the crypto flags are provided but the messages don't have any cryptographic parts. --- mime-node.c | 20 ++-- notmuch-client.h |3 ++- notmuch-reply.c | 19 --- notmuch-show.c | 23 --- 4 files changed, 16 insertions(+), 49 deletions(-) diff --git a/mime-node.c b/mime-node.c index 73e28c5..97e8b48 100644 --- a/mime-node.c +++ b/mime-node.c @@ -150,6 +150,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) { mime_node_t *node = talloc_zero (parent, mime_node_t); GError *err = NULL; +notmuch_crypto_context_t *cryptoctx = NULL; /* Set basic node properties */ node->part = part; @@ -182,8 +183,15 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) return NULL; } +if ((GMIME_IS_MULTIPART_ENCRYPTED (part) && node->ctx->crypto->decrypt) + || (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->verify)) { + GMimeContentType *content_type = g_mime_object_get_content_type (part); + const char *protocol = g_mime_content_type_get_parameter (content_type, "protocol"); + cryptoctx = notmuch_crypto_get_context (node->ctx->crypto, protocol); +} + /* Handle PGP/MIME parts */ -if (GMIME_IS_MULTIPART_ENCRYPTED (part) && node->ctx->crypto->decrypt) { +if (GMIME_IS_MULTIPART_ENCRYPTED (part) && node->ctx->crypto->decrypt && cryptoctx) { if (node->nchildren != 2) { /* this violates RFC 3156 section 4, so we won't bother with it. */ fprintf (stderr, "Error: %d part(s) for a multipart/encrypted " @@ -196,10 +204,10 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) #ifdef GMIME_ATLEAST_26 GMimeDecryptResult *decrypt_result = NULL; node->decrypted_child = g_mime_multipart_encrypted_decrypt - (encrypteddata, node->ctx->crypto->gpgctx, &decrypt_result, &err); + (encrypteddata, cryptoctx, &decrypt_result, &err); #else node->decrypted_child = g_mime_multipart_encrypted_decrypt - (encrypteddata, node->ctx->crypto->gpgctx, &err); + (encrypteddata, cryptoctx, &err); #endif if (node->decrypted_child) { node->decrypt_success = node->verify_attempted = TRUE; @@ -217,7 +225,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) (err ? err->message : "no error explanation given")); } } -} else if (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->verify) { +} else if (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->verify && cryptoctx) { if (node->nchildren != 2) { /* this violates RFC 3156 section 5, so we won't bother with it. */ fprintf (stderr, "Error: %d part(s) for a multipart/signed message " @@ -226,7 +234,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) } else { #ifdef GMIME_ATLEAST_26 node->sig_list = g_mime_multipart_signed_verify - (GMIME_MULTIPART_SIGNED (part), node->ctx->crypto->gpgctx, &err); + (GMIME_MULTIPART_SIGNED (part), cryptoctx, &err); node->verify_attempted = TRUE; if (!node->sig_list) @@ -242,7 +250,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) * In GMime 2.6, they're both non-const, so we'll be able * to clean up this asymmetry. */ GMimeSignatureValidity *sig_validity = g_mime_multipart_signed_verify - (GMIME_MULTIPART_SIGNED (part), node->ctx->crypto->gpgctx, &err); + (GMIME_MULTIPART_SIGNED (part), cryptoctx, &err); node->verify_attempted = TRUE; node->sig_validity = sig_validity; if (sig_validity) { diff --git a/notmuch-client.h b/notmuch-client.h index 0f29a83..9b63eae 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -353,7 +353,8 @@ struct mime_node { /* Construct a new MIME node pointing to the root message part of * message. If crypto->verify is true, signed child parts will be * verified. If crypto->decrypt is true, encrypted child parts will be - * decrypted. + * decrypted. If crypto->gpgctx is NULL, it will be lazily + * initialized. * * Return value: * diff --git a/notmuch-reply.c b/notmuch-reply.c index 1ab3db9..3a038ed 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -741,25 +741,6 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) else reply_format_func = notmuch_reply_format_default; -if (params.crypto.decrypt) { -#ifdef GMIME_ATLEAST_26 - /* TODO: GMimePasswordRequestFunc */ - params.crypto.gpgctx = g_mime_gpg_context_new (NULL, "gpg"); -#else - GMimeSession* session = g_object
[PATCH v5 0/7] cli: improved crypto internals
I'm not going to claim this is the last version, but I think it addresses the remaining comments. I implemented Austin's of introducing a new type to handle the gmime 2.4/2.6 context incompatibility. jamie. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v5 5/7] cli: modify mime_node_context to use the new crypto struct
This simplifies some more interfaces. --- mime-node.c | 18 -- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/mime-node.c b/mime-node.c index 67f4b16..a838224 100644 --- a/mime-node.c +++ b/mime-node.c @@ -33,8 +33,7 @@ typedef struct mime_node_context { GMimeMessage *mime_message; /* Context provided by the caller. */ -notmuch_crypto_context_t *cryptoctx; -notmuch_bool_t decrypt; +notmuch_crypto_t *crypto; } mime_node_context_t; static int @@ -109,8 +108,7 @@ mime_node_open (const void *ctx, notmuch_message_t *message, goto DONE; } -mctx->cryptoctx = crypto->gpgctx; -mctx->decrypt = crypto->decrypt; +mctx->crypto = crypto; /* Create the root node */ root->part = GMIME_OBJECT (mctx->mime_message); @@ -186,7 +184,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) /* Handle PGP/MIME parts */ if (GMIME_IS_MULTIPART_ENCRYPTED (part) - && node->ctx->cryptoctx && node->ctx->decrypt) { + && node->ctx->crypto->gpgctx && node->ctx->crypto->decrypt) { if (node->nchildren != 2) { /* this violates RFC 3156 section 4, so we won't bother with it. */ fprintf (stderr, "Error: %d part(s) for a multipart/encrypted " @@ -199,10 +197,10 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) #ifdef GMIME_ATLEAST_26 GMimeDecryptResult *decrypt_result = NULL; node->decrypted_child = g_mime_multipart_encrypted_decrypt - (encrypteddata, node->ctx->cryptoctx, &decrypt_result, &err); + (encrypteddata, node->ctx->crypto->gpgctx, &decrypt_result, &err); #else node->decrypted_child = g_mime_multipart_encrypted_decrypt - (encrypteddata, node->ctx->cryptoctx, &err); + (encrypteddata, node->ctx->crypto->gpgctx, &err); #endif if (node->decrypted_child) { node->decrypt_success = node->verify_attempted = TRUE; @@ -220,7 +218,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) (err ? err->message : "no error explanation given")); } } -} else if (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->cryptoctx) { +} else if (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->gpgctx) { if (node->nchildren != 2) { /* this violates RFC 3156 section 5, so we won't bother with it. */ fprintf (stderr, "Error: %d part(s) for a multipart/signed message " @@ -229,7 +227,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) } else { #ifdef GMIME_ATLEAST_26 node->sig_list = g_mime_multipart_signed_verify - (GMIME_MULTIPART_SIGNED (part), node->ctx->cryptoctx, &err); + (GMIME_MULTIPART_SIGNED (part), node->ctx->crypto->gpgctx, &err); node->verify_attempted = TRUE; if (!node->sig_list) @@ -245,7 +243,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) * In GMime 2.6, they're both non-const, so we'll be able * to clean up this asymmetry. */ GMimeSignatureValidity *sig_validity = g_mime_multipart_signed_verify - (GMIME_MULTIPART_SIGNED (part), node->ctx->cryptoctx, &err); + (GMIME_MULTIPART_SIGNED (part), node->ctx->crypto->gpgctx, &err); node->verify_attempted = TRUE; node->sig_validity = sig_validity; if (sig_validity) { -- 1.7.10 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v5 3/7] cli: modify show and reply to use new crypto struct
notmuch_show_params_t is modified to use the new notmuch_crypto_t, and notmuch-show and notmuch-reply are modified accordingly. --- notmuch-client.h |3 +-- notmuch-reply.c | 29 - notmuch-show.c | 30 +- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/notmuch-client.h b/notmuch-client.h index 6664075..ead7fbd 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -87,8 +87,7 @@ typedef struct notmuch_show_params { notmuch_bool_t omit_excluded; notmuch_bool_t raw; int part; -notmuch_crypto_context_t* cryptoctx; -notmuch_bool_t decrypt; +notmuch_crypto_t crypto; } notmuch_show_params_t; /* There's no point in continuing when we've detected that we've done diff --git a/notmuch-reply.c b/notmuch-reply.c index 0f92a2e..11f269f 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -575,7 +575,7 @@ notmuch_reply_format_default(void *ctx, g_object_unref (G_OBJECT (reply)); reply = NULL; - if (mime_node_open (ctx, message, params->cryptoctx, params->decrypt, + if (mime_node_open (ctx, message, params->crypto.gpgctx, params->crypto.decrypt, &root) == NOTMUCH_STATUS_SUCCESS) { format_part_reply (root); talloc_free (root); @@ -605,7 +605,7 @@ notmuch_reply_format_json(void *ctx, messages = notmuch_query_search_messages (query); message = notmuch_messages_get (messages); -if (mime_node_open (ctx, message, params->cryptoctx, params->decrypt, +if (mime_node_open (ctx, message, params->crypto.gpgctx, params->crypto.decrypt, &node) != NOTMUCH_STATUS_SUCCESS) return 1; @@ -706,7 +706,12 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) char *query_string; int opt_index, ret = 0; int (*reply_format_func)(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params, notmuch_bool_t reply_all); -notmuch_show_params_t params = { .part = -1 }; +notmuch_show_params_t params = { + .part = -1, + .crypto = { + .decrypt = FALSE + } +}; int format = FORMAT_DEFAULT; int reply_all = TRUE; @@ -720,7 +725,7 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) (notmuch_keyword_t []){ { "all", TRUE }, { "sender", FALSE }, { 0, 0 } } }, - { NOTMUCH_OPT_BOOLEAN, ¶ms.decrypt, "decrypt", 'd', 0 }, + { NOTMUCH_OPT_BOOLEAN, ¶ms.crypto.decrypt, "decrypt", 'd', 0 }, { 0, 0, 0, 0, 0 } }; @@ -737,18 +742,18 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) else reply_format_func = notmuch_reply_format_default; -if (params.decrypt) { +if (params.crypto.decrypt) { #ifdef GMIME_ATLEAST_26 /* TODO: GMimePasswordRequestFunc */ - params.cryptoctx = g_mime_gpg_context_new (NULL, "gpg"); + params.crypto.gpgctx = g_mime_gpg_context_new (NULL, "gpg"); #else GMimeSession* session = g_object_new (g_mime_session_get_type(), NULL); - params.cryptoctx = g_mime_gpg_context_new (session, "gpg"); + params.crypto.gpgctx = g_mime_gpg_context_new (session, "gpg"); #endif - if (params.cryptoctx) { - g_mime_gpg_context_set_always_trust ((GMimeGpgContext*) params.cryptoctx, FALSE); + if (params.crypto.gpgctx) { + g_mime_gpg_context_set_always_trust ((GMimeGpgContext*) params.crypto.gpgctx, FALSE); } else { - params.decrypt = FALSE; + params.crypto.decrypt = FALSE; fprintf (stderr, "Failed to construct gpg context.\n"); } #ifndef GMIME_ATLEAST_26 @@ -784,11 +789,9 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) if (reply_format_func (ctx, config, query, ¶ms, reply_all) != 0) return 1; +notmuch_crypto_cleanup (¶ms.crypto); notmuch_query_destroy (query); notmuch_database_destroy (notmuch); -if (params.cryptoctx) - g_object_unref(params.cryptoctx); - return ret; } diff --git a/notmuch-show.c b/notmuch-show.c index 95427d4..cc509a6 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -810,8 +810,8 @@ show_message (void *ctx, mime_node_t *root, *part; notmuch_status_t status; -status = mime_node_open (local, message, params->cryptoctx, -params->decrypt, &root); +status = mime_node_open (local, message, params->crypto.gpgctx, +params->crypto.decrypt, &root); if (status) goto DONE; part = mime_node_seek_dfs (root, (params->part < 0 ? 0 : params->part)); @@ -984,7 +984,13 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) char *query_string; int opt_index, ret; const notmuch_show_format_t *format = &format_text; -notmuch_show_params_t params = { .part = -1, .om
[PATCH v5 1/7] cli: use new typedef to deal with gmime 2.4/2.6 context incompatibility
gmime 2.4 defines GMimeCipherContext, while 2.6 defines GMimeCryptoContext. typedef them both to notmuch_crypto_context_t to cover this discrepancy and remove a bunch of #ifdefs. --- mime-node.c | 12 ++-- notmuch-client.h | 15 +-- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/mime-node.c b/mime-node.c index a95bdab..a5645e5 100644 --- a/mime-node.c +++ b/mime-node.c @@ -33,11 +33,7 @@ typedef struct mime_node_context { GMimeMessage *mime_message; /* Context provided by the caller. */ -#ifdef GMIME_ATLEAST_26 -GMimeCryptoContext *cryptoctx; -#else -GMimeCipherContext *cryptoctx; -#endif +notmuch_crypto_context_t *cryptoctx; notmuch_bool_t decrypt; } mime_node_context_t; @@ -61,11 +57,7 @@ _mime_node_context_free (mime_node_context_t *res) notmuch_status_t mime_node_open (const void *ctx, notmuch_message_t *message, -#ifdef GMIME_ATLEAST_26 - GMimeCryptoContext *cryptoctx, -#else - GMimeCipherContext *cryptoctx, -#endif + notmuch_crypto_context_t *cryptoctx, notmuch_bool_t decrypt, mime_node_t **root_out) { const char *filename = notmuch_message_get_filename (message); diff --git a/notmuch-client.h b/notmuch-client.h index 19b7f01..d377b04 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -36,6 +36,9 @@ * these to check the version number. */ #ifdef GMIME_MAJOR_VERSION #define GMIME_ATLEAST_26 +typedef GMimeCryptoContext notmuch_crypto_context_t; +#else +typedef GMimeCipherContext notmuch_crypto_context_t; #endif #include "notmuch.h" @@ -79,11 +82,7 @@ typedef struct notmuch_show_params { notmuch_bool_t omit_excluded; notmuch_bool_t raw; int part; -#ifdef GMIME_ATLEAST_26 -GMimeCryptoContext* cryptoctx; -#else -GMimeCipherContext* cryptoctx; -#endif +notmuch_crypto_context_t* cryptoctx; notmuch_bool_t decrypt; } notmuch_show_params_t; @@ -355,11 +354,7 @@ struct mime_node { */ notmuch_status_t mime_node_open (const void *ctx, notmuch_message_t *message, -#ifdef GMIME_ATLEAST_26 - GMimeCryptoContext *cryptoctx, -#else - GMimeCipherContext *cryptoctx, -#endif + notmuch_crypto_context_t *cryptoctx, notmuch_bool_t decrypt, mime_node_t **node_out); /* Return a new MIME node for the requested child part of parent. -- 1.7.10 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v5 7/7] cli: use new notmuch_crypto_get_context in mime-node.c
This has the affect of lazily creating the crypto contexts only when needed. This removes code duplication from notmuch-show and notmuch-reply, and should speed up these functions considerably if the crypto flags are provided but the messages don't have any cryptographic parts. --- mime-node.c | 20 ++-- notmuch-client.h |3 ++- notmuch-reply.c | 19 --- notmuch-show.c | 23 --- 4 files changed, 16 insertions(+), 49 deletions(-) diff --git a/mime-node.c b/mime-node.c index 73e28c5..97e8b48 100644 --- a/mime-node.c +++ b/mime-node.c @@ -150,6 +150,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) { mime_node_t *node = talloc_zero (parent, mime_node_t); GError *err = NULL; +notmuch_crypto_context_t *cryptoctx = NULL; /* Set basic node properties */ node->part = part; @@ -182,8 +183,15 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) return NULL; } +if ((GMIME_IS_MULTIPART_ENCRYPTED (part) && node->ctx->crypto->decrypt) + || (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->verify)) { + GMimeContentType *content_type = g_mime_object_get_content_type (part); + const char *protocol = g_mime_content_type_get_parameter (content_type, "protocol"); + cryptoctx = notmuch_crypto_get_context (node->ctx->crypto, protocol); +} + /* Handle PGP/MIME parts */ -if (GMIME_IS_MULTIPART_ENCRYPTED (part) && node->ctx->crypto->decrypt) { +if (GMIME_IS_MULTIPART_ENCRYPTED (part) && node->ctx->crypto->decrypt && cryptoctx) { if (node->nchildren != 2) { /* this violates RFC 3156 section 4, so we won't bother with it. */ fprintf (stderr, "Error: %d part(s) for a multipart/encrypted " @@ -196,10 +204,10 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) #ifdef GMIME_ATLEAST_26 GMimeDecryptResult *decrypt_result = NULL; node->decrypted_child = g_mime_multipart_encrypted_decrypt - (encrypteddata, node->ctx->crypto->gpgctx, &decrypt_result, &err); + (encrypteddata, cryptoctx, &decrypt_result, &err); #else node->decrypted_child = g_mime_multipart_encrypted_decrypt - (encrypteddata, node->ctx->crypto->gpgctx, &err); + (encrypteddata, cryptoctx, &err); #endif if (node->decrypted_child) { node->decrypt_success = node->verify_attempted = TRUE; @@ -217,7 +225,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) (err ? err->message : "no error explanation given")); } } -} else if (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->verify) { +} else if (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->verify && cryptoctx) { if (node->nchildren != 2) { /* this violates RFC 3156 section 5, so we won't bother with it. */ fprintf (stderr, "Error: %d part(s) for a multipart/signed message " @@ -226,7 +234,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) } else { #ifdef GMIME_ATLEAST_26 node->sig_list = g_mime_multipart_signed_verify - (GMIME_MULTIPART_SIGNED (part), node->ctx->crypto->gpgctx, &err); + (GMIME_MULTIPART_SIGNED (part), cryptoctx, &err); node->verify_attempted = TRUE; if (!node->sig_list) @@ -242,7 +250,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) * In GMime 2.6, they're both non-const, so we'll be able * to clean up this asymmetry. */ GMimeSignatureValidity *sig_validity = g_mime_multipart_signed_verify - (GMIME_MULTIPART_SIGNED (part), node->ctx->crypto->gpgctx, &err); + (GMIME_MULTIPART_SIGNED (part), cryptoctx, &err); node->verify_attempted = TRUE; node->sig_validity = sig_validity; if (sig_validity) { diff --git a/notmuch-client.h b/notmuch-client.h index 0f29a83..9b63eae 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -353,7 +353,8 @@ struct mime_node { /* Construct a new MIME node pointing to the root message part of * message. If crypto->verify is true, signed child parts will be * verified. If crypto->decrypt is true, encrypted child parts will be - * decrypted. + * decrypted. If crypto->gpgctx is NULL, it will be lazily + * initialized. * * Return value: * diff --git a/notmuch-reply.c b/notmuch-reply.c index 1ab3db9..3a038ed 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -741,25 +741,6 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) else reply_format_func = notmuch_reply_format_default; -if (params.crypto.decrypt) { -#ifdef GMIME_ATLEAST_26 - /* TODO: GMimePasswordRequestFunc */ - params.crypto.gpgctx = g_mime_gpg_context_new (NULL, "gpg"); -#else - GMimeSession* session = g_object_new
[PATCH v5 6/7] cli: new crypto verify flag to handle verification
Use this flag rather than depend on the existence of an initialized gpgctx, to determine whether we should verify a multipart/signed. We will be moving to create the ctx lazily, so we don't want to depend on it being previously initialized if it's not needed. --- mime-node.c |5 ++--- notmuch-client.h |8 notmuch-reply.c |1 + notmuch-show.c | 14 +++--- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/mime-node.c b/mime-node.c index a838224..73e28c5 100644 --- a/mime-node.c +++ b/mime-node.c @@ -183,8 +183,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) } /* Handle PGP/MIME parts */ -if (GMIME_IS_MULTIPART_ENCRYPTED (part) - && node->ctx->crypto->gpgctx && node->ctx->crypto->decrypt) { +if (GMIME_IS_MULTIPART_ENCRYPTED (part) && node->ctx->crypto->decrypt) { if (node->nchildren != 2) { /* this violates RFC 3156 section 4, so we won't bother with it. */ fprintf (stderr, "Error: %d part(s) for a multipart/encrypted " @@ -218,7 +217,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) (err ? err->message : "no error explanation given")); } } -} else if (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->gpgctx) { +} else if (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->verify) { if (node->nchildren != 2) { /* this violates RFC 3156 section 5, so we won't bother with it. */ fprintf (stderr, "Error: %d part(s) for a multipart/signed message " diff --git a/notmuch-client.h b/notmuch-client.h index 962c747..0f29a83 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -79,6 +79,7 @@ typedef struct notmuch_show_format { typedef struct notmuch_crypto { notmuch_crypto_context_t* gpgctx; +notmuch_bool_t verify; notmuch_bool_t decrypt; } notmuch_crypto_t; @@ -350,10 +351,9 @@ struct mime_node { }; /* Construct a new MIME node pointing to the root message part of - * message. If crypto->gpgctx is non-NULL, it will be used to verify - * signatures on any child parts. If crypto->decrypt is true, then - * crypto.gpgctx will additionally be used to decrypt any encrypted - * child parts. + * message. If crypto->verify is true, signed child parts will be + * verified. If crypto->decrypt is true, encrypted child parts will be + * decrypted. * * Return value: * diff --git a/notmuch-reply.c b/notmuch-reply.c index 6f368c9..1ab3db9 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -707,6 +707,7 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) notmuch_show_params_t params = { .part = -1, .crypto = { + .verify = FALSE, .decrypt = FALSE } }; diff --git a/notmuch-show.c b/notmuch-show.c index fb5e9b6..3c06792 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -987,11 +987,11 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) .part = -1, .omit_excluded = TRUE, .crypto = { + .verify = FALSE, .decrypt = FALSE } }; int format_sel = NOTMUCH_FORMAT_NOT_SPECIFIED; -notmuch_bool_t verify = FALSE; int exclude = EXCLUDE_TRUE; notmuch_opt_desc_t options[] = { @@ -1008,7 +1008,7 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) { NOTMUCH_OPT_INT, ¶ms.part, "part", 'p', 0 }, { NOTMUCH_OPT_BOOLEAN, ¶ms.entire_thread, "entire-thread", 't', 0 }, { NOTMUCH_OPT_BOOLEAN, ¶ms.crypto.decrypt, "decrypt", 'd', 0 }, - { NOTMUCH_OPT_BOOLEAN, &verify, "verify", 'v', 0 }, + { NOTMUCH_OPT_BOOLEAN, ¶ms.crypto.verify, "verify", 'v', 0 }, { 0, 0, 0, 0, 0 } }; @@ -1018,6 +1018,10 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) return 1; } +/* decryption implies verification */ +if (params.crypto.decrypt) + params.crypto.verify = TRUE; + if (format_sel == NOTMUCH_FORMAT_NOT_SPECIFIED) { /* if part was requested and format was not specified, use format=raw */ if (params.part >= 0) @@ -1052,7 +1056,7 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) break; } -if (params.crypto.decrypt || verify) { +if (params.crypto.decrypt || params.crypto.verify) { #ifdef GMIME_ATLEAST_26 /* TODO: GMimePasswordRequestFunc */ params.crypto.gpgctx = g_mime_gpg_context_new (NULL, "gpg"); @@ -1063,6 +1067,10 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) if (params.crypto.gpgctx) { g_mime_gpg_context_set_always_trust ((GMimeGpgContext*) params.crypto.gpgctx, FALSE); } else { + /* If we fail to create the gpgctx set the verify and +* decrypt flags to FALSE so we don't try to do any +* further verification or decryption */ +
[PATCH v5 5/7] cli: modify mime_node_context to use the new crypto struct
This simplifies some more interfaces. --- mime-node.c | 18 -- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/mime-node.c b/mime-node.c index 67f4b16..a838224 100644 --- a/mime-node.c +++ b/mime-node.c @@ -33,8 +33,7 @@ typedef struct mime_node_context { GMimeMessage *mime_message; /* Context provided by the caller. */ -notmuch_crypto_context_t *cryptoctx; -notmuch_bool_t decrypt; +notmuch_crypto_t *crypto; } mime_node_context_t; static int @@ -109,8 +108,7 @@ mime_node_open (const void *ctx, notmuch_message_t *message, goto DONE; } -mctx->cryptoctx = crypto->gpgctx; -mctx->decrypt = crypto->decrypt; +mctx->crypto = crypto; /* Create the root node */ root->part = GMIME_OBJECT (mctx->mime_message); @@ -186,7 +184,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) /* Handle PGP/MIME parts */ if (GMIME_IS_MULTIPART_ENCRYPTED (part) - && node->ctx->cryptoctx && node->ctx->decrypt) { + && node->ctx->crypto->gpgctx && node->ctx->crypto->decrypt) { if (node->nchildren != 2) { /* this violates RFC 3156 section 4, so we won't bother with it. */ fprintf (stderr, "Error: %d part(s) for a multipart/encrypted " @@ -199,10 +197,10 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) #ifdef GMIME_ATLEAST_26 GMimeDecryptResult *decrypt_result = NULL; node->decrypted_child = g_mime_multipart_encrypted_decrypt - (encrypteddata, node->ctx->cryptoctx, &decrypt_result, &err); + (encrypteddata, node->ctx->crypto->gpgctx, &decrypt_result, &err); #else node->decrypted_child = g_mime_multipart_encrypted_decrypt - (encrypteddata, node->ctx->cryptoctx, &err); + (encrypteddata, node->ctx->crypto->gpgctx, &err); #endif if (node->decrypted_child) { node->decrypt_success = node->verify_attempted = TRUE; @@ -220,7 +218,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) (err ? err->message : "no error explanation given")); } } -} else if (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->cryptoctx) { +} else if (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->gpgctx) { if (node->nchildren != 2) { /* this violates RFC 3156 section 5, so we won't bother with it. */ fprintf (stderr, "Error: %d part(s) for a multipart/signed message " @@ -229,7 +227,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) } else { #ifdef GMIME_ATLEAST_26 node->sig_list = g_mime_multipart_signed_verify - (GMIME_MULTIPART_SIGNED (part), node->ctx->cryptoctx, &err); + (GMIME_MULTIPART_SIGNED (part), node->ctx->crypto->gpgctx, &err); node->verify_attempted = TRUE; if (!node->sig_list) @@ -245,7 +243,7 @@ _mime_node_create (mime_node_t *parent, GMimeObject *part) * In GMime 2.6, they're both non-const, so we'll be able * to clean up this asymmetry. */ GMimeSignatureValidity *sig_validity = g_mime_multipart_signed_verify - (GMIME_MULTIPART_SIGNED (part), node->ctx->cryptoctx, &err); + (GMIME_MULTIPART_SIGNED (part), node->ctx->crypto->gpgctx, &err); node->verify_attempted = TRUE; node->sig_validity = sig_validity; if (sig_validity) { -- 1.7.10
[PATCH v5 4/7] cli: modify mime_node_open to take new crypto struct as argument
This simplifies the interface considerably. --- mime-node.c |7 +++ notmuch-client.h | 10 +- notmuch-reply.c |6 ++ notmuch-show.c |3 +-- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/mime-node.c b/mime-node.c index a5645e5..67f4b16 100644 --- a/mime-node.c +++ b/mime-node.c @@ -57,8 +57,7 @@ _mime_node_context_free (mime_node_context_t *res) notmuch_status_t mime_node_open (const void *ctx, notmuch_message_t *message, - notmuch_crypto_context_t *cryptoctx, - notmuch_bool_t decrypt, mime_node_t **root_out) + notmuch_crypto_t *crypto, mime_node_t **root_out) { const char *filename = notmuch_message_get_filename (message); mime_node_context_t *mctx; @@ -110,8 +109,8 @@ mime_node_open (const void *ctx, notmuch_message_t *message, goto DONE; } -mctx->cryptoctx = cryptoctx; -mctx->decrypt = decrypt; +mctx->cryptoctx = crypto->gpgctx; +mctx->decrypt = crypto->decrypt; /* Create the root node */ root->part = GMIME_OBJECT (mctx->mime_message); diff --git a/notmuch-client.h b/notmuch-client.h index ead7fbd..962c747 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -350,9 +350,10 @@ struct mime_node { }; /* Construct a new MIME node pointing to the root message part of - * message. If cryptoctx is non-NULL, it will be used to verify - * signatures on any child parts. If decrypt is true, then cryptoctx - * will additionally be used to decrypt any encrypted child parts. + * message. If crypto->gpgctx is non-NULL, it will be used to verify + * signatures on any child parts. If crypto->decrypt is true, then + * crypto.gpgctx will additionally be used to decrypt any encrypted + * child parts. * * Return value: * @@ -364,8 +365,7 @@ struct mime_node { */ notmuch_status_t mime_node_open (const void *ctx, notmuch_message_t *message, - notmuch_crypto_context_t *cryptoctx, - notmuch_bool_t decrypt, mime_node_t **node_out); + notmuch_crypto_t *crypto, mime_node_t **node_out); /* Return a new MIME node for the requested child part of parent. * parent will be used as the talloc context for the returned child diff --git a/notmuch-reply.c b/notmuch-reply.c index 11f269f..6f368c9 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -575,8 +575,7 @@ notmuch_reply_format_default(void *ctx, g_object_unref (G_OBJECT (reply)); reply = NULL; - if (mime_node_open (ctx, message, params->crypto.gpgctx, params->crypto.decrypt, - &root) == NOTMUCH_STATUS_SUCCESS) { + if (mime_node_open (ctx, message, &(params->crypto), &root) == NOTMUCH_STATUS_SUCCESS) { format_part_reply (root); talloc_free (root); } @@ -605,8 +604,7 @@ notmuch_reply_format_json(void *ctx, messages = notmuch_query_search_messages (query); message = notmuch_messages_get (messages); -if (mime_node_open (ctx, message, params->crypto.gpgctx, params->crypto.decrypt, - &node) != NOTMUCH_STATUS_SUCCESS) +if (mime_node_open (ctx, message, &(params->crypto), &node) != NOTMUCH_STATUS_SUCCESS) return 1; reply = create_reply_message (ctx, config, message, reply_all); diff --git a/notmuch-show.c b/notmuch-show.c index cc509a6..fb5e9b6 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -810,8 +810,7 @@ show_message (void *ctx, mime_node_t *root, *part; notmuch_status_t status; -status = mime_node_open (local, message, params->crypto.gpgctx, -params->crypto.decrypt, &root); +status = mime_node_open (local, message, &(params->crypto), &root); if (status) goto DONE; part = mime_node_seek_dfs (root, (params->part < 0 ? 0 : params->part)); -- 1.7.10
[PATCH v5 3/7] cli: modify show and reply to use new crypto struct
notmuch_show_params_t is modified to use the new notmuch_crypto_t, and notmuch-show and notmuch-reply are modified accordingly. --- notmuch-client.h |3 +-- notmuch-reply.c | 29 - notmuch-show.c | 30 +- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/notmuch-client.h b/notmuch-client.h index 6664075..ead7fbd 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -87,8 +87,7 @@ typedef struct notmuch_show_params { notmuch_bool_t omit_excluded; notmuch_bool_t raw; int part; -notmuch_crypto_context_t* cryptoctx; -notmuch_bool_t decrypt; +notmuch_crypto_t crypto; } notmuch_show_params_t; /* There's no point in continuing when we've detected that we've done diff --git a/notmuch-reply.c b/notmuch-reply.c index 0f92a2e..11f269f 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -575,7 +575,7 @@ notmuch_reply_format_default(void *ctx, g_object_unref (G_OBJECT (reply)); reply = NULL; - if (mime_node_open (ctx, message, params->cryptoctx, params->decrypt, + if (mime_node_open (ctx, message, params->crypto.gpgctx, params->crypto.decrypt, &root) == NOTMUCH_STATUS_SUCCESS) { format_part_reply (root); talloc_free (root); @@ -605,7 +605,7 @@ notmuch_reply_format_json(void *ctx, messages = notmuch_query_search_messages (query); message = notmuch_messages_get (messages); -if (mime_node_open (ctx, message, params->cryptoctx, params->decrypt, +if (mime_node_open (ctx, message, params->crypto.gpgctx, params->crypto.decrypt, &node) != NOTMUCH_STATUS_SUCCESS) return 1; @@ -706,7 +706,12 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) char *query_string; int opt_index, ret = 0; int (*reply_format_func)(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params, notmuch_bool_t reply_all); -notmuch_show_params_t params = { .part = -1 }; +notmuch_show_params_t params = { + .part = -1, + .crypto = { + .decrypt = FALSE + } +}; int format = FORMAT_DEFAULT; int reply_all = TRUE; @@ -720,7 +725,7 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) (notmuch_keyword_t []){ { "all", TRUE }, { "sender", FALSE }, { 0, 0 } } }, - { NOTMUCH_OPT_BOOLEAN, ¶ms.decrypt, "decrypt", 'd', 0 }, + { NOTMUCH_OPT_BOOLEAN, ¶ms.crypto.decrypt, "decrypt", 'd', 0 }, { 0, 0, 0, 0, 0 } }; @@ -737,18 +742,18 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) else reply_format_func = notmuch_reply_format_default; -if (params.decrypt) { +if (params.crypto.decrypt) { #ifdef GMIME_ATLEAST_26 /* TODO: GMimePasswordRequestFunc */ - params.cryptoctx = g_mime_gpg_context_new (NULL, "gpg"); + params.crypto.gpgctx = g_mime_gpg_context_new (NULL, "gpg"); #else GMimeSession* session = g_object_new (g_mime_session_get_type(), NULL); - params.cryptoctx = g_mime_gpg_context_new (session, "gpg"); + params.crypto.gpgctx = g_mime_gpg_context_new (session, "gpg"); #endif - if (params.cryptoctx) { - g_mime_gpg_context_set_always_trust ((GMimeGpgContext*) params.cryptoctx, FALSE); + if (params.crypto.gpgctx) { + g_mime_gpg_context_set_always_trust ((GMimeGpgContext*) params.crypto.gpgctx, FALSE); } else { - params.decrypt = FALSE; + params.crypto.decrypt = FALSE; fprintf (stderr, "Failed to construct gpg context.\n"); } #ifndef GMIME_ATLEAST_26 @@ -784,11 +789,9 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) if (reply_format_func (ctx, config, query, ¶ms, reply_all) != 0) return 1; +notmuch_crypto_cleanup (¶ms.crypto); notmuch_query_destroy (query); notmuch_database_destroy (notmuch); -if (params.cryptoctx) - g_object_unref(params.cryptoctx); - return ret; } diff --git a/notmuch-show.c b/notmuch-show.c index 95427d4..cc509a6 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -810,8 +810,8 @@ show_message (void *ctx, mime_node_t *root, *part; notmuch_status_t status; -status = mime_node_open (local, message, params->cryptoctx, -params->decrypt, &root); +status = mime_node_open (local, message, params->crypto.gpgctx, +params->crypto.decrypt, &root); if (status) goto DONE; part = mime_node_seek_dfs (root, (params->part < 0 ? 0 : params->part)); @@ -984,7 +984,13 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) char *query_string; int opt_index, ret; const notmuch_show_format_t *format = &format_text; -notmuch_show_params_t params = { .part = -1, .omit_exclude
[PATCH v5 2/7] cli: new crypto structure to store crypto contexts and parameters, and functions to support it
This new structure, notmuch_crypto_t, keeps all relevant crypto contexts and parameters together, and will make it easier to pass the stuff around and clean it up. The name of the crypto context inside this new struct will change, to reflect that it is actually a GPG context, which is a sub type of Crypto context. There are other types of Crypto contexts (Pkcs7 in particular, which we hope to support) so we want to be clear. The new crypto.c contains functions to return the proper context from the struct for a given protocol (and initialize it if needed), and to cleanup a struct by releasing the crypto contexts. --- Makefile.local |1 + crypto.c | 71 ++ notmuch-client.h | 11 + 3 files changed, 83 insertions(+) create mode 100644 crypto.c diff --git a/Makefile.local b/Makefile.local index 53b4a0d..a890df2 100644 --- a/Makefile.local +++ b/Makefile.local @@ -292,6 +292,7 @@ notmuch_client_srcs = \ notmuch-time.c \ query-string.c \ mime-node.c \ + crypto.c\ json.c notmuch_client_modules = $(notmuch_client_srcs:.c=.o) diff --git a/crypto.c b/crypto.c new file mode 100644 index 000..fbe5aeb --- /dev/null +++ b/crypto.c @@ -0,0 +1,71 @@ +/* notmuch - Not much of an email program, (just index and search) + * + * Copyright ? 2012 Jameson Rollins + * + * 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/ . + * + * Authors: Jameson Rollins + */ + +#include "notmuch-client.h" + +/* for the specified protocol return the context pointer (initializing + * if needed) */ +notmuch_crypto_context_t * +notmuch_crypto_get_context (notmuch_crypto_t *crypto, const char *protocol) +{ +notmuch_crypto_context_t *cryptoctx = NULL; + +/* As per RFC 1847 section 2.1: "the [protocol] value token is + * comprised of the type and sub-type tokens of the Content-Type". + * As per RFC 1521 section 2: "Content-Type values, subtypes, and + * parameter names as defined in this document are + * case-insensitive." Thus, we use strcasecmp for the protocol. + */ +if ((strcasecmp (protocol, "application/pgp-signature") == 0) + || (strcasecmp (protocol, "application/pgp-encrypted") == 0)) { + if (!crypto->gpgctx) { +#ifdef GMIME_ATLEAST_26 + /* TODO: GMimePasswordRequestFunc */ + crypto->gpgctx = g_mime_gpg_context_new (NULL, "gpg"); +#else + GMimeSession* session = g_object_new (g_mime_session_get_type(), NULL); + crypto->gpgctx = g_mime_gpg_context_new (session, "gpg"); + g_object_unref (session); +#endif + if (crypto->gpgctx) { + g_mime_gpg_context_set_always_trust ((GMimeGpgContext*) crypto->gpgctx, FALSE); + } else { + fprintf (stderr, "Failed to construct gpg context.\n"); + } + } + cryptoctx = crypto->gpgctx; + +} else { + fprintf (stderr, "Unknown or unsupported cryptographic protocol.\n"); +} + +return cryptoctx; +} + +int +notmuch_crypto_cleanup (notmuch_crypto_t *crypto) +{ +if (crypto->gpgctx) { + g_object_unref (crypto->gpgctx); + crypto->gpgctx = NULL; +} + +return 0; +} diff --git a/notmuch-client.h b/notmuch-client.h index d377b04..6664075 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -77,6 +77,11 @@ typedef struct notmuch_show_format { const char *message_set_end; } notmuch_show_format_t; +typedef struct notmuch_crypto { +notmuch_crypto_context_t* gpgctx; +notmuch_bool_t decrypt; +} notmuch_crypto_t; + typedef struct notmuch_show_params { notmuch_bool_t entire_thread; notmuch_bool_t omit_excluded; @@ -112,6 +117,12 @@ chomp_newline (char *str) str[strlen(str)-1] = '\0'; } +notmuch_crypto_context_t * +notmuch_crypto_get_context (notmuch_crypto_t *crypto, const char *protocol); + +int +notmuch_crypto_cleanup (notmuch_crypto_t *crypto); + int notmuch_count_command (void *ctx, int argc, char *argv[]); -- 1.7.10
[PATCH v5 1/7] cli: use new typedef to deal with gmime 2.4/2.6 context incompatibility
gmime 2.4 defines GMimeCipherContext, while 2.6 defines GMimeCryptoContext. typedef them both to notmuch_crypto_context_t to cover this discrepancy and remove a bunch of #ifdefs. --- mime-node.c | 12 ++-- notmuch-client.h | 15 +-- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/mime-node.c b/mime-node.c index a95bdab..a5645e5 100644 --- a/mime-node.c +++ b/mime-node.c @@ -33,11 +33,7 @@ typedef struct mime_node_context { GMimeMessage *mime_message; /* Context provided by the caller. */ -#ifdef GMIME_ATLEAST_26 -GMimeCryptoContext *cryptoctx; -#else -GMimeCipherContext *cryptoctx; -#endif +notmuch_crypto_context_t *cryptoctx; notmuch_bool_t decrypt; } mime_node_context_t; @@ -61,11 +57,7 @@ _mime_node_context_free (mime_node_context_t *res) notmuch_status_t mime_node_open (const void *ctx, notmuch_message_t *message, -#ifdef GMIME_ATLEAST_26 - GMimeCryptoContext *cryptoctx, -#else - GMimeCipherContext *cryptoctx, -#endif + notmuch_crypto_context_t *cryptoctx, notmuch_bool_t decrypt, mime_node_t **root_out) { const char *filename = notmuch_message_get_filename (message); diff --git a/notmuch-client.h b/notmuch-client.h index 19b7f01..d377b04 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -36,6 +36,9 @@ * these to check the version number. */ #ifdef GMIME_MAJOR_VERSION #define GMIME_ATLEAST_26 +typedef GMimeCryptoContext notmuch_crypto_context_t; +#else +typedef GMimeCipherContext notmuch_crypto_context_t; #endif #include "notmuch.h" @@ -79,11 +82,7 @@ typedef struct notmuch_show_params { notmuch_bool_t omit_excluded; notmuch_bool_t raw; int part; -#ifdef GMIME_ATLEAST_26 -GMimeCryptoContext* cryptoctx; -#else -GMimeCipherContext* cryptoctx; -#endif +notmuch_crypto_context_t* cryptoctx; notmuch_bool_t decrypt; } notmuch_show_params_t; @@ -355,11 +354,7 @@ struct mime_node { */ notmuch_status_t mime_node_open (const void *ctx, notmuch_message_t *message, -#ifdef GMIME_ATLEAST_26 - GMimeCryptoContext *cryptoctx, -#else - GMimeCipherContext *cryptoctx, -#endif + notmuch_crypto_context_t *cryptoctx, notmuch_bool_t decrypt, mime_node_t **node_out); /* Return a new MIME node for the requested child part of parent. -- 1.7.10
[PATCH v5 0/7] cli: improved crypto internals
I'm not going to claim this is the last version, but I think it addresses the remaining comments. I implemented Austin's of introducing a new type to handle the gmime 2.4/2.6 context incompatibility. jamie.
[PATCH v4 2/4] cli: make --entire-thread=false work for format=json.
Mark Walters writes: > On Sat, 26 May 2012, Peter Wang wrote: >> On Tue, 24 Apr 2012 10:11:13 +0100, Mark Walters > gmail.com> wrote: > > It is easy to change the keyword parsing code to allow this: I include a > first draft of such a patch below. This would allow the solution you > suggest and thus avoid the hack/abuse. What do people think? > It didn't carefully review it, but it looks sane enough at a quick glance. d
Re: [PATCH 1/2] Makefile.local: added checks for latest NEWS title
Tomi Ollila writes: > Added target `verify-version-news` which checks that the first line > in NEWS file has the following properties: > First word is 'Notmuch' > Second "word" matches the current version > Rest of line is in format (201[2-9]-[01][0-9]-[0-3][0-9] I appreciate the effort, but I wonder if it is worth complicating the build system further? I'm willing to be swayed either way. d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v4 2/4] cli: make --entire-thread=false work for format=json.
On Sat, 26 May 2012, Peter Wang wrote: > On Tue, 24 Apr 2012 10:11:13 +0100, Mark Walters gmail.com> wrote: >> The --entire-thread option in notmuch-show.c defaults to true when >> format=json. Previously there was no way to turn this off. This patch >> makes it respect --entire-thread=false. >> >> The one subtlety is that we initialise a notmuch_bool_t to -1 to >> indicate that the option parsing has not set it. This allows the code >> to distinguish between the option being omitted from the command line, >> and the option being set to false on the command line. >> --- >> notmuch-show.c | 16 ++-- >> 1 files changed, 14 insertions(+), 2 deletions(-) >> >> diff --git a/notmuch-show.c b/notmuch-show.c >> index 0d21f1a..48551bb 100644 >> --- a/notmuch-show.c >> +++ b/notmuch-show.c >> @@ -996,7 +996,13 @@ notmuch_show_command (void *ctx, unused (int argc), >> unused (char *argv[])) >> char *query_string; >> int opt_index, ret; >> const notmuch_show_format_t *format = &format_text; >> -notmuch_show_params_t params = { .part = -1, .omit_excluded = TRUE }; >> + >> +/* We abuse the notmuch_bool_t variable params.entire-thread by >> + * setting it to -1 to denote that the command line parsing has >> + * not set it. We ensure it is set to TRUE or FALSE before passing >> + * it to any other function.*/ >> +notmuch_show_params_t params = { .part = -1, .entire_thread = -1 }; >> + >> int format_sel = NOTMUCH_FORMAT_NOT_SPECIFIED; >> notmuch_bool_t verify = FALSE; >> int exclude = EXCLUDE_TRUE; > > Hi Mark, > > As an alternative to the abuse, could you just treat it as with exclude, > using an enum with three values (TRUE|FALSE|DEFAULT)? > Then set params.entire_thread afterwards. The reason I haven't done this is that the current command line parser does not allow keyword options to take default values: in other words --entire-thread without an "=" would not be allowed. It is easy to change the keyword parsing code to allow this: I include a first draft of such a patch below. This would allow the solution you suggest and thus avoid the hack/abuse. What do people think? Best wishes Mark --- command-line-arguments.c | 13 ++--- 1 files changed, 10 insertions(+), 3 deletions(-) diff --git a/command-line-arguments.c b/command-line-arguments.c index 76b185f..d40c7e6 100644 --- a/command-line-arguments.c +++ b/command-line-arguments.c @@ -11,10 +11,16 @@ */ static notmuch_bool_t -_process_keyword_arg (const notmuch_opt_desc_t *arg_desc, const char *arg_str) { +_process_keyword_arg (const notmuch_opt_desc_t *arg_desc, char next, const char *arg_str) { const notmuch_keyword_t *keywords = arg_desc->keywords; +if (next == 0) { +/* No keyword given so return first option as default */ + *((int *)arg_desc->output_var) = keywords->value; + return TRUE; +} + while (keywords->name) { if (strcmp (arg_str, keywords->name) == 0) { if (arg_desc->output_var) { @@ -99,7 +105,8 @@ parse_option (const char *arg, */ if (next != '=' && next != ':' && next != 0) return FALSE; if (next == 0) { - if (try->opt_type != NOTMUCH_OPT_BOOLEAN) + if (try->opt_type != NOTMUCH_OPT_BOOLEAN && + try->opt_type != NOTMUCH_OPT_KEYWORD) return FALSE; } else { if (value[0] == 0) return FALSE; @@ -110,7 +117,7 @@ parse_option (const char *arg, switch (try->opt_type) { case NOTMUCH_OPT_KEYWORD: - return _process_keyword_arg (try, value); + return _process_keyword_arg (try, next, value); break; case NOTMUCH_OPT_BOOLEAN: return _process_boolean_arg (try, next, value); -- 1.7.9.1
[PATCH v5 5/5] emacs: make elide messages use notmuch-show for omitting messages.
Previously the elide messages code got the entire-thread from notmuch-show.c and then threw away all non-matching messages. This version calls notmuch-show.c without the --entire-thread flag so it never receives the non-matching messages in the first place. This makes it substantially faster. --- emacs/notmuch-show.el | 18 ++ 1 files changed, 10 insertions(+), 8 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index d318430..9cc68be 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -958,9 +958,9 @@ message at DEPTH in the current thread." "Insert the message tree TREE at depth DEPTH in the current thread." (let ((msg (car tree)) (replies (cadr tree))) -(if (or (not notmuch-show-elide-non-matching-messages) - (plist-get msg :match)) - (notmuch-show-insert-msg msg depth)) +;; We test whether there is a message or just some replies. +(when msg + (notmuch-show-insert-msg msg depth)) (notmuch-show-insert-thread replies (1+ depth (defun notmuch-show-insert-thread (thread depth) @@ -1041,16 +1041,18 @@ function is used." (args (if notmuch-show-query-context (append (list "\'") basic-args (list "and (" notmuch-show-query-context ")\'")) -(append (list "\'") basic-args (list "\'") - (notmuch-show-insert-forest (notmuch-query-get-threads -(cons "--exclude=false" args))) +(append (list "\'") basic-args (list "\'" +(cli-args (cons "--exclude=false" +(when notmuch-show-elide-non-matching-messages + (list "--entire-thread=false") + + (notmuch-show-insert-forest (notmuch-query-get-threads (append cli-args args))) ;; If the query context reduced the results to nothing, run ;; the basic query. (when (and (eq (buffer-size) 0) notmuch-show-query-context) (notmuch-show-insert-forest - (notmuch-query-get-threads - (cons "--exclude=false" basic-args) + (notmuch-query-get-threads (append cli-args basic-args) (jit-lock-register #'notmuch-show-buttonise-links) -- 1.7.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v5 3/5] cli: make --entire-thread=false work for format=json.
The --entire-thread option in notmuch-show.c defaults to true when format=json. Previously there was no way to turn this off. This patch makes it respect --entire-thread=false. To do this the patch moves the --entire-thread option to be a keyword option using the new command line parsing to allow the existing --entire-thread syntax to keep working. --- notmuch-show.c | 25 +++-- 1 files changed, 23 insertions(+), 2 deletions(-) diff --git a/notmuch-show.c b/notmuch-show.c index 97da5cc..207093a 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -981,6 +981,12 @@ enum { NOTMUCH_FORMAT_RAW }; +enum { +ENTIRE_THREAD_DEFAULT, +ENTIRE_THREAD_TRUE, +ENTIRE_THREAD_FALSE, +}; + /* The following is to allow future options to be added more easily */ enum { EXCLUDE_TRUE, @@ -1000,6 +1006,7 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) int format_sel = NOTMUCH_FORMAT_NOT_SPECIFIED; notmuch_bool_t verify = FALSE; int exclude = EXCLUDE_TRUE; +int entire_thread = ENTIRE_THREAD_DEFAULT; notmuch_opt_desc_t options[] = { { NOTMUCH_OPT_KEYWORD, &format_sel, "format", 'f', @@ -1012,8 +1019,11 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) (notmuch_keyword_t []){ { "true", EXCLUDE_TRUE }, { "false", EXCLUDE_FALSE }, { 0, 0 } } }, +{ NOTMUCH_OPT_KEYWORD, &entire_thread, "entire-thread", 't', + (notmuch_keyword_t []){ { "true", ENTIRE_THREAD_TRUE }, + { "false", ENTIRE_THREAD_FALSE }, + { 0, 0 } } }, { NOTMUCH_OPT_INT, ¶ms.part, "part", 'p', 0 }, - { NOTMUCH_OPT_BOOLEAN, ¶ms.entire_thread, "entire-thread", 't', 0 }, { NOTMUCH_OPT_BOOLEAN, ¶ms.decrypt, "decrypt", 'd', 0 }, { NOTMUCH_OPT_BOOLEAN, &verify, "verify", 'v', 0 }, { 0, 0, 0, 0, 0 } @@ -1036,7 +1046,9 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) switch (format_sel) { case NOTMUCH_FORMAT_JSON: format = &format_json; - params.entire_thread = TRUE; + /* JSON defaults to entire-thread TRUE */ + if (entire_thread == ENTIRE_THREAD_DEFAULT) + entire_thread = ENTIRE_THREAD_TRUE; break; case NOTMUCH_FORMAT_TEXT: format = &format_text; @@ -1058,6 +1070,15 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) params.raw = TRUE; break; } +/* Default is entire-thread = FALSE except for format=json which + * is dealt with above. */ +if (entire_thread == ENTIRE_THREAD_DEFAULT) + entire_thread = ENTIRE_THREAD_FALSE; + +if (entire_thread == ENTIRE_THREAD_TRUE) + params.entire_thread = TRUE; +else + params.entire_thread = FALSE; if (params.decrypt || verify) { #ifdef GMIME_ATLEAST_26 -- 1.7.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v5 4/5] Update devel/schemata for --entire-thread=false
Also remove the Json --entire-thread item from devel/TODO. --- devel/TODO |2 -- devel/schemata |2 +- 2 files changed, 1 insertions(+), 3 deletions(-) diff --git a/devel/TODO b/devel/TODO index 7b750af..eb757af 100644 --- a/devel/TODO +++ b/devel/TODO @@ -92,8 +92,6 @@ and email address in the From: line. We could also then easily support "notmuch compose --from " to support getting at alternate email addresses. -Fix the --format=json option to not imply --entire-thread. - Implement "notmuch search --exclude-threads=" to allow for excluding muted threads, (and any other negative, thread-based filtering that the user wants to do). diff --git a/devel/schemata b/devel/schemata index 977cea7..8fcab8e 100644 --- a/devel/schemata +++ b/devel/schemata @@ -32,7 +32,7 @@ thread = [thread_node*] # A message and its replies (show_messages) thread_node = [ -message?, # present if --entire-thread or matched +message?, # null if not matched and not --entire-thread [thread_node*]# children of message ] -- 1.7.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v5 1/5] cli: command line parsing: allow default for keyword options
This changes the parsing for "keyword" options so that if the option is specified with no argument the first possible argument is chosen. This make it easier to add options to existing boolean arguments (the existing --option can default to TRUE). --- command-line-arguments.c | 13 ++--- 1 files changed, 10 insertions(+), 3 deletions(-) diff --git a/command-line-arguments.c b/command-line-arguments.c index 76b185f..d40c7e6 100644 --- a/command-line-arguments.c +++ b/command-line-arguments.c @@ -11,10 +11,16 @@ */ static notmuch_bool_t -_process_keyword_arg (const notmuch_opt_desc_t *arg_desc, const char *arg_str) { +_process_keyword_arg (const notmuch_opt_desc_t *arg_desc, char next, const char *arg_str) { const notmuch_keyword_t *keywords = arg_desc->keywords; +if (next == 0) { +/* No keyword given so return first option as default */ + *((int *)arg_desc->output_var) = keywords->value; + return TRUE; +} + while (keywords->name) { if (strcmp (arg_str, keywords->name) == 0) { if (arg_desc->output_var) { @@ -99,7 +105,8 @@ parse_option (const char *arg, */ if (next != '=' && next != ':' && next != 0) return FALSE; if (next == 0) { - if (try->opt_type != NOTMUCH_OPT_BOOLEAN) + if (try->opt_type != NOTMUCH_OPT_BOOLEAN && + try->opt_type != NOTMUCH_OPT_KEYWORD) return FALSE; } else { if (value[0] == 0) return FALSE; @@ -110,7 +117,7 @@ parse_option (const char *arg, switch (try->opt_type) { case NOTMUCH_OPT_KEYWORD: - return _process_keyword_arg (try, value); + return _process_keyword_arg (try, next, value); break; case NOTMUCH_OPT_BOOLEAN: return _process_boolean_arg (try, next, value); -- 1.7.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v5 2/5] cli: Let json output "null" messages for non --entire-thread
All formats except Json can output empty messages for non entire-thread, but in Json format we output "null" to keep the other elements (e.g. the replies to the omitted message) in the correct place. --- notmuch-client.h |1 + notmuch-show.c | 20 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/notmuch-client.h b/notmuch-client.h index 19b7f01..08540a7 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -72,6 +72,7 @@ typedef struct notmuch_show_format { const struct notmuch_show_params *params); const char *message_set_sep; const char *message_set_end; +const char *null_message; } notmuch_show_format_t; typedef struct notmuch_show_params { diff --git a/notmuch-show.c b/notmuch-show.c index 95427d4..97da5cc 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -37,7 +37,8 @@ static const notmuch_show_format_t format_json = { .message_set_start = "[", .part = format_part_json_entry, .message_set_sep = ", ", -.message_set_end = "]" +.message_set_end = "]", +.null_message = "null" }; static notmuch_status_t @@ -800,6 +801,15 @@ format_part_raw (unused (const void *ctx), mime_node_t *node, } static notmuch_status_t +show_null_message (const notmuch_show_format_t *format) +{ +/* Output a null message. Currently empty for all formats except Json */ +if (format->null_message) + printf ("%s", format->null_message); +return NOTMUCH_STATUS_SUCCESS; +} + +static notmuch_status_t show_message (void *ctx, const notmuch_show_format_t *format, notmuch_message_t *message, @@ -862,11 +872,13 @@ show_messages (void *ctx, if (status && !res) res = status; next_indent = indent + 1; - - if (!status && format->message_set_sep) - fputs (format->message_set_sep, stdout); + } else { + status = show_null_message (format); } + if (!status && format->message_set_sep) + fputs (format->message_set_sep, stdout); + status = show_messages (ctx, format, notmuch_message_get_replies (message), -- 1.7.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v5 0/5] Allow JSON to use non-entire thread, and use for elide
This is version 5 of this patch series: version 4 is at id:"1335258675-29439-1-git-send-email-markwalters1...@gmail.com". This version changes the way the command-line parser deals with keywords so that specifying --option without an = returns the first option. This means that boolean options can easily have extra options added without breaking the existing syntax. Patch 3/5 takes advantage of this new feature to implement the --entire-thread option to notmuch-show in a non-hacky way. Best wishes Mark Mark Walters (5): cli: command line parsing: allow default for keyword options cli: Let json output "null" messages for non --entire-thread cli: make --entire-thread=false work for format=json. Update devel/schemata for --entire-thread=false emacs: make elide messages use notmuch-show for omitting messages. command-line-arguments.c | 13 ++--- devel/TODO |2 -- devel/schemata |2 +- emacs/notmuch-show.el| 18 ++ notmuch-client.h |1 + notmuch-show.c | 45 +++-- 6 files changed, 61 insertions(+), 20 deletions(-) -- 1.7.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 2/2] Makefile.local: added verify-version-news to verify-no-dirty-code deps.
Added `verify-version-news` to the end of `verify-no-dirty-code` dependencies so it is part of release testing checks. --- Tested by executing the following commands: make verify-source-tree-and-version make verify-source-tree-and-version VERSION=0.13 make verify-source-tree-and-version VERSION=0.12 Makefile.local |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Makefile.local b/Makefile.local index 1b34c00..94a3a70 100644 --- a/Makefile.local +++ b/Makefile.local @@ -187,7 +187,7 @@ release-message: verify-source-tree-and-version: verify-no-dirty-code .PHONY: verify-no-dirty-code -verify-no-dirty-code: verify-version-debian verify-version-python verify-version-manpage +verify-no-dirty-code: verify-version-debian verify-version-python verify-version-manpage verify-version-news ifeq ($(IS_GIT),yes) @printf "Checking that source tree is clean..." ifneq ($(shell git ls-files -m),) -- 1.7.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 1/2] Makefile.local: added checks for latest NEWS title
Added target `verify-version-news` which checks that the first line in NEWS file has the following properties: First word is 'Notmuch' Second "word" matches the current version Rest of line is in format (201[2-9]-[01][0-9]-[0-3][0-9] --- Tested by executing the following commands: make verify-version-news make verify-version-news VERSION=0.13 make verify-version-news VERSION=0.12 Makefile.local | 15 +++ 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/Makefile.local b/Makefile.local index 53b4a0d..1b34c00 100644 --- a/Makefile.local +++ b/Makefile.local @@ -220,6 +220,21 @@ verify-version-python: verify-version-components echo "Please edit version and $(PV_FILE) to have consistent versions." && false) @echo "Good." +.PHONY: verify-version-news +verify-version-news: verify-version-components + @read notmuch version date < NEWS ;\ + ev=0 ;\ + echo -n "Checking that this is 'Notmuch' NEWS..." ;\ + if [ "$$notmuch" = 'Notmuch' ]; then echo 'Good.' ;\ + else echo 'No.'; ev=1; fi ;\ + echo -n "Checking that NEWS version is $(VERSION)..." ;\ + if [ "$$version" = '$(VERSION)' ]; then echo 'Good.' ;\ + else echo 'No.'; ev=1; fi ;\ + echo -n "Checking that NEWS date is in correct format..." ;\ + case $$date in '('201[2-9]-[0-1][0-9]-[0-3][0-9]')') echo 'Good.' ;;\ + *) echo 'No.'; ev=1; esac ;\ + if [ $$ev -ne 0 ]; then echo "Please edit NEWS file to have Notmuch header line in correct format."; false; fi + .PHONY: verify-version-components verify-version-components: @echo -n "Checking that $(VERSION) consists only of digits and periods..." -- 1.7.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v4 2/4] cli: make --entire-thread=false work for format=json.
Mark Walters writes: > On Sat, 26 May 2012, Peter Wang wrote: >> On Tue, 24 Apr 2012 10:11:13 +0100, Mark Walters >> wrote: > > It is easy to change the keyword parsing code to allow this: I include a > first draft of such a patch below. This would allow the solution you > suggest and thus avoid the hack/abuse. What do people think? > It didn't carefully review it, but it looks sane enough at a quick glance. d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
FreeBSD Support Patches
Mike Kelly writes: > On Fri, May 25, 2012 at 10:15 AM, Dmitry Kurochkin > wrote: >> Why do we need to explicitly declare Emacs dependency for tests? ?There >> should be no need for it. ?We have "implicit" dependencies which are >> declared once (see test_declare_external_prereq calls at the end of >> test-lib.sh) and are automatically handled when a test tries to use a >> missing binary. ?Explicit dependencies are hard to maintain (e.g. your >> patch adds explicit emacs dependency for crypto test but misses gpg). >> With rare exceptions we should not use explicit dependencies. > > Because not every test actually has those implicit dependencies. For > example, some of the crypto tests depend upon emacs_deliver_message > working correctly for subsequents tests. Those emacs_deliver_message > tests are skipped, but not the ones after it that try to do something > with that injected message. > > For the emacs-* test files, there are some tests that act the same > way. These subtests do not directly depend on Emacs. They depend on other subtests. Currently, we do not support such dependencies. But what you propose is not the solution. We have two options here: make all subtests independent or introduce proper subtests dependencies. The former might require many changes to existing tests and may be hard to enforce. The latter is not trivial as well but is doable. I planned to implement subtests dependencies but never really got to it (and I do not think I will anytime soon). > However, it is also a minor speed improvement to say that, > obviously, none of the emacs tests are going to work, so just don't > bother. > I do not think maintaining an explicit list of dependencies worth a minor speed improvement. Given all above, I understand that your patches fix a common problem in a simple way. And it does not look like we would get proper solution anytime soon. So I am ok with these patches with two comments: * Provide a proper commit message to explain the issue in more detail. * Add an XXX comment for each explicit dependency, something like: // XXX: Workaround for subtests that depend on other subtests (and, // hence, indirectly depend on emacs). Should be removed when we // have proper subtests dependencies. Regards, Dmitry > -- > Mike Kelly
Re: [PATCH 03/10] Fix compilation of smtp-dummy on FreeBSD
On May 25, 2012 4:44 PM, "Mike Kelly" wrote: > > --- > test/smtp-dummy.c |5 - > 1 file changed, 4 insertions(+), 1 deletion(-) > > diff --git a/test/smtp-dummy.c b/test/smtp-dummy.c > index 3801a5e..aa82fa1 100644 > --- a/test/smtp-dummy.c > +++ b/test/smtp-dummy.c > @@ -33,11 +33,14 @@ > * have been warned. > */ > > +#define _GNU_SOURCE /* for getline */ First of all, thanks for sharing your work. Independent of this patch, I've been thinking about defining _GNU_SOURCE in the makefile. I don't think it's very elegant to #define it everywhere. It would also pave the way towards building with -pedantic (and possibly -std=c99) in a portable way. For example, the compat test code #defines _GNU_SOURCE while the actual code does not, which I think is an error. I'll look into this after the weekend (unless you beat me to it). BR, Jani. > #include > #include > #include > #include > -#include > +#include > +#include > +#include > #include > #include > > -- > 1.7.10.2 > > ___ > 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 v4 2/4] cli: make --entire-thread=false work for format=json.
On Sat, 26 May 2012, Peter Wang wrote: > On Tue, 24 Apr 2012 10:11:13 +0100, Mark Walters > wrote: >> The --entire-thread option in notmuch-show.c defaults to true when >> format=json. Previously there was no way to turn this off. This patch >> makes it respect --entire-thread=false. >> >> The one subtlety is that we initialise a notmuch_bool_t to -1 to >> indicate that the option parsing has not set it. This allows the code >> to distinguish between the option being omitted from the command line, >> and the option being set to false on the command line. >> --- >> notmuch-show.c | 16 ++-- >> 1 files changed, 14 insertions(+), 2 deletions(-) >> >> diff --git a/notmuch-show.c b/notmuch-show.c >> index 0d21f1a..48551bb 100644 >> --- a/notmuch-show.c >> +++ b/notmuch-show.c >> @@ -996,7 +996,13 @@ notmuch_show_command (void *ctx, unused (int argc), >> unused (char *argv[])) >> char *query_string; >> int opt_index, ret; >> const notmuch_show_format_t *format = &format_text; >> -notmuch_show_params_t params = { .part = -1, .omit_excluded = TRUE }; >> + >> +/* We abuse the notmuch_bool_t variable params.entire-thread by >> + * setting it to -1 to denote that the command line parsing has >> + * not set it. We ensure it is set to TRUE or FALSE before passing >> + * it to any other function.*/ >> +notmuch_show_params_t params = { .part = -1, .entire_thread = -1 }; >> + >> int format_sel = NOTMUCH_FORMAT_NOT_SPECIFIED; >> notmuch_bool_t verify = FALSE; >> int exclude = EXCLUDE_TRUE; > > Hi Mark, > > As an alternative to the abuse, could you just treat it as with exclude, > using an enum with three values (TRUE|FALSE|DEFAULT)? > Then set params.entire_thread afterwards. The reason I haven't done this is that the current command line parser does not allow keyword options to take default values: in other words --entire-thread without an "=" would not be allowed. It is easy to change the keyword parsing code to allow this: I include a first draft of such a patch below. This would allow the solution you suggest and thus avoid the hack/abuse. What do people think? Best wishes Mark --- command-line-arguments.c | 13 ++--- 1 files changed, 10 insertions(+), 3 deletions(-) diff --git a/command-line-arguments.c b/command-line-arguments.c index 76b185f..d40c7e6 100644 --- a/command-line-arguments.c +++ b/command-line-arguments.c @@ -11,10 +11,16 @@ */ static notmuch_bool_t -_process_keyword_arg (const notmuch_opt_desc_t *arg_desc, const char *arg_str) { +_process_keyword_arg (const notmuch_opt_desc_t *arg_desc, char next, const char *arg_str) { const notmuch_keyword_t *keywords = arg_desc->keywords; +if (next == 0) { +/* No keyword given so return first option as default */ + *((int *)arg_desc->output_var) = keywords->value; + return TRUE; +} + while (keywords->name) { if (strcmp (arg_str, keywords->name) == 0) { if (arg_desc->output_var) { @@ -99,7 +105,8 @@ parse_option (const char *arg, */ if (next != '=' && next != ':' && next != 0) return FALSE; if (next == 0) { - if (try->opt_type != NOTMUCH_OPT_BOOLEAN) + if (try->opt_type != NOTMUCH_OPT_BOOLEAN && + try->opt_type != NOTMUCH_OPT_KEYWORD) return FALSE; } else { if (value[0] == 0) return FALSE; @@ -110,7 +117,7 @@ parse_option (const char *arg, switch (try->opt_type) { case NOTMUCH_OPT_KEYWORD: - return _process_keyword_arg (try, value); + return _process_keyword_arg (try, next, value); break; case NOTMUCH_OPT_BOOLEAN: return _process_boolean_arg (try, next, value); -- 1.7.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch