ANNOUNCE: nottoomuch-addresses.pl
In addition to http://notmuchmail.org/emacstips/#index11h2 and Jani's 'goobook' in id:87zkfuh3i0@nikula.org you can now also use http://www.iki.fi/too/nottoomuch/nottoomuch-addresses.pl for your address completion needs when composing mail/reply. This program is 1) easy to install and 2) pretty fast to use when completing. How to install 1) Download the program from above url on the machine you're running notmuch and find suitable location to it. 2) Verify it's sha1 checksum is 125f3917b3f2dc68bdf30af04ab623d53321e50c 3) chmod 755 /path/to/nottoomuch-addresses.pl 4) Run /path/to/nottoomuch-addresses.pl --update When run first time this gathers email addresses from all of your mail. This may take a long while to complete -- depends on the amount of email you have. Further --updates are much faster as those just take addresses from new mail. 5) Test that it works: Run /path/to/nottoomuch-addresses.pl notmuchmail 6) In case you're using emacs mua with notmuch, edit your notmuch configuration for emacs with the following content: (require 'notmuch-address) (setq notmuch-address-command /path/to/nottoomuch-addresses.pl) (notmuch-address-message-insinuate) 7) Restart emacs notmuch mua (or eval above lines) and start composing new mail. When adding recipient to To: field. press TAB after 3 or more characters have been added. In case you get 2 or more address matches, use arrow keys in minibuffer to choose desired recipient... 8) Enjoy! /path/to/nottoomuch-addresses.pl --help provides more detailed information. BR, Tomi ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
python-notmuch crash with threads
Hi, I've been seeing a race with python-notmuch, where it will crash due to pointers being invalidated when threads are used. I've attached a script which shows the problem some of the time. It's about the smallest script I can make, but it's hampered by the fact that making it simpler seems to make the race less likely, so it's hard to know when it is gone. The typical backtrace is: Program terminated with signal 11, Segmentation fault. #0 0x7f7b19c34b59 in talloc_named_const () from /usr/lib/x86_64-linux-gnu/libtalloc.so.2 (gdb) up #1 0x7f7b1a5f78dc in notmuch_query_search_threads (query=0x14001c70) at lib/query.cc:322 322 lib/query.cc: No such file or directory. in lib/query.cc (gdb) p *query Cannot access memory at address 0x14001c70 Where something is invalidating the pointer between creation in db.create_query() and calling it in query.search_threads() I've seen other similar things when using other code in the thread. http://talloc.samba.org/talloc/doc/html/index.html talks about the thread-safety of talloc, and I don't think it's any of those issues here. Any suggestions for how to debug this further would be most welcome. Thanks, James import threading class NotmuchThread(threading.Thread): def __init__(self): super(NotmuchThread, self).__init__() self.job_waiting = threading.Condition() self.job_queue = [] def run(self): from notmuch.database import Database self.db = Database() job = None print Aquiring lock with self.job_waiting: if len(self.job_queue) 1: print Job queue empty so waiting while True: ready = self.job_waiting.wait(1) if ready: break if len(self.job_queue) 0: break print Got job, releasing lock self.search_threads(tag:inbox) def search_threads(self, query_string): query = self.db.create_query(query_string) print(%X % query._query) threads = query.search_threads() return threads test_thread = NotmuchThread() test_thread.start() with test_thread.job_waiting: test_thread.job_queue.append() test_thread.job_waiting.notify() import time; time.sleep(1) test_thread.join() ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: ANNOUNCE: nottoomuch-addresses.pl
Hi Tomi, I have had a quick try of setting up nottoomuch-addresses addresses. Here are a couple of issues I have hit and I think it's still not quite right. I attach the shell output from emacs below. - firstly it appears that if the term is set to DUMB then the script assumes it's being called from emacs and exits if there is no search string. This is problematic for me as I run all my stuff including the --update command from a shell. - The instructions don't tell you to create the .config/nottoomuch directory. Perhaps you could check for it's existance and create if required? - Even when I got this far I had an odd result when running the script as shown below. First time I got a strange error. Second run it added 900 or so addresses. Subsiquent runs added no more addresses. I find this strange as I have over 180k emails. Anyway great work. Heading in a cool direction. Hope this somewhat rambling report helps. Bart bart@bit:~$ bart@bit:~$shasum ~/bin/nottoomuch-addresses.pl 125f3917b3f2dc68bdf30af04ab623d53321e50c /Users/bart/bin/nottoomuch-addresses.pl bart@bit:~$chmod 755 ~/bin/nottoomuch-addresses.pl bart@bit:~$~/bin/nottoomuch-addresses.pl --update Cannot open database, maybe not created yet. run /Users/bart/bin/nottoomuch-addresses.pl --update from command line first. bart@bit:~$cd bart@bit:~$cd .config bash: cd: .config: No such file or directory bart@bit:~$ bart@bit:~$mkdir .config bart@bit:~$nottoomuch --update bash: nottoomuch: command not found bart@bit:~$~/bin/nottoomuch-addresses.pl --update Cannot open database, maybe not created yet. run /Users/bart/bin/nottoomuch-addresses.pl --update from command line first. bart@bit:~$ bart@bit:~$cd bart@bit:~$cd .config bart@bit:~/.config$mkdir nottoomuch bart@bit:~/.config$ bart@bit:~/.config$~/bin/nottoomuch-addresses.pl --update Cannot open database, maybe not created yet. run /Users/bart/bin/nottoomuch-addresses.pl --update from command line first. bart@bit:~/.config$cd nottoomuch/ bart@bit:~/.config/nottoomuch$touch addresses bart@bit:~/.config/nottoomuch$~/bin/nottoomuch-addresses.pl --update bart@bit:~/.config/nottoomuch$ls addresses bart@bit:~/.config/nottoomuch$ls -s addresses 0 addresses bart@bit:~/.config/nottoomuch$echo $TERM dumb bart@bit:~/.config/nottoomuch$export TERM=emacs bart@bit:~/.config/nottoomuch$ls -s addresses 0 addresses bart@bit:~/.config/nottoomuch$~/bin/nottoomuch-addresses.pl --update Updating '/Users/bart/.config/nottoomuch/addresses', since -604800. Unrecognized option: -604800.. Added 0 addresses in 0 seconds. Total number of addresses: 0. bart@bit:~/.config/nottoomuch$~/bin/nottoomuch-addresses.pl --update Updating '/Users/bart/.config/nottoomuch/addresses', since 1322159542. Added 993 addresses in 4 seconds. Total number of addresses: 993. bart@bit:~/.config/nottoomuch$~/bin/nottoomuch-addresses.pl --update Updating '/Users/bart/.config/nottoomuch/addresses', since 1322159560. Added 0 addresses in 1 seconds. Total number of addresses: 993. bart@bit:~/.config/nottoomuch$ On Thu, 01 Dec 2011 17:36:24 +0200, Tomi Ollila tomi.oll...@iki.fi wrote: ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Bugs on adding flag D
Hi, I've a recurrent problem on syncing. To solve it, I've to remove internal files (rm -rf ~/.offlineimap/) and mails in .Sent folder. With offlineimap 6.3.5-rc1, the output is the following : Account sync toto_irisa: * Processing account toto_irisa Copying folder structure from IMAP to Maildir Establishing connection to zimbra.inria.fr:993. Folder sync [toto_irisa]: Syncing INBOX: IMAP - Maildir Syncing Drafts: IMAP - Maildir Syncing Sent: IMAP - Maildir Adding flag D to 1 messages on Sent ERROR [InstanceLimitedThread(Folder sync [toto_irisa], started daemon 140489914951424)]: Syncing folder .Sent [acc: toto_irisa] Error with store: UID STORE failed ERROR [InstanceLimitedThread(Folder sync [toto_irisa], started daemon 140489914951424)]: ERROR in syncfolder for toto_irisa folder .Sent: Traceback (most recent call last): File /home/toto/comp/offlineimap/offlineimap/accounts.py, line 358, in syncfolder localfolder.syncmessagesto(remotefolder, statusfolder) File /home/toto/comp/offlineimap/offlineimap/folder/Base.py, line 431, in syncmessagesto action(dstfolder, statusfolder) File /home/toto/comp/offlineimap/offlineimap/folder/Base.py, line 388, in syncmessagesto_flags dstfolder.addmessagesflags(uids, set(flag)) File /home/toto/comp/offlineimap/offlineimap/folder/IMAP.py, line 627, in addmessagesflags self.addmessagesflags_noconvert(uidlist, flags) File /home/toto/comp/offlineimap/offlineimap/folder/IMAP.py, line 621, in addmessagesflags_noconvert self.processmessagesflags('+', uidlist, flags) File /home/toto/comp/offlineimap/offlineimap/folder/IMAP.py, line 653, in processmessagesflags assert r[0] == 'OK', 'Error with store: ' + '. '.join(r[1]) AssertionError: Error with store: UID STORE failed Error with store: UID STORE failed Syncing Trash: IMAP - Maildir Account sync toto_irisa: * Finished processing account toto_irisa ERROR: Exceptions occurred during the run! ERROR: Syncing folder .Sent [acc: toto_irisa] Error with store: UID STORE failed ERROR: ERROR in syncfolder for toto_irisa folder .Sent: Traceback (most recent call last): File /home/toto/comp/offlineimap/offlineimap/accounts.py, line 358, in syncfolder localfolder.syncmessagesto(remotefolder, statusfolder) File /home/toto/comp/offlineimap/offlineimap/folder/Base.py, line 431, in syncmessagesto action(dstfolder, statusfolder) File /home/toto/comp/offlineimap/offlineimap/folder/Base.py, line 388, in syncmessagesto_flags dstfolder.addmessagesflags(uids, set(flag)) File /home/toto/comp/offlineimap/offlineimap/folder/IMAP.py, line 627, in addmessagesflags self.addmessagesflags_noconvert(uidlist, flags) File /home/toto/comp/offlineimap/offlineimap/folder/IMAP.py, line 621, in addmessagesflags_noconvert self.processmessagesflags('+', uidlist, flags) File /home/toto/comp/offlineimap/offlineimap/folder/IMAP.py, line 653, in processmessagesflags assert r[0] == 'OK', 'Error with store: ' + '. '.join(r[1]) AssertionError: Error with store: UID STORE failed Error with store: UID STORE failed Of course, I can give you more detailled information if you need it. Dal. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 1/2] python: add classes to wrap all notmuch_*_t types
On Mon, 28 Nov 2011 13:36:44 +0100, Justus Winter wrote: Well, quoting my commit message: Add type information to the ctypes._FuncPtr wrappers and use the wrapper classes instead of c_void_p for pointers to notmuch_*_t. This enables the ctypes library to type check parameters being handed to functions from the notmuch library. This strikes me as a rather good thing, so the patches went in. Sebastian pgp6adgNBIklt.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: python-notmuch decoding error on a message
On Thu, 24 Nov 2011 12:13:22 -0400, David Bremner da...@tethera.net wrote: I get a set of critical errors about forgetting to call g_type_init. We actually call g_type_init in the CLI now, thanks to Oooh, ahh, I just saw these message on doing 'notmuch.py search moo' myself. I would prefer if I (the binding) would not have to deal with g_type_init stuff myself, it would mean loading more C libraries and doing stuff that no libnotmuch documentation has told me about :-). Sebastian pgpP9Bq2aADLi.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] test: cleanup gdb external dependency in atomicity tests
Change atomicity tests to use the new external binary dependencies. This simplifies the code and makes output consistent. --- test/atomicity | 12 1 files changed, 4 insertions(+), 8 deletions(-) diff --git a/test/atomicity b/test/atomicity index ad7d4a3..6df0a00 100755 --- a/test/atomicity +++ b/test/atomicity @@ -7,8 +7,7 @@ test_description='atomicity' # final database contents should be the same regardless of when (or # if) it is killed and restarted. -if which gdb 1/dev/null 21; then -test_set_prereq GDB +if test_require_external_prereq gdb; then # Create a maildir structure to also stress flag synchronization mkdir $MAIL_DIR/cur @@ -91,14 +90,11 @@ if which gdb 1/dev/null 21; then i=$(expr $end - 1) fi done -else -say_color info %-6s WARNING -echo Missing test prerequisite GDB -fi +fi test_begin_subtest 'notmuch new is idempotent under arbitrary aborts' -test_expect_equal_file GDB searchall expectall +test_expect_equal_file searchall expectall -test_expect_success GDB detected $outcount10 abort points test $outcount -gt 10 +test_expect_success detected $outcount10 abort points test $outcount -gt 10 test_done -- 1.7.7.3 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH] python: Store pointers as c_void_p to keep references
On Thu, 1 Dec 2011 18:13:05 -0500, James Westby jw+deb...@jameswestby.net wrote: From: James Westby james.wes...@linaro.org ctypes doesn't return c_void_p return values as that, it returns them as 32-bit integers instead. This has two problems: 1 - On 64-bit machines anything higher than the max 32-bit integer will overflow when passed back in to another function expecting, a pointer giving the wrong value. 2 - If the value isn't stored as a pointer then the memory can be re-used and so the object will be corrupted. The fix for both of these is to store the values as pointers. http://osdir.com/ml/python.ctypes/2006-12/msg00048.html states that this is expected behaviour of ctypes. Thanks, James ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 1/2] python: add classes to wrap all notmuch_*_t types
On Thu, 01 Dec 2011 22:25:41 +0100, Sebastian Spaeth sebast...@sspaeth.de wrote: This strikes me as a rather good thing, so the patches went in. Hah, I've just seen this, and I'm going to guess that it fixes my problems too. ... I've tested and it seems to work, so my patch is unneeded witht his one. Thanks, James ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[RFC Patch v2 3/3] notmuch-dump: add --format option
From: David Bremner brem...@debian.org Note that the new option does not control anything at the moment. --- notmuch-dump.c |4 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/notmuch-dump.c b/notmuch-dump.c index 9e0c91d..d0ab360 100644 --- a/notmuch-dump.c +++ b/notmuch-dump.c @@ -42,10 +42,14 @@ notmuch_dump_command (unused (void *ctx), int argc, char *argv[]) if (notmuch == NULL) return 1; +int output_format = 's'; char *output_file_name = NULL; int opt_index; notmuch_opt_desc_t options[] = { + { format, 'f', NOTMUCH_OPT_KEYWORD, + (notmuch_keyword_t []){ { sup, 's' }, { path, 'p' }, {0, 0} }, + output_format }, { out-file, 'o', NOTMUCH_OPT_POSITION, 0, output_file_name }, { 0, 0, 0, 0, 0 } }; -- 1.7.5.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[RFC Patch v2 2/3] notmuch-dump: convert to notmuch-opts argument handling.
From: David Bremner brem...@debian.org The output file is handled via positional arguments. There are currently no normal options. --- notmuch-dump.c | 27 +++ 1 files changed, 15 insertions(+), 12 deletions(-) diff --git a/notmuch-dump.c b/notmuch-dump.c index 0475eb9..9e0c91d 100644 --- a/notmuch-dump.c +++ b/notmuch-dump.c @@ -19,6 +19,7 @@ */ #include notmuch-client.h +#include notmuch-opts.h int notmuch_dump_command (unused (void *ctx), int argc, char *argv[]) @@ -41,27 +42,29 @@ notmuch_dump_command (unused (void *ctx), int argc, char *argv[]) if (notmuch == NULL) return 1; -argc--; argv++; /* skip subcommand argument */ +char *output_file_name = NULL; +int opt_index; -if (argc strcmp (argv[0], --) != 0) { +notmuch_opt_desc_t options[] = { + { out-file, 'o', NOTMUCH_OPT_POSITION, 0, output_file_name }, + { 0, 0, 0, 0, 0 } +}; + +opt_index = notmuch_parse_args (argc, argv, options, 1); + +if (output_file_name) { fprintf (stderr, Warning: the output file argument of dump is deprecated.\n); - output = fopen (argv[0], w); + output = fopen (output_file_name, w); if (output == NULL) { fprintf (stderr, Error opening %s for writing: %s\n, -argv[0], strerror (errno)); +output_file_name, strerror (errno)); return 1; } - argc--; - argv++; } -if (argc strcmp (argv[0], --) == 0){ - argc--; - argv++; -} -if (argc) { - query_str = query_string_from_args (notmuch, argc, argv); +if (opt_index argc) { + query_str = query_string_from_args (notmuch, argc-opt_index, argv+opt_index); if (query_str == NULL) { fprintf (stderr, Out of memory.\n); return 1; -- 1.7.5.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[RFC Patch v2 1/3] notmuch-opts.[ch]: new argument parsing framework for notmuch.
From: David Bremner brem...@debian.org As we noticed when Jani kindly converted things to getopt_long, much of the work in argument parsing in notmuch is due to the the key-value style arguments like --format=(raw|json|text). In this version I implement Austin Clements' suggestion of basing the main API on taking pointers to output variables. --- Makefile.local |1 + notmuch-opts.c | 120 notmuch-opts.h | 50 +++ 3 files changed, 171 insertions(+), 0 deletions(-) create mode 100644 notmuch-opts.c create mode 100644 notmuch-opts.h diff --git a/Makefile.local b/Makefile.local index c94402b..6606be8 100644 --- a/Makefile.local +++ b/Makefile.local @@ -303,6 +303,7 @@ notmuch_client_srcs = \ notmuch-count.c \ notmuch-dump.c \ notmuch-new.c \ + notmuch-opts.c \ notmuch-reply.c \ notmuch-restore.c \ notmuch-search.c\ diff --git a/notmuch-opts.c b/notmuch-opts.c new file mode 100644 index 000..a8c5223 --- /dev/null +++ b/notmuch-opts.c @@ -0,0 +1,120 @@ +#include assert.h +#include string.h +#include stdio.h +#include error_util.h +#include notmuch-opts.h + +/* + Search the list of keywords for a given argument, assigning the + output variable to the corresponding value. Return FALSE if nothing + matches. +*/ + +static notmuch_bool_t +_process_keyword_arg (const notmuch_opt_desc_t *arg_desc, const char *arg_str) { + +if (arg_str[0] != ':' arg_str[0] != '=') { + return FALSE; +} + +/* skip delimiter */ +arg_str++; + +notmuch_keyword_t *keywords = arg_desc-keywords; + +while (keywords-name) { + if (strcmp (arg_str, keywords-name) == 0) { + if (arg_desc-output_var) { + *((int *)arg_desc-output_var) = keywords-value; + } + return TRUE; + } + keywords++; +} +return FALSE; +} + +/* + Search for the {pos_arg_index}th position argument, return FALSE if + that does not exist. +*/ + +notmuch_bool_t +parse_position_arg (const char *arg_str, int pos_arg_index, const notmuch_opt_desc_t *arg_desc) { + +int pos_arg_counter = 0; +while (arg_desc-name){ + if (arg_desc-opt_type == NOTMUCH_OPT_POSITION) { + if (pos_arg_counter == pos_arg_index) { + if (arg_desc-output_var) { + *((const char **)arg_desc-output_var) = arg_str; + } + return TRUE; + } + pos_arg_counter++; + } + arg_desc++; +} +return FALSE; +} + +notmuch_opt_result_t +parse_option (const char *arg, + const notmuch_opt_desc_t *options){ + +assert(arg); +assert(options); + +arg += 2; + +const notmuch_opt_desc_t *try = options; +while (try-name) { + if (strncmp (arg, try-name, strlen(try-name)) == 0) { + + switch (try-opt_type) { + case NOTMUCH_OPT_KEYWORD: + return _process_keyword_arg (try, arg+strlen(try-name)); + break; + case NOTMUCH_OPT_BOOLEAN: + return TRUE; + break; + case NOTMUCH_OPT_POSITION: + case NOTMUCH_OPT_NULL: + default: + INTERNAL_ERROR (unknown or unhandled option type %d, try-opt_type); + /*UNREACHED*/ + } + } + try++; +} +return FALSE; +} + +int +notmuch_parse_args (int argc, char **argv, const notmuch_opt_desc_t *options, int opt_index){ + +int pos_arg_index = 0; +notmuch_bool_t more_args = TRUE; + +while (more_args opt_index argc) { + if (strncmp (argv[opt_index],--,2) != 0) { + + more_args = parse_position_arg (argv[opt_index], pos_arg_index, options); + + if (more_args) { + pos_arg_index++; + opt_index++; + } + + } else { + + if (strlen (argv[opt_index]) == 2) + return opt_index+1; + + more_args = parse_option (argv[opt_index], options); + opt_index++; + } +} + +return opt_index; +} diff --git a/notmuch-opts.h b/notmuch-opts.h new file mode 100644 index 000..75d65cb --- /dev/null +++ b/notmuch-opts.h @@ -0,0 +1,50 @@ +#ifndef NOTMUCH_OPTS_H +#define NOTMUCH_OPTS_H + +#include notmuch.h + +enum notmuch_opt_type { +NOTMUCH_OPT_NULL = 0, +NOTMUCH_OPT_BOOLEAN, +NOTMUCH_OPT_KEYWORD, +NOTMUCH_OPT_POSITION +}; + +typedef enum notmuch_opt_result { +NOTMUCH_OPT_ERROR = -2, +NOTMUCH_OPT_GOT_POS = -1, +NOTMUCH_OPT_STOP = 0, +NOTMUCH_OPT_SUCCESS = 1 +} notmuch_opt_result_t; + +typedef struct notmuch_keyword { +const char *name; +int value; +} notmuch_keyword_t; + +typedef struct notmuch_opt_desc { +const char *name; +int arg_id; +enum notmuch_opt_type opt_type; +struct notmuch_keyword *keywords; +
Re: ANNOUNCE: nottoomuch-addresses.pl
On Fri, 02 Dec 2011 05:38:01 +1100, Bart Bunting b...@ursys.com.au wrote: Hi Tomi, I have had a quick try of setting up nottoomuch-addresses addresses. Here are a couple of issues I have hit and I think it's still not quite right. I attach the shell output from emacs below. - firstly it appears that if the term is set to DUMB then the script assumes it's being called from emacs and exits if there is no search string. This is problematic for me as I run all my stuff including the --update command from a shell. Good point. I'll remove that 'optimization' -- mysterious are the ways users run commands :) (Well, I occasionally run commands from emacs myself, too). You could try removing part '''$ENV{TERM} eq 'dumb' or ''' in line 25 - The instructions don't tell you to create the .config/nottoomuch directory. Perhaps you could check for it's existance and create if required? It does that (in line 91): mv .config .xconfig ~/mail/nottoomuch/nottoomuch-addresses.pl --update Creating '/home/too/.config/nottoomuch/addresses'. This may take some time... Added 3335 addresses in 14 seconds. Total number of addresses: 3335. It seems your other problems make it seem the directories are not created, however I check this... - Even when I got this far I had an odd result when running the script as shown below. First time I got a strange error. Second run it added 900 or so addresses. Subsiquent runs added no more addresses. I find this strange as I have over 180k emails. Haa, the ls output '0 addresses' tells me something: rm .config/nottoomuch/addresses touch .config/nottoomuch/addresses guru$ ~/mail/nottoomuch/nottoomuch-addresses.pl --update Updating '/home/too/.config/nottoomuch/addresses', since -604800. Unrecognized option: -604800.. Added 0 addresses in 0 seconds. Total number of addresses: 0. Anyway great work. Heading in a cool direction. Hope this somewhat rambling report helps. Thanks a lot for your bug report, it's been very helpful. please retry doing the following: TERM=emacs /Users/bart/bin/nottoomuch-addresses.pl --update --rebuild And report if you get more problems. Bart Tomi bart@bit:~$ bart@bit:~$shasum ~/bin/nottoomuch-addresses.pl 125f3917b3f2dc68bdf30af04ab623d53321e50c /Users/bart/bin/nottoomuch-addresses.pl bart@bit:~$chmod 755 ~/bin/nottoomuch-addresses.pl bart@bit:~$~/bin/nottoomuch-addresses.pl --update Cannot open database, maybe not created yet. run /Users/bart/bin/nottoomuch-addresses.pl --update from command line first. bart@bit:~$cd bart@bit:~$cd .config bash: cd: .config: No such file or directory bart@bit:~$ bart@bit:~$mkdir .config bart@bit:~$nottoomuch --update bash: nottoomuch: command not found bart@bit:~$~/bin/nottoomuch-addresses.pl --update Cannot open database, maybe not created yet. run /Users/bart/bin/nottoomuch-addresses.pl --update from command line first. bart@bit:~$ bart@bit:~$cd bart@bit:~$cd .config bart@bit:~/.config$mkdir nottoomuch bart@bit:~/.config$ bart@bit:~/.config$~/bin/nottoomuch-addresses.pl --update Cannot open database, maybe not created yet. run /Users/bart/bin/nottoomuch-addresses.pl --update from command line first. bart@bit:~/.config$cd nottoomuch/ bart@bit:~/.config/nottoomuch$touch addresses bart@bit:~/.config/nottoomuch$~/bin/nottoomuch-addresses.pl --update bart@bit:~/.config/nottoomuch$ls addresses bart@bit:~/.config/nottoomuch$ls -s addresses 0 addresses bart@bit:~/.config/nottoomuch$echo $TERM dumb bart@bit:~/.config/nottoomuch$export TERM=emacs bart@bit:~/.config/nottoomuch$ls -s addresses 0 addresses bart@bit:~/.config/nottoomuch$~/bin/nottoomuch-addresses.pl --update Updating '/Users/bart/.config/nottoomuch/addresses', since -604800. Unrecognized option: -604800.. Added 0 addresses in 0 seconds. Total number of addresses: 0. bart@bit:~/.config/nottoomuch$~/bin/nottoomuch-addresses.pl --update Updating '/Users/bart/.config/nottoomuch/addresses', since 1322159542. Added 993 addresses in 4 seconds. Total number of addresses: 993. bart@bit:~/.config/nottoomuch$~/bin/nottoomuch-addresses.pl --update Updating '/Users/bart/.config/nottoomuch/addresses', since 1322159560. Added 0 addresses in 1 seconds. Total number of addresses: 993. bart@bit:~/.config/nottoomuch$ On Thu, 01 Dec 2011 17:36:24 +0200, Tomi Ollila tomi.oll...@iki.fi wrote: ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Having trouble displaying some html emails
Thanks tomi, I missed your reply. This works beautifully! Thanks Bart On Tue, 15 Nov 2011 09:51:26 +0200, Tomi Ollila wrote: > On Tue, 15 Nov 2011 10:37:42 +1100, Bart Bunting > wrote: > > Hi everyone, > > > > I am having an issue with html emails displaying correctly. > > > > For some reason the first time I view a html email it displays > > correctly. All subsequent attempts to view html emails result in the > > following error: > > > > mm-shr: Wrong type argument: bufferp, "*Summary*" > > > > > > The message opens but the parts are hidden like this: > > > > [ multipart/mixed ] > > [ text/html ] > > > > > > I'm not exactly sure what is going on here or what the best way to debug > > is? > > > > Any one have any ideas or suggestions? > > You could try > > (setq mm-text-html-renderer 'w3m) > > or > > (setq mm-text-html-renderer 'w3m-standalone) > > > For w3m-standalone you need w3m binary to be installed > and with w3m you also need some w3m.el elisp packages > (which may or may not be installed along emacs) > (or something) > > > > > Kind regards > > > > Bart > > Tomi
ANNOUNCE: nottoomuch-addresses.pl
In addition to http://notmuchmail.org/emacstips/#index11h2 and Jani's 'goobook' in id:"87zkfuh3i0.fsf at nikula.org" you can now also use http://www.iki.fi/too/nottoomuch/nottoomuch-addresses.pl for your address completion needs when composing mail/reply. This program is 1) easy to install and 2) pretty fast to use when completing. How to install 1) Download the program from above url on the machine you're running notmuch and find suitable location to it. 2) Verify it's sha1 checksum is 125f3917b3f2dc68bdf30af04ab623d53321e50c 3) chmod 755 /path/to/nottoomuch-addresses.pl 4) Run /path/to/nottoomuch-addresses.pl --update When run first time this gathers email addresses from all of your mail. This may take a long while to complete -- depends on the amount of email you have. Further --updates are much faster as those just take addresses from new mail. 5) Test that it works: Run /path/to/nottoomuch-addresses.pl notmuchmail 6) In case you're using emacs mua with notmuch, edit your notmuch configuration for emacs with the following content: (require 'notmuch-address) (setq notmuch-address-command "/path/to/nottoomuch-addresses.pl") (notmuch-address-message-insinuate) 7) Restart emacs notmuch mua (or eval above lines) and start composing new mail. When adding recipient to To: field. press after 3 or more characters have been added. In case you get 2 or more address matches, use arrow keys in minibuffer to choose desired recipient... 8) Enjoy! /path/to/nottoomuch-addresses.pl --help provides more detailed information. BR, Tomi
python-notmuch crash with threads
Hi, I've been seeing a race with python-notmuch, where it will crash due to pointers being invalidated when threads are used. I've attached a script which shows the problem some of the time. It's about the smallest script I can make, but it's hampered by the fact that making it simpler seems to make the race less likely, so it's hard to know when it is gone. The typical backtrace is: Program terminated with signal 11, Segmentation fault. #0 0x7f7b19c34b59 in talloc_named_const () from /usr/lib/x86_64-linux-gnu/libtalloc.so.2 (gdb) up #1 0x7f7b1a5f78dc in notmuch_query_search_threads (query=0x14001c70) at lib/query.cc:322 322 lib/query.cc: No such file or directory. in lib/query.cc (gdb) p *query Cannot access memory at address 0x14001c70 Where something is invalidating the pointer between creation in db.create_query() and calling it in query.search_threads() I've seen other similar things when using other code in the thread. http://talloc.samba.org/talloc/doc/html/index.html talks about the thread-safety of talloc, and I don't think it's any of those issues here. Any suggestions for how to debug this further would be most welcome. Thanks, James -- next part -- A non-text attachment was scrubbed... Name: test.py Type: text/x-python Size: 1170 bytes Desc: not available URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20111201/33032025/attachment-0001.py>
Bugs on adding flag D
Hi, I've a recurrent problem on syncing. To solve it, I've to remove internal files (rm -rf ~/.offlineimap/) and mails in .Sent folder. With offlineimap 6.3.5-rc1, the output is the following : Account sync toto_irisa: * Processing account toto_irisa Copying folder structure from IMAP to Maildir Establishing connection to zimbra.inria.fr:993. Folder sync [toto_irisa]: Syncing INBOX: IMAP -> Maildir Syncing Drafts: IMAP -> Maildir Syncing Sent: IMAP -> Maildir Adding flag D to 1 messages on Sent ERROR []: Syncing folder .Sent [acc: toto_irisa] Error with store: UID STORE failed ERROR [ ]: ERROR in syncfolder for toto_irisa folder .Sent: Traceback (most recent call last): File "/home/toto/comp/offlineimap/offlineimap/accounts.py", line 358, in syncfolder localfolder.syncmessagesto(remotefolder, statusfolder) File "/home/toto/comp/offlineimap/offlineimap/folder/Base.py", line 431, in syncmessagesto action(dstfolder, statusfolder) File "/home/toto/comp/offlineimap/offlineimap/folder/Base.py", line 388, in syncmessagesto_flags dstfolder.addmessagesflags(uids, set(flag)) File "/home/toto/comp/offlineimap/offlineimap/folder/IMAP.py", line 627, in addmessagesflags self.addmessagesflags_noconvert(uidlist, flags) File "/home/toto/comp/offlineimap/offlineimap/folder/IMAP.py", line 621, in addmessagesflags_noconvert self.processmessagesflags('+', uidlist, flags) File "/home/toto/comp/offlineimap/offlineimap/folder/IMAP.py", line 653, in processmessagesflags assert r[0] == 'OK', 'Error with store: ' + '. '.join(r[1]) AssertionError: Error with store: UID STORE failed Error with store: UID STORE failed Syncing Trash: IMAP -> Maildir Account sync toto_irisa: * Finished processing account toto_irisa ERROR: Exceptions occurred during the run! ERROR: Syncing folder .Sent [acc: toto_irisa] Error with store: UID STORE failed ERROR: ERROR in syncfolder for toto_irisa folder .Sent: Traceback (most recent call last): File "/home/toto/comp/offlineimap/offlineimap/accounts.py", line 358, in syncfolder localfolder.syncmessagesto(remotefolder, statusfolder) File "/home/toto/comp/offlineimap/offlineimap/folder/Base.py", line 431, in syncmessagesto action(dstfolder, statusfolder) File "/home/toto/comp/offlineimap/offlineimap/folder/Base.py", line 388, in syncmessagesto_flags dstfolder.addmessagesflags(uids, set(flag)) File "/home/toto/comp/offlineimap/offlineimap/folder/IMAP.py", line 627, in addmessagesflags self.addmessagesflags_noconvert(uidlist, flags) File "/home/toto/comp/offlineimap/offlineimap/folder/IMAP.py", line 621, in addmessagesflags_noconvert self.processmessagesflags('+', uidlist, flags) File "/home/toto/comp/offlineimap/offlineimap/folder/IMAP.py", line 653, in processmessagesflags assert r[0] == 'OK', 'Error with store: ' + '. '.join(r[1]) AssertionError: Error with store: UID STORE failed Error with store: UID STORE failed Of course, I can give you more detailled information if you need it. Dal.
[PATCH 1/2] python: add classes to wrap all notmuch_*_t types
On Mon, 28 Nov 2011 13:36:44 +0100, Justus Winter wrote: > Well, quoting my commit message: > > > Add type information to the ctypes._FuncPtr wrappers and > > use the wrapper classes instead of c_void_p for pointers > > to notmuch_*_t. > > > > This enables the ctypes library to type check parameters > > being handed to functions from the notmuch library. This strikes me as a rather good thing, so the patches went in. Sebastian -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 197 bytes Desc: not available URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20111201/34f4fe1a/attachment.pgp>
python-notmuch decoding error on a message
On Thu, 24 Nov 2011 12:13:22 -0400, David Bremner wrote: > I get a set of critical errors about forgetting to call g_type_init. > We actually call g_type_init in the CLI now, thanks to Oooh, ahh, I just saw these message on doing 'notmuch.py search "moo"' myself. I would prefer if I (the binding) would not have to deal with g_type_init stuff myself, it would mean loading more C libraries and doing stuff that no libnotmuch documentation has told me about :-). Sebastian -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 197 bytes Desc: not available URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20111201/27a46d03/attachment.pgp>
[PATCH] python: Store pointers as c_void_p to keep references
From: James Westbyctypes doesn't return c_void_p return values as that, it returns them as 32-bit integers instead. This has two problems: 1 - On 64-bit machines anything higher than the max 32-bit integer will overflow when passed back in to another function expecting, a pointer giving the wrong value. 2 - If the value isn't stored as a pointer then the memory can be re-used and so the object will be corrupted. The fix for both of these is to store the values as pointers. --- bindings/python/notmuch/database.py | 18 +- bindings/python/notmuch/message.py | 10 +- bindings/python/notmuch/thread.py |6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/bindings/python/notmuch/database.py b/bindings/python/notmuch/database.py index f4bc53e..e5188fb 100644 --- a/bindings/python/notmuch/database.py +++ b/bindings/python/notmuch/database.py @@ -152,7 +152,7 @@ class Database(object): if res is None: raise NotmuchError( message="Could not create the specified database") -self._db = res +self._db = c_void_p(res) def open(self, path, mode=0): """Opens an existing database @@ -171,7 +171,7 @@ class Database(object): if res is None: raise NotmuchError(message="Could not open the specified database") -self._db = res +self._db = c_void_p(res) def get_path(self): """Returns the file path of an open database""" @@ -297,7 +297,7 @@ class Database(object): dir_p = Database._get_directory(self._db, _str(path)) # return the Directory, init it with the absolute path -return Directory(_str(abs_dirpath), dir_p, self) +return Directory(_str(abs_dirpath), c_void_p(dir_p), self) def add_message(self, filename, sync_maildir_flags=False): """Adds a new message to the database @@ -466,7 +466,7 @@ class Database(object): tags_p = Database._get_all_tags(self._db) if tags_p == None: raise NotmuchError(STATUS.NULL_POINTER) -return Tags(tags_p, self) +return Tags(c_void_p(tags_p), self) def create_query(self, querystring): """Returns a :class:`Query` derived from this database @@ -600,7 +600,7 @@ class Query(object): query_p = Query._create(db.db_p, _str(querystr)) if query_p is None: raise NullPointerError -self._query = query_p +self._query = c_void_p(query_p) def set_sort(self, sort): """Set the sort order future results will be delivered in @@ -630,7 +630,7 @@ class Query(object): if threads_p is None: raise NullPointerError -return Threads(threads_p, self) +return Threads(c_void_p(threads_p), self) def search_messages(self): """Filter messages according to the query and return @@ -644,7 +644,7 @@ class Query(object): if msgs_p is None: raise NullPointerError -return Messages(msgs_p, self) +return Messages(c_void_p(msgs_p), self) def count_messages(self): """Estimate the number of messages matching the query @@ -793,7 +793,7 @@ class Directory(object): """ self._assert_dir_is_initialized() files_p = Directory._get_child_files(self._dir_p) -return Filenames(files_p, self) +return Filenames(c_void_p(files_p), self) def get_child_directories(self): """Gets a :class:`Filenames` iterator listing all the filenames of @@ -804,7 +804,7 @@ class Directory(object): """ self._assert_dir_is_initialized() files_p = Directory._get_child_directories(self._dir_p) -return Filenames(files_p, self) +return Filenames(c_void_p(files_p), self) @property def path(self): diff --git a/bindings/python/notmuch/message.py b/bindings/python/notmuch/message.py index 4bf90c2..672a169 100644 --- a/bindings/python/notmuch/message.py +++ b/bindings/python/notmuch/message.py @@ -140,7 +140,7 @@ class Messages(object): if tags_p == None: raise NotmuchError(STATUS.NULL_POINTER) -return Tags(tags_p, self) +return Tags(c_void_p(tags_p), self) def __iter__(self): """ Make Messages an iterator """ @@ -154,7 +154,7 @@ class Messages(object): self._msgs = None raise StopIteration -msg = Message(Messages._get(self._msgs), self) +msg = Message(c_void_p(Messages._get(self._msgs)), self) nmlib.notmuch_messages_move_to_next(self._msgs) return msg @@ -350,7 +350,7 @@ class Message(object): if msgs_p is None: return None -return Messages(msgs_p, self) +return Messages(c_void_p(msgs_p), self) def get_date(self): """Returns time_t of the message date @@ -418,7 +418,7 @@ class Message(object):
[RFC Patch v2 3/3] notmuch-dump: add --format option
From: David BremnerNote that the new option does not control anything at the moment. --- notmuch-dump.c |4 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/notmuch-dump.c b/notmuch-dump.c index 9e0c91d..d0ab360 100644 --- a/notmuch-dump.c +++ b/notmuch-dump.c @@ -42,10 +42,14 @@ notmuch_dump_command (unused (void *ctx), int argc, char *argv[]) if (notmuch == NULL) return 1; +int output_format = 's'; char *output_file_name = NULL; int opt_index; notmuch_opt_desc_t options[] = { + { "format", 'f', NOTMUCH_OPT_KEYWORD, + (notmuch_keyword_t []){ { "sup", 's' }, { "path", 'p' }, {0, 0} }, + _format }, { "out-file", 'o', NOTMUCH_OPT_POSITION, 0, _file_name }, { 0, 0, 0, 0, 0 } }; -- 1.7.5.4
[RFC Patch v2 2/3] notmuch-dump: convert to notmuch-opts argument handling.
From: David BremnerThe output file is handled via positional arguments. There are currently no "normal" options. --- notmuch-dump.c | 27 +++ 1 files changed, 15 insertions(+), 12 deletions(-) diff --git a/notmuch-dump.c b/notmuch-dump.c index 0475eb9..9e0c91d 100644 --- a/notmuch-dump.c +++ b/notmuch-dump.c @@ -19,6 +19,7 @@ */ #include "notmuch-client.h" +#include "notmuch-opts.h" int notmuch_dump_command (unused (void *ctx), int argc, char *argv[]) @@ -41,27 +42,29 @@ notmuch_dump_command (unused (void *ctx), int argc, char *argv[]) if (notmuch == NULL) return 1; -argc--; argv++; /* skip subcommand argument */ +char *output_file_name = NULL; +int opt_index; -if (argc && strcmp (argv[0], "--") != 0) { +notmuch_opt_desc_t options[] = { + { "out-file", 'o', NOTMUCH_OPT_POSITION, 0, _file_name }, + { 0, 0, 0, 0, 0 } +}; + +opt_index = notmuch_parse_args (argc, argv, options, 1); + +if (output_file_name) { fprintf (stderr, "Warning: the output file argument of dump is deprecated.\n"); - output = fopen (argv[0], "w"); + output = fopen (output_file_name, "w"); if (output == NULL) { fprintf (stderr, "Error opening %s for writing: %s\n", -argv[0], strerror (errno)); +output_file_name, strerror (errno)); return 1; } - argc--; - argv++; } -if (argc && strcmp (argv[0], "--") == 0){ - argc--; - argv++; -} -if (argc) { - query_str = query_string_from_args (notmuch, argc, argv); +if (opt_index < argc) { + query_str = query_string_from_args (notmuch, argc-opt_index, argv+opt_index); if (query_str == NULL) { fprintf (stderr, "Out of memory.\n"); return 1; -- 1.7.5.4
[RFC Patch v2 1/3] notmuch-opts.[ch]: new argument parsing framework for notmuch.
From: David BremnerAs we noticed when Jani kindly converted things to getopt_long, much of the work in argument parsing in notmuch is due to the the key-value style arguments like --format=(raw|json|text). In this version I implement Austin Clements' suggestion of basing the main API on taking pointers to output variables. --- Makefile.local |1 + notmuch-opts.c | 120 notmuch-opts.h | 50 +++ 3 files changed, 171 insertions(+), 0 deletions(-) create mode 100644 notmuch-opts.c create mode 100644 notmuch-opts.h diff --git a/Makefile.local b/Makefile.local index c94402b..6606be8 100644 --- a/Makefile.local +++ b/Makefile.local @@ -303,6 +303,7 @@ notmuch_client_srcs = \ notmuch-count.c \ notmuch-dump.c \ notmuch-new.c \ + notmuch-opts.c \ notmuch-reply.c \ notmuch-restore.c \ notmuch-search.c\ diff --git a/notmuch-opts.c b/notmuch-opts.c new file mode 100644 index 000..a8c5223 --- /dev/null +++ b/notmuch-opts.c @@ -0,0 +1,120 @@ +#include +#include +#include +#include "error_util.h" +#include "notmuch-opts.h" + +/* + Search the list of keywords for a given argument, assigning the + output variable to the corresponding value. Return FALSE if nothing + matches. +*/ + +static notmuch_bool_t +_process_keyword_arg (const notmuch_opt_desc_t *arg_desc, const char *arg_str) { + +if (arg_str[0] != ':' && arg_str[0] != '=') { + return FALSE; +} + +/* skip delimiter */ +arg_str++; + +notmuch_keyword_t *keywords = arg_desc->keywords; + +while (keywords->name) { + if (strcmp (arg_str, keywords->name) == 0) { + if (arg_desc->output_var) { + *((int *)arg_desc->output_var) = keywords->value; + } + return TRUE; + } + keywords++; +} +return FALSE; +} + +/* + Search for the {pos_arg_index}th position argument, return FALSE if + that does not exist. +*/ + +notmuch_bool_t +parse_position_arg (const char *arg_str, int pos_arg_index, const notmuch_opt_desc_t *arg_desc) { + +int pos_arg_counter = 0; +while (arg_desc->name){ + if (arg_desc->opt_type == NOTMUCH_OPT_POSITION) { + if (pos_arg_counter == pos_arg_index) { + if (arg_desc->output_var) { + *((const char **)arg_desc->output_var) = arg_str; + } + return TRUE; + } + pos_arg_counter++; + } + arg_desc++; +} +return FALSE; +} + +notmuch_opt_result_t +parse_option (const char *arg, + const notmuch_opt_desc_t *options){ + +assert(arg); +assert(options); + +arg += 2; + +const notmuch_opt_desc_t *try = options; +while (try->name) { + if (strncmp (arg, try->name, strlen(try->name)) == 0) { + + switch (try->opt_type) { + case NOTMUCH_OPT_KEYWORD: + return _process_keyword_arg (try, arg+strlen(try->name)); + break; + case NOTMUCH_OPT_BOOLEAN: + return TRUE; + break; + case NOTMUCH_OPT_POSITION: + case NOTMUCH_OPT_NULL: + default: + INTERNAL_ERROR ("unknown or unhandled option type %d", try->opt_type); + /*UNREACHED*/ + } + } + try++; +} +return FALSE; +} + +int +notmuch_parse_args (int argc, char **argv, const notmuch_opt_desc_t *options, int opt_index){ + +int pos_arg_index = 0; +notmuch_bool_t more_args = TRUE; + +while (more_args && opt_index < argc) { + if (strncmp (argv[opt_index],"--",2) != 0) { + + more_args = parse_position_arg (argv[opt_index], pos_arg_index, options); + + if (more_args) { + pos_arg_index++; + opt_index++; + } + + } else { + + if (strlen (argv[opt_index]) == 2) + return opt_index+1; + + more_args = parse_option (argv[opt_index], options); + opt_index++; + } +} + +return opt_index; +} diff --git a/notmuch-opts.h b/notmuch-opts.h new file mode 100644 index 000..75d65cb --- /dev/null +++ b/notmuch-opts.h @@ -0,0 +1,50 @@ +#ifndef NOTMUCH_OPTS_H +#define NOTMUCH_OPTS_H + +#include "notmuch.h" + +enum notmuch_opt_type { +NOTMUCH_OPT_NULL = 0, +NOTMUCH_OPT_BOOLEAN, +NOTMUCH_OPT_KEYWORD, +NOTMUCH_OPT_POSITION +}; + +typedef enum notmuch_opt_result { +NOTMUCH_OPT_ERROR = -2, +NOTMUCH_OPT_GOT_POS = -1, +NOTMUCH_OPT_STOP = 0, +NOTMUCH_OPT_SUCCESS = 1 +} notmuch_opt_result_t; + +typedef struct notmuch_keyword { +const char *name; +int value; +} notmuch_keyword_t; + +typedef struct notmuch_opt_desc { +const char *name; +int arg_id; +enum notmuch_opt_type opt_type; +struct notmuch_keyword