[PATCH 10/13] vim: option to add reply quote datetime
From: Aaron Borden By default it's empty so the format doesn't change. Cleanup-by: Felipe Contreras Signed-off-by: Felipe Contreras --- vim/notmuch.txt | 7 +++ vim/notmuch.vim | 12 +++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/vim/notmuch.txt b/vim/notmuch.txt index b658020d..a8a75fed 100644 --- a/vim/notmuch.txt +++ b/vim/notmuch.txt @@ -140,6 +140,13 @@ If you want to change the reply quote format to show the email address: let g:notmuch_reply_quote_format = '%s <%s>' < + *g:notmuch_reply_quote_datetime_format* + +There's also a way to specy the reply quote datetime format: +> + let g:notmuch_reply_quote_datetime_format = '%a %b %e' +< + *g:notmuch_folders_count_threads* If you want to count the threads instead of the messages in the folder view: diff --git a/vim/notmuch.vim b/vim/notmuch.vim index 59914a76..e717fb5a 100644 --- a/vim/notmuch.vim +++ b/vim/notmuch.vim @@ -57,6 +57,7 @@ let s:notmuch_folders_default = [ let s:notmuch_date_format_default = '%d.%m.%y' let s:notmuch_datetime_format_default = '%d.%m.%y %H:%M:%S' let s:notmuch_reply_quote_format_default = '%s' +let s:notmuch_reply_quote_datetime_format_default = '' let s:notmuch_reader_default = 'mutt -f %s' let s:notmuch_sendmail_default = 'sendmail' let s:notmuch_folders_count_threads_default = 0 @@ -418,6 +419,10 @@ function! s:set_defaults() let g:notmuch_reply_quote_format = s:notmuch_reply_quote_format_default endif + if !exists('g:notmuch_reply_quote_datetime_format') + let g:notmuch_reply_quote_datetime_format = s:notmuch_reply_quote_datetime_format_default + endif + if !exists('g:notmuch_reader') if exists('g:notmuch_rb_reader') let g:notmuch_reader = g:notmuch_rb_reader @@ -600,12 +605,17 @@ ruby << EOF name = addr.local + "@" if name.nil? && !addr.local.nil? name_format = VIM::evaluate('g:notmuch_reply_quote_format') name = name_format % [name, addr.address] if !addr.address.nil? + date_format = VIM::evaluate('g:notmuch_reply_quote_datetime_format') + quote_datetime = orig.date.strftime(date_format) if !date_format.empty? and orig.date else name = orig[:from] end name = "somebody" if name.nil? - body_lines << "%s wrote:" % name + quote = [] + quote << "On %s" % quote_datetime if quote_datetime + quote << "%s wrote:" % name + body_lines << quote.join(', ') part = orig.find_first_text part.convert.each_line do |l| body_lines << "> %s" % l.chomp -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 11/13] vim: syntax: fix message description highlighting
From: Aaron Borden Signed-off-by: Felipe Contreras --- vim/syntax/notmuch-show.vim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vim/syntax/notmuch-show.vim b/vim/syntax/notmuch-show.vim index c3a98b77..de0c43a1 100644 --- a/vim/syntax/notmuch-show.vim +++ b/vim/syntax/notmuch-show.vim @@ -1,8 +1,8 @@ " notmuch show mode syntax file syntax cluster nmShowMsgDesc contains=nmShowMsgDescWho,nmShowMsgDescDate,nmShowMsgDescTags -syntax match nmShowMsgDescWho /[^)]\+)/ contained -syntax match nmShowMsgDescDate / ([^)]\+[0-9]) / contained +syntax match nmShowMsgDescWho /[^)]\+>/ contained +syntax match nmShowMsgDescDate / [^(]\+ / contained syntax match nmShowMsgDescTags /([^)]\+)$/ contained syntax cluster nmShowMsgHead contains=nmShowMsgHeadKey,nmShowMsgHeadVal -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 12/13] vim: remove backwards compatibility wrappers
Seven years is more than enough. Signed-off-by: Felipe Contreras --- vim/notmuch.vim | 50 + 1 file changed, 9 insertions(+), 41 deletions(-) diff --git a/vim/notmuch.vim b/vim/notmuch.vim index e717fb5a..717633c7 100644 --- a/vim/notmuch.vim +++ b/vim/notmuch.vim @@ -399,20 +399,16 @@ endfunction "" root function! s:set_defaults() + if !exists('g:notmuch_folders') + let g:notmuch_folders = s:notmuch_folders_default + endif + if !exists('g:notmuch_date_format') - if exists('g:notmuch_rb_date_format') - let g:notmuch_date_format = g:notmuch_rb_date_format - else - let g:notmuch_date_format = s:notmuch_date_format_default - endif + let g:notmuch_date_format = s:notmuch_date_format_default endif if !exists('g:notmuch_datetime_format') - if exists('g:notmuch_rb_datetime_format') - let g:notmuch_datetime_format = g:notmuch_rb_datetime_format - else - let g:notmuch_datetime_format = s:notmuch_datetime_format_default - endif + let g:notmuch_datetime_format = s:notmuch_datetime_format_default endif if !exists('g:notmuch_reply_quote_format') @@ -424,41 +420,21 @@ function! s:set_defaults() endif if !exists('g:notmuch_reader') - if exists('g:notmuch_rb_reader') - let g:notmuch_reader = g:notmuch_rb_reader - else - let g:notmuch_reader = s:notmuch_reader_default - endif + let g:notmuch_reader = s:notmuch_reader_default endif if !exists('g:notmuch_sendmail') - if exists('g:notmuch_rb_sendmail') - let g:notmuch_sendmail = g:notmuch_rb_sendmail - else - let g:notmuch_sendmail = s:notmuch_sendmail_default - endif + let g:notmuch_sendmail = s:notmuch_sendmail_default endif if !exists('g:notmuch_folders_count_threads') - if exists('g:notmuch_rb_count_threads') - let g:notmuch_count_threads = g:notmuch_rb_count_threads - else - let g:notmuch_folders_count_threads = s:notmuch_folders_count_threads_default - endif + let g:notmuch_folders_count_threads = s:notmuch_folders_count_threads_default endif if !exists('g:notmuch_compose_start_insert') let g:notmuch_compose_start_insert = s:notmuch_compose_start_insert_default endif - if !exists('g:notmuch_custom_search_maps') && exists('g:notmuch_rb_custom_search_maps') - let g:notmuch_custom_search_maps = g:notmuch_rb_custom_search_maps - endif - - if !exists('g:notmuch_custom_show_maps') && exists('g:notmuch_rb_custom_show_maps') - let g:notmuch_custom_show_maps = g:notmuch_rb_custom_show_maps - endif - if exists('g:notmuch_custom_search_maps') call extend(g:notmuch_search_maps, g:notmuch_custom_search_maps) endif @@ -466,14 +442,6 @@ function! s:set_defaults() if exists('g:notmuch_custom_show_maps') call extend(g:notmuch_show_maps, g:notmuch_custom_show_maps) endif - - if !exists('g:notmuch_folders') - if exists('g:notmuch_rb_folders') - let g:notmuch_folders = g:notmuch_rb_folders - else - let g:notmuch_folders = s:notmuch_folders_default - endif - endif endfunction function! s:NotMuch(...) -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 13/13] vim: README: sync with upstream
Signed-off-by: Felipe Contreras --- vim/README | 27 +-- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/vim/README b/vim/README index c137bacd..d9a635a2 100644 --- a/vim/README +++ b/vim/README @@ -3,7 +3,7 @@ This is a vim plug-in that provides a fully usable mail client interface, utilizing the notmuch framework, through it's ruby bindings. -== install == +== Install == Simply run 'make install'. However, check that you have the dependencies below. @@ -12,6 +12,8 @@ Simply run 'make install'. However, check that you have the dependencies below. Make sure your vim version has ruby support: check for +ruby in 'vim --version' features. + % vim --version | grep +ruby + === ruby bindings === Check if you are able to run the following command cleanly: @@ -28,16 +30,10 @@ directory in the notmuch source tree. Since libnotmuch library concentrates on things other than handling mail, we need a library to do that, and for Ruby the best library for that is called -'mail'. The easiest way to install it is with ruby's gem. In most distro's the -package is called 'rubygems'. - -Once you have gem, run: +'mail': % gem install mail -In some systems gems are installed on a per-user basis by default, so make sure -you are running as the same user as the one that installed them. - This gem is not mandatory, but it's extremely recommended. == Running == @@ -46,6 +42,15 @@ Simple: % gvim -c ':NotMuch' +You might want to write a wrapper script (e.g. `vnm`) + + #!/bin/sh + gvim -c ":NotMuch $*" + +So you can run: + + vnm is:inbox date:yesterday.. + Enjoy ;) == More stuff == @@ -53,10 +58,12 @@ Enjoy ;) As an example to configure a key mapping to add the tag 'to-do' and archive, this is what I use: -let g:notmuch_rb_custom_search_maps = { + +let g:notmuch_custom_search_maps = { \ 't': 'search_tag("+to-do -inbox")', \ } -let g:notmuch_rb_custom_show_maps = { +let g:notmuch_custom_show_maps = { \ 't': 'show_tag("+to-do -inbox")', \ } + -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH] ruby: fix ruby 3.1 warnings
Hello. On Sat, Apr 17, 2021 at 7:20 AM David Bremner wrote: > Thanks for the patch. I have a couple of questions / comments > > - It doesn't apply against current master (5248f55d5f1). Can you rebase > it? Huh? That's precisely the commit I used as a base. It applies cleanly. > - What version of ruby is generating those warnings? I don't see it with > ruby 2.7. I guess that's not necessarily a blocker, as long as the > patched version still builds and runs with older ruby. Yeah, not a blocker. I'm using Ruby 3.0. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH] ruby: fix ruby 3.1 warnings
On Mon, Apr 19, 2021 at 1:50 PM Tomi Ollila wrote: > (otoh?) latest git-send-email has this option: --8bit-encoding > -- and if not given (and not in git config), according to namual page, > will prompt for an encoding (IIRC I've seen this w/ git 2.30) I have this configured: sendemail.assume8bitEncoding = utf-8 I don't know if this is the right thing to do, but in git world everything is utf-8. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH 00/13] vim: a bunch of updates from upstream
On Mon, Apr 19, 2021 at 5:16 AM David Bremner wrote: > > Felipe Contreras writes: > > > I finally took some time to update notmuch-vim and include some fixes, > > as well as pull requests. > > > > Here are the transplanted patches. > > > > So, big picture question. If notmuch is not upstream for this code, > should we be distributing it? I'm not sure which should be considered "upstream" at this point. Apparently there's also a fork by Ian Main that a lot of people are using. >From my point of view the code in notmuch is the one that has been maintained the best. It also has the advantage that there's debian packaging. However, it doesn't have all the improvements of my code-base, nor the features from Ian's code-base. If I manage to: 1. Provide debian packaging 2. Merge the important features from Ian's code (cleanly) 3. Remain active merging future patches Then I think we could consider removing the vim stuff from notmuch. In the meantime I think the three code-bases serve a purpose. Cheers. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH 00/13] vim: a bunch of updates from upstream
On Mon, Apr 19, 2021 at 5:14 PM David Bremner wrote: > Felipe Contreras writes: > > > Then I think we could consider removing the vim stuff from notmuch. In > > the meantime I think the three code-bases serve a purpose. > > Thanks for the detailed explanation. Your reasoning makes sense to > me. Now if only we could get more than one person at a time interested > in the notmuch version of the code. Indeed, but this is open source; nobody is paying me (or others) to do this, so not much can be demanded. I guess we'll have to wait and see. Cheers. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH 1/2] Vim: Respect excluded tags when showing a thread
On Fri, Apr 23, 2021 at 7:23 AM David Bremner wrote: > > Jules Aguillon writes: > > > Other queries have exclude_tags taken into account but this one. > > This is annoying when using an excluded tag to ignore past messages from a > > thread (for example the 'deleted' tag), the entire thread is shown all the > > The two of you are the most recent submitters of patches [1] to the vim > frontend for notmuch. You might want to consider helping test and/or > review each other's patches. I don't need to test it, the patch is obviously correct. Reviewed-by: Felipe Contreras -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: Release process for 0.32
On Sat, Apr 24, 2021 at 11:36 AM David Bremner wrote: > As always, NEWS items and last minute bug fixes are solicited. Can we at least include one fix for the vim plugin? Without it the code is pretty much unusable. https://nmbug.notmuchmail.org/nmweb/show/20210418224851.88240-2-felipe.contreras%40gmail.com -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[RFC PATCH] Attempt to reactive Ruby gc
Commit c7893408 (ruby: Kill garbage collection related cruft., 2010-05-26) removed garbage collection because the order of objects freed couldn't be ensured in Ruby. However, we can use talloc for reference counting and thus preventing Ruby from destroying the objects. First we create a wrapper object with no talloc parent, which will be owned by the Ruby object (e.g. Notmuch::Thread). The notmuch object (notmuch_thread_t) will have two parents then (notmuch_threads_t and Notmuch::Thread). If Ruby destroys the other parent first (notmuch_threads_t), that still doesn't destroy the object, since we still own a reference (from Notmuch::Thread). It's only when both are destroyed that the object is actually freed. Signed-off-by: Felipe Contreras --- bindings/ruby/defs.h | 24 +++- bindings/ruby/extconf.rb | 1 + bindings/ruby/thread.c | 6 +++--- bindings/ruby/threads.c | 2 +- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index 48544ca2..56a70a4f 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -23,6 +23,7 @@ #include #include +#include extern VALUE notmuch_rb_cDatabase; extern VALUE notmuch_rb_cDirectory; @@ -50,6 +51,25 @@ extern ID ID_call; extern ID ID_db_create; extern ID ID_db_mode; +typedef struct { +void *pointer; +} notmuch_rb_object_t; + +static inline void +notmuch_rb_object_free (void *object) +{ +talloc_free (object); +} + +static inline VALUE +notmuch_rb_object_wrap (VALUE klass, void *ptr) +{ +notmuch_rb_object_t *object = talloc (NULL, typeof (*object)); +object->pointer = ptr; +talloc_reference (object, ptr); +return Data_Wrap_Struct (klass, NULL, ¬much_rb_object_free, object); +} + /* RSTRING_PTR() is new in ruby-1.9 */ #if !defined(RSTRING_PTR) # define RSTRING_PTR(v) (RSTRING((v))->ptr) @@ -105,10 +125,12 @@ extern ID ID_db_mode; #define Data_Get_Notmuch_Thread(obj, ptr) \ do { \ + notmuch_rb_object_t *object;\ Check_Type ((obj), T_DATA); \ if (DATA_PTR ((obj)) == NULL) \ rb_raise (rb_eRuntimeError, "thread destroyed");\ - Data_Get_Struct ((obj), notmuch_thread_t, (ptr)); \ + Data_Get_Struct ((obj), typeof (*object), object); \ + (ptr) = object->pointer;\ } while (0) #define Data_Get_Notmuch_Message(obj, ptr) \ diff --git a/bindings/ruby/extconf.rb b/bindings/ruby/extconf.rb index 161de5a2..d914537c 100644 --- a/bindings/ruby/extconf.rb +++ b/bindings/ruby/extconf.rb @@ -19,6 +19,7 @@ if not ENV['LIBNOTMUCH'] end $LOCAL_LIBS += ENV['LIBNOTMUCH'] +$LIBS += " -ltalloc" # Create Makefile dir_config('notmuch') diff --git a/bindings/ruby/thread.c b/bindings/ruby/thread.c index 9b295981..5705b556 100644 --- a/bindings/ruby/thread.c +++ b/bindings/ruby/thread.c @@ -28,11 +28,11 @@ VALUE notmuch_rb_thread_destroy (VALUE self) { -notmuch_thread_t *thread; +notmuch_rb_object_t *object; -Data_Get_Notmuch_Thread (self, thread); +Data_Get_Struct (self, typeof (*object), object); -notmuch_thread_destroy (thread); +notmuch_rb_object_free (object); DATA_PTR (self) = NULL; return Qnil; diff --git a/bindings/ruby/threads.c b/bindings/ruby/threads.c index ed403a8f..302ffd91 100644 --- a/bindings/ruby/threads.c +++ b/bindings/ruby/threads.c @@ -53,7 +53,7 @@ notmuch_rb_threads_each (VALUE self) for (; notmuch_threads_valid (threads); notmuch_threads_move_to_next (threads)) { thread = notmuch_threads_get (threads); - rb_yield (Data_Wrap_Struct (notmuch_rb_cThread, NULL, NULL, thread)); + rb_yield (notmuch_rb_object_wrap (notmuch_rb_cThread, thread)); } return self; -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH 1/2] Vim: Respect excluded tags when showing a thread
On Mon, Apr 26, 2021 at 6:39 PM David Bremner wrote: > > Felipe Contreras writes: > > > > I don't need to test it, the patch is obviously correct. > > > > Reviewed-by: Felipe Contreras > > Famous last words ;). But OK, applied to master. Er, I acked the first patch, not the second. The second one will likely introduce issues. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH 1/2] Vim: Respect excluded tags when showing a thread
On Tue, Apr 27, 2021 at 3:09 PM David Bremner wrote: > > Felipe Contreras writes: > > > On Mon, Apr 26, 2021 at 6:39 PM David Bremner wrote: > >> > >> Felipe Contreras writes: > >> > > >> > I don't need to test it, the patch is obviously correct. > >> > > >> > Reviewed-by: Felipe Contreras > >> > >> Famous last words ;). But OK, applied to master. > > > > Er, I acked the first patch, not the second. > > > > The second one will likely introduce issues. > > OK, let me know if I should revert the second patch. Yes please. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH 2/2] Vim: Ensure that every queries respect excluded tags
On Tue, Feb 16, 2021 at 5:43 PM Jules Aguillon wrote: > > This makes sure that the bug solved by the previous commit won't happen again > and remove some dupplication. > This shouldn't have any side effect. At least Aaron D Borden did mention some issues with this approach [1]. >From my cursory look at this patch this would cause the do_tag() function to skip excluded tags, therefore you couldn't do for example "-delete". I think the query() helper could be extended to make it easier to pass excluded_tags, but this is not the way. Cheers. [1] https://github.com/felipec/notmuch-vim/pull/7 -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
The future of Ruby bindings
Hi, Ruby is by far my favorite programming language, and I'm very familiar with the way it's meant to be used. This is very idiomatic of Ruby: $db.query('').search_threads.each do |thread| puts thread.subject end It works perfectly fine, but it leaks memory. In order to prevent memory from being leaked, we have to do something like: query = $db.query('') threads = query.search_threads threads.each do |thread| puts thread.subject thread.destroy! end threads.destroy! query.destroy! This is very ugly Ruby. Ruby is a garbage collected language, this destroy! approach works, but there's no better way to describe it but "a hack". I understand why Ali Polatel did commit c7893408 (ruby: Kill garbage collection related cruft., 2010-05-26); because the order of the object destruction cannot be ensured in Ruby, however, there's ways to workaround that. 1. We can steal the object 2. We can increase the reference count 3. We can add a second parent The notmuch API doesn't have helpers to do either one of those things, but since we know talloc is used internally, we can simply utilize that knowledge. I sent a proof of concept patch [1], that uses method 3, but it was ignored. I could proceed and do the actual full patch using this method over all the Ruby code, but it's tedious work that I would rather not do until I know such an approach would be accepted. With my proposed approach we wouldn't have to rely on destroy! (which still works), and Ruby's garbage collection would work fine and no memory would be leaked. Thoughts? Cheers. [1] id:20210427085343.2300-1-felipe.contre...@gmail.com -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
notmuch and public-inbox
Hi, My workflow with notmuch is near to perfect, however, the only pain point I have is fetching all the mail of a particular mailing list. To do this efficiently public-inbox seems ideal, however, when searching information to link notmuch to public-inbox I don't find anything of value. In fact, I can't find an URL of a public-inbox repository of the notmuch mailing list. Am I missing something or has nobody really worked on linking these two tools? Seems like an obvious area of opportunity. Cheers. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: notmuch and public-inbox
On Fri, Apr 30, 2021 at 7:05 PM Eric Wong wrote: > > Felipe Contreras wrote: > > My workflow with notmuch is near to perfect, however, the only pain > > point I have is fetching all the mail of a particular mailing list. > > > > To do this efficiently public-inbox seems ideal, however, when > > searching information to link notmuch to public-inbox I don't find > > anything of value. In fact, I can't find an URL of a public-inbox > > repository of the notmuch mailing list. > > Kyle maintains an unofficial mirror at https://yhetil.org/notmuch Nice. Who is Kyle? > There's no real relationship between them aside from they both > use Xapian (and I learned Xapian from reading the notmuch source). I don't mean sharing the Xapian database (although that could be interesting for the future). I'm talking about as a client of public-inbox, not as a server. I mean doing a git clone for a public-inbox repository and notmuch indexing that repository. > > Am I missing something or has nobody really worked on linking these two > > tools? Seems like an obvious area of opportunity. > > I think W. Trevor King (Cc-ed) also started looking something > many years ago, but I'm not sure if anything became of it. > > I never had the interest in using notmuch since Maildirs are a > non-starter with millions of messages with current FSes/OSes. > mairix + gzipped mboxes mostly works for me, (though mairix > indexing is silly expensive[1]) If notmuch was patched to support the public-inbox format--as an alternative to Maildir--then users of public-inbox could clone a repository, and use notmuch to index that. I don't see how that could be difficult. But then again, I haven't looked at the Maildir code. Cheers. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 02/13] test: unset NAME environment variable
Otherwise the output from the tests would be different. Signed-off-by: Felipe Contreras --- test/test-lib.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test-lib.sh b/test/test-lib.sh index e13797a7..ae653363 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -112,6 +112,7 @@ unset ALTERNATE_EDITOR # for reproducibility unset EMAIL +unset NAME add_gnupg_home () { -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 01/13] test: fix passwd_sanitize()
If any of the variables is empty the output is completely messed up, because replace("", "FOO") puts "FOO" before every single character. I don't have my full name configured, and this is what I get: USER_FULL_NAME=USER_FULL_NAME=USER_FULL_NAME USER_FULL_NAMEsUSER_FULL_NAMEtUSER_FULL_NAMEdUSER_FULL_NAMEoUSER_FULL_NAMEuUSER_FULL_NAMEtUSER_FULL_NAME USER_FULL_NAME=USER_FULL_NAME=USER_FULL_NAME Let's check for empty strings before doing any replace. Signed-off-by: Felipe Contreras --- test/test-lib.sh | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/test-lib.sh b/test/test-lib.sh index 4c9f2a21..e13797a7 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -711,7 +711,12 @@ name = pw.pw_gecos.partition(",")[0] fqdn = socket.getfqdn() for l in sys.stdin: -l = l.replace(user, "USERNAME").replace(fqdn, "FQDN").replace(".(none)","").replace(name, "USER_FULL_NAME") +if user: +l = l.replace(user, "USERNAME") +if fqdn: +l = l.replace(fqdn, "FQDN").replace(".(none)","") +if name: +l = l.replace(name, "USER_FULL_NAME") sys.stdout.write(l) ' } -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 03/13] test: remove USER_FULL_NAME when not present
If a full name is not configured, the output is empty. This is possibly not portable, but it's a start. Signed-off-by: Felipe Contreras --- test/T590-libconfig.sh | 10 ++ 1 file changed, 10 insertions(+) diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh index 51dd29c8..36d9af1b 100755 --- a/test/T590-libconfig.sh +++ b/test/T590-libconfig.sh @@ -5,6 +5,14 @@ test_description="library config API" add_email_corpus +get_name () { +if hash getent 2>/dev/null; then +getent passwd "$USER" | cut -d ':' -f 5 +else +echo "Foo Bar" +fi +} + cat < c_head #include #include @@ -402,6 +410,7 @@ NULL USER_FULL_NAME == stderr == EOF +test "$(get_name)" = "" && sed -e "s/USER_FULL_NAME//" -i EXPECTED unset MAILDIR test_expect_equal_file EXPECTED OUTPUT.clean @@ -744,6 +753,7 @@ NULL USER_FULL_NAME == stderr == EOF +test "$(get_name)" = "" && sed -e "s/USER_FULL_NAME//" -i EXPECTED test_expect_equal_file EXPECTED OUTPUT.clean backup_database -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 00/13] test: several fixes and improvements
The current tests fail on my machine due to my configuration, mainly because I didn't have dtach installed, but also other stuff. The following patches fix all the issues I found, and also do plenty of cleanups. Felipe Contreras (13): test: fix passwd_sanitize() test: unset NAME environment variable test: remove USER_FULL_NAME when not present test: use correct fqdn in passwd_sanitize() test: fix wrong SKIP messages test: add prereqs check in test_emacs_expect_t test: add external prereqs to many emacs tests test: split emacs functionality to its own file test: emacs: simplify missing dependencies check test: emacs: check for configured emacs test: emacs: fix a couple of shellcheck complaints test: trivial style cleanups test: more style fixes test/T000-basic.sh | 2 +- test/T070-insert.sh| 2 +- test/T140-excludes.sh | 3 +- test/T160-json.sh | 1 + test/T170-sexp.sh | 1 + test/T190-multipart.sh | 3 +- test/T310-emacs.sh | 2 + test/T320-emacs-large-search-buffer.sh | 3 + test/T330-emacs-subject-to-filename.sh | 3 + test/T350-crypto.sh| 2 + test/T355-smime.sh | 2 + test/T357-index-decryption.sh | 2 + test/T358-emacs-protected-headers.sh | 2 + test/T420-emacs-test-functions.sh | 1 + test/T430-emacs-address-cleaning.sh| 3 + test/T440-emacs-hello.sh | 2 + test/T450-emacs-show.sh| 2 + test/T455-emacs-charsets.sh| 3 + test/T460-emacs-tree.sh| 2 + test/T490-parse-time-string.sh | 6 +- test/T510-thread-replies.sh| 1 + test/T590-libconfig.sh | 10 + test/T590-thread-breakage.sh | 10 +- test/T630-emacs-draft.sh | 2 + test/T720-emacs-attachment-warnings.sh | 3 + test/T730-emacs-forwarding.sh | 3 + test/export-dirs.sh| 3 +- test/test-lib-common.sh| 6 +- test/test-lib-emacs.sh | 209 ++ test/test-lib.sh | 282 - 30 files changed, 310 insertions(+), 266 deletions(-) create mode 100644 test/test-lib-emacs.sh -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 04/13] test: use correct fqdn in passwd_sanitize()
My fqdn is 'natae.localdomain', however, socket.getfqdn() returns 'localhost'. To fetch the true fqdn we need socket.getaddrinfo(). For more information see: https://stackoverflow.com/a/11580042/10474 Signed-off-by: Felipe Contreras --- test/test-lib.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-lib.sh b/test/test-lib.sh index ae653363..21dda265 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -709,7 +709,7 @@ import os, sys, pwd, socket pw = pwd.getpwuid(os.getuid()) user = pw.pw_name name = pw.pw_gecos.partition(",")[0] -fqdn = socket.getfqdn() +fqdn = socket.getaddrinfo(socket.gethostname(), 0, 0, socket.SOCK_STREAM, 0, socket.AI_CANONNAME)[0][3] for l in sys.stdin: if user: -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 05/13] test: fix wrong SKIP messages
When the external prereqs are updated inside the body of the command (e.g. test_emacs) the message in test_report_skip_ is wrong: it outputs the body of the command instead of the subtest name. We need to pass the same argument we pass to test_skip. Signed-off-by: Felipe Contreras --- test/test-lib.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test-lib.sh b/test/test-lib.sh index 21dda265..1067316d 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -919,7 +919,7 @@ test_expect_success () { test_run_ "$1" run_ret="$?" # test_run_ may update missing external prerequisites - test_check_missing_external_prereqs_ "$@" || + test_check_missing_external_prereqs_ "$test_subtest_name" || if [ "$run_ret" = 0 -a "$eval_ret" = 0 ] then test_ok_ @@ -943,7 +943,7 @@ test_expect_code () { test_run_ "$2" run_ret="$?" # test_run_ may update missing external prerequisites, - test_check_missing_external_prereqs_ "$@" || + test_check_missing_external_prereqs_ "$test_subtest_name" || if [ "$run_ret" = 0 -a "$eval_ret" = "$1" ] then test_ok_ -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 06/13] test: add prereqs check in test_emacs_expect_t
test_emacs may update the external prereqs, in which case we want to skip the test rather than fail. Signed-off-by: Felipe Contreras --- test/test-lib.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test-lib.sh b/test/test-lib.sh index 1067316d..72ac2e89 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -592,6 +592,9 @@ test_emacs_expect_t () { exec 1>&6 2>&7 # Restore stdout and stderr inside_subtest= + # test_emacs may update missing external prerequisites + test_check_missing_external_prereqs_ "$test_subtest_name" && return + # Report success/failure. result=$(cat OUTPUT) if [ "$result" = t ] -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 07/13] test: add external prereqs to many emacs tests
The tests fail otherwise. Signed-off-by: Felipe Contreras --- test/T310-emacs.sh| 1 + test/T350-crypto.sh | 1 + test/T355-smime.sh| 1 + test/T357-index-decryption.sh | 1 + test/T450-emacs-show.sh | 1 + test/T460-emacs-tree.sh | 1 + test/T730-emacs-forwarding.sh | 2 ++ test/test-lib.sh | 6 ++ 8 files changed, 14 insertions(+) diff --git a/test/T310-emacs.sh b/test/T310-emacs.sh index 78ac19a8..e64627c6 100755 --- a/test/T310-emacs.sh +++ b/test/T310-emacs.sh @@ -5,6 +5,7 @@ test_description="emacs interface" EXPECTED=$NOTMUCH_SRCDIR/test/emacs.expected-output +test_require_emacs add_email_corpus # syntax errors in test-lib.el cause mysterious failures diff --git a/test/T350-crypto.sh b/test/T350-crypto.sh index 0aada4df..ae1d6a98 100755 --- a/test/T350-crypto.sh +++ b/test/T350-crypto.sh @@ -9,6 +9,7 @@ test_description='PGP/MIME signature verification and decryption' ## +test_require_emacs add_gnupg_home test_begin_subtest "emacs delivery of signed message" diff --git a/test/T355-smime.sh b/test/T355-smime.sh index 8b2b52be..12ac2525 100755 --- a/test/T355-smime.sh +++ b/test/T355-smime.sh @@ -3,6 +3,7 @@ test_description='S/MIME signature verification and decryption' . $(dirname "$0")/test-lib.sh || exit 1 +test_require_emacs test_require_external_prereq openssl test_require_external_prereq gpgsm diff --git a/test/T357-index-decryption.sh b/test/T357-index-decryption.sh index 1ed5f28c..b81bdfe1 100755 --- a/test/T357-index-decryption.sh +++ b/test/T357-index-decryption.sh @@ -7,6 +7,7 @@ test_description='indexing decrypted mail' ## +test_require_emacs add_gnupg_home # create a test encrypted message diff --git a/test/T450-emacs-show.sh b/test/T450-emacs-show.sh index cca56ca3..bd76d378 100755 --- a/test/T450-emacs-show.sh +++ b/test/T450-emacs-show.sh @@ -5,6 +5,7 @@ test_description="emacs notmuch-show view" EXPECTED=$NOTMUCH_SRCDIR/test/emacs-show.expected-output +test_require_emacs add_email_corpus test_begin_subtest "Hiding Original Message region at beginning of a message" diff --git a/test/T460-emacs-tree.sh b/test/T460-emacs-tree.sh index cb2c90b8..195485c1 100755 --- a/test/T460-emacs-tree.sh +++ b/test/T460-emacs-tree.sh @@ -5,6 +5,7 @@ test_description="emacs tree view interface" EXPECTED=$NOTMUCH_SRCDIR/test/emacs-tree.expected-output +test_require_emacs add_email_corpus test_begin_subtest "Basic notmuch-tree view in emacs" diff --git a/test/T730-emacs-forwarding.sh b/test/T730-emacs-forwarding.sh index 45e61568..5d6ac9f0 100755 --- a/test/T730-emacs-forwarding.sh +++ b/test/T730-emacs-forwarding.sh @@ -3,6 +3,8 @@ test_description="emacs forwarding" . $(dirname "$0")/test-lib.sh || exit 1 +test_require_emacs + test_begin_subtest "Forward setting the correct references header" # Check that, when forwarding a message, the new message has # a References-header pointing to the original (forwarded) message. diff --git a/test/test-lib.sh b/test/test-lib.sh index 72ac2e89..88e2a82f 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -114,6 +114,12 @@ unset ALTERNATE_EDITOR unset EMAIL unset NAME +test_require_emacs () { +test_require_external_prereq emacs +test_require_external_prereq ${TEST_EMACSCLIENT} +test_require_external_prereq dtach +} + add_gnupg_home () { [ -e "${GNUPGHOME}/gpg.conf" ] && return -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 08/13] test: split emacs functionality to its own file
This way it's easier to identify the tests that do require emacs stuff. Signed-off-by: Felipe Contreras --- test/T160-json.sh | 1 + test/T170-sexp.sh | 1 + test/T310-emacs.sh | 1 + test/T320-emacs-large-search-buffer.sh | 3 + test/T330-emacs-subject-to-filename.sh | 3 + test/T350-crypto.sh| 1 + test/T355-smime.sh | 1 + test/T357-index-decryption.sh | 1 + test/T358-emacs-protected-headers.sh | 2 + test/T420-emacs-test-functions.sh | 1 + test/T430-emacs-address-cleaning.sh| 3 + test/T440-emacs-hello.sh | 2 + test/T450-emacs-show.sh| 1 + test/T455-emacs-charsets.sh| 3 + test/T460-emacs-tree.sh| 1 + test/T510-thread-replies.sh| 1 + test/T630-emacs-draft.sh | 2 + test/T720-emacs-attachment-warnings.sh | 3 + test/T730-emacs-forwarding.sh | 1 + test/test-lib-emacs.sh | 213 + test/test-lib.sh | 199 --- 21 files changed, 245 insertions(+), 199 deletions(-) create mode 100644 test/test-lib-emacs.sh diff --git a/test/T160-json.sh b/test/T160-json.sh index e8b75605..638afb4d 100755 --- a/test/T160-json.sh +++ b/test/T160-json.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash test_description="--format=json output" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 test_begin_subtest "Show message: json" add_message "[subject]=\"json-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" "[bcc]=\"test_suite+...@notmuchmail.org\"" "[reply-to]=\"test_suite+repl...@notmuchmail.org\"" "[body]=\"json-show-message\"" diff --git a/test/T170-sexp.sh b/test/T170-sexp.sh index 24be8351..af8c4b44 100755 --- a/test/T170-sexp.sh +++ b/test/T170-sexp.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash test_description="--format=sexp output" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 test_begin_subtest "Show message: sexp" add_message "[subject]=\"sexp-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" "[bcc]=\"test_suite+...@notmuchmail.org\"" "[reply-to]=\"test_suite+repl...@notmuchmail.org\"" "[body]=\"sexp-show-message\"" diff --git a/test/T310-emacs.sh b/test/T310-emacs.sh index e64627c6..c08df5fc 100755 --- a/test/T310-emacs.sh +++ b/test/T310-emacs.sh @@ -2,6 +2,7 @@ test_description="emacs interface" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 EXPECTED=$NOTMUCH_SRCDIR/test/emacs.expected-output diff --git a/test/T320-emacs-large-search-buffer.sh b/test/T320-emacs-large-search-buffer.sh index f61e8a97..d2638c8b 100755 --- a/test/T320-emacs-large-search-buffer.sh +++ b/test/T320-emacs-large-search-buffer.sh @@ -1,11 +1,14 @@ #!/usr/bin/env bash test_description="Emacs with large search results buffer" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 x=xx # 10 x=$x$x$x$x$x$x$x$x$x$x # 100 x=$x$x$x$x$x$x$x$x$x # 900 +test_require_emacs + # We generate a long subject here (over 900 bytes) so that the emacs # search results get large quickly. With 30 such messages we should # cross several 4kB page boundaries and see the bug. diff --git a/test/T330-emacs-subject-to-filename.sh b/test/T330-emacs-subject-to-filename.sh index eaf7c980..6e09a048 100755 --- a/test/T330-emacs-subject-to-filename.sh +++ b/test/T330-emacs-subject-to-filename.sh @@ -2,6 +2,9 @@ test_description="emacs: mail subject to filename" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 + +test_require_emacs # emacs server can't be started in a child process with $(test_emacs ...) test_emacs '(ignore)' > /dev/null diff --git a/test/T350-crypto.sh b/test/T350-crypto.sh index ae1d6a98..4508c984 100755 --- a/test/T350-crypto.sh +++ b/test/T350-crypto.sh @@ -6,6 +6,7 @@ test_description='PGP/MIME signature verification and decryption' . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 ## diff --git a/test/T355-smime.sh b/test/T355-smime.sh index 12ac2525..69bdcfac 100755 --- a/test/T355-smime.sh +++ b/test/T355-smime.sh @@ -2,6 +2,7 @@ test_description='S/MIME signature verification and decryption' . $(dirname "$0")/test-lib.sh ||
[PATCH 09/13] test: emacs: simplify missing dependencies check
No functional changes. Signed-off-by: Felipe Contreras --- test/test-lib-emacs.sh | 14 ++ 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/test/test-lib-emacs.sh b/test/test-lib-emacs.sh index ecad501a..83f5b10b 100644 --- a/test/test-lib-emacs.sh +++ b/test/test-lib-emacs.sh @@ -15,9 +15,11 @@ # along with this program. If not, see https://www.gnu.org/licenses/ . test_require_emacs () { -test_require_external_prereq emacs -test_require_external_prereq ${TEST_EMACSCLIENT} -test_require_external_prereq dtach +local ret=0 +test_require_external_prereq emacs || ret=1 +test_require_external_prereq ${TEST_EMACSCLIENT} || ret=1 +test_require_external_prereq dtach || ret=1 +return $ret } # Deliver a message with emacs and add it to the database @@ -167,11 +169,7 @@ EOF test_emacs () { # test dependencies beforehand to avoid the waiting loop below - missing_dependencies= - test_require_external_prereq dtach || missing_dependencies=1 - test_require_external_prereq emacs || missing_dependencies=1 - test_require_external_prereq ${TEST_EMACSCLIENT} || missing_dependencies=1 - test -z "$missing_dependencies" || return + test_require_emacs || return if [ -z "$EMACS_SERVER" ]; then emacs_tests="$NOTMUCH_SRCDIR/test/${this_test_bare}.el" -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 10/13] test: emacs: check for configured emacs
Commit d59d9c81 (test: Make the emacsclient binary user-configurable, 2012-11-27) modified the prereq check for the configured emacsclient, but we probably want to do the same for emacs itself. Signed-off-by: Felipe Contreras --- test/test-lib-emacs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-lib-emacs.sh b/test/test-lib-emacs.sh index 83f5b10b..3075fa59 100644 --- a/test/test-lib-emacs.sh +++ b/test/test-lib-emacs.sh @@ -16,7 +16,7 @@ test_require_emacs () { local ret=0 -test_require_external_prereq emacs || ret=1 +test_require_external_prereq ${TEST_EMACS} || ret=1 test_require_external_prereq ${TEST_EMACSCLIENT} || ret=1 test_require_external_prereq dtach || ret=1 return $ret -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 11/13] test: emacs: fix a couple of shellcheck complaints
In test-lib-emacs.sh line 20: test_require_external_prereq ${TEST_EMACS} || ret=1 ^---^ SC2086: Double quote to prevent globbing and word splitting. Did you mean: test_require_external_prereq "${TEST_EMACS}" || ret=1 In test-lib-emacs.sh line 21: test_require_external_prereq ${TEST_EMACSCLIENT} || ret=1 ^-^ SC2086: Double quote to prevent globbing and word splitting. Did you mean: test_require_external_prereq "${TEST_EMACSCLIENT}" || ret=1 Signed-off-by: Felipe Contreras --- test/test-lib-emacs.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test-lib-emacs.sh b/test/test-lib-emacs.sh index 3075fa59..bf875a28 100644 --- a/test/test-lib-emacs.sh +++ b/test/test-lib-emacs.sh @@ -16,8 +16,8 @@ test_require_emacs () { local ret=0 -test_require_external_prereq ${TEST_EMACS} || ret=1 -test_require_external_prereq ${TEST_EMACSCLIENT} || ret=1 +test_require_external_prereq "$TEST_EMACS" || ret=1 +test_require_external_prereq "$TEST_EMACSCLIENT" || ret=1 test_require_external_prereq dtach || ret=1 return $ret } -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 12/13] test: trivial style cleanups
Signed-off-by: Felipe Contreras --- test/T000-basic.sh | 2 +- test/T070-insert.sh | 2 +- test/T590-thread-breakage.sh | 10 +- test/export-dirs.sh | 2 +- test/test-lib.sh | 8 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/test/T000-basic.sh b/test/T000-basic.sh index 7fbdcfa3..a2f4d93f 100755 --- a/test/T000-basic.sh +++ b/test/T000-basic.sh @@ -33,7 +33,7 @@ test_begin_subtest 'failure to clean up causes the test to fail' test_expect_code 2 'test_when_finished "(exit 2)"' EXPECTED=$NOTMUCH_SRCDIR/test/test.expected-output -suppress_diff_date() { +suppress_diff_date () { sed -e 's/\(.*\-\-\- test-verbose\.4\.\expected\).*/\1/' \ -e 's/\(.*\+\+\+ test-verbose\.4\.\output\).*/\1/' } diff --git a/test/T070-insert.sh b/test/T070-insert.sh index b37a9b67..208deb1c 100755 --- a/test/T070-insert.sh +++ b/test/T070-insert.sh @@ -15,7 +15,7 @@ notmuch new > /dev/null # They happen to be in the mail directory already but that is okay # since we do not call notmuch new hereafter. -gen_insert_msg() { +gen_insert_msg () { generate_message \ "[subject]=\"insert-subject\"" \ "[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" \ diff --git a/test/T590-thread-breakage.sh b/test/T590-thread-breakage.sh index aeb82cf4..92a70e3e 100755 --- a/test/T590-thread-breakage.sh +++ b/test/T590-thread-breakage.sh @@ -21,7 +21,7 @@ test_description='thread breakage during reindexing' . $(dirname "$0")/test-lib.sh || exit 1 -message_a() { +message_a () { mkdir -p ${MAIL_DIR}/cur cat > ${MAIL_DIR}/cur/a < ${MAIL_DIR}/cur/b < OUTPUT } -test_ruby() { +test_ruby () { MAIL_DIR=$MAIL_DIR $NOTMUCH_RUBY -I "$NOTMUCH_BUILDDIR/bindings/ruby"> OUTPUT } -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 13/13] test: more style fixes
In order to fit the git coding style. Signed-off-by: Felipe Contreras --- test/T140-excludes.sh | 3 +- test/T190-multipart.sh | 3 +- test/T490-parse-time-string.sh | 6 +-- test/export-dirs.sh| 3 +- test/test-lib-common.sh| 6 +-- test/test-lib-emacs.sh | 6 +-- test/test-lib.sh | 72 -- 7 files changed, 33 insertions(+), 66 deletions(-) diff --git a/test/T140-excludes.sh b/test/T140-excludes.sh index acab5381..352b3eb8 100755 --- a/test/T140-excludes.sh +++ b/test/T140-excludes.sh @@ -5,8 +5,7 @@ test_description='"notmuch search, count and show" with excludes in several vari # Generates a thread consisting of a top level message and 'length' # replies. The subject of the top message 'subject: top message" # and the subject of the nth reply in the thread is "subject: reply n" -generate_thread () -{ +generate_thread () { local subject="$1" local length="$2" generate_message '[subject]="'"${subject}: top message"'"' '[body]="'"body of top message"'"' diff --git a/test/T190-multipart.sh b/test/T190-multipart.sh index 6f715ff9..3545a599 100755 --- a/test/T190-multipart.sh +++ b/test/T190-multipart.sh @@ -725,8 +725,7 @@ EOF notmuch new > /dev/null -cat_expected_head () -{ +cat_expected_head () { cat < /dev/null } diff --git a/test/test-lib-emacs.sh b/test/test-lib-emacs.sh index bf875a28..dde32177 100644 --- a/test/test-lib-emacs.sh +++ b/test/test-lib-emacs.sh @@ -28,8 +28,7 @@ test_require_emacs () { # Accepts arbitrary extra emacs/elisp functions to modify the message # before sending, which is useful to doing things like attaching files # to the message and encrypting/signing. -emacs_deliver_message () -{ +emacs_deliver_message () { local subject body smtp_dummy_pid smtp_dummy_port subject="$1" body="$2" @@ -75,8 +74,7 @@ emacs_deliver_message () # If any GNU-style long-arguments (like --quiet or --decrypt=true) are # at the head of the argument list, they are sent directly to "notmuch # new" after message delivery -emacs_fcc_message () -{ +emacs_fcc_message () { local nmn_args subject body nmn_args='' while [[ "$1" =~ ^-- ]]; do diff --git a/test/test-lib.sh b/test/test-lib.sh index 1b502456..1d0178f0 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -114,8 +114,7 @@ unset ALTERNATE_EDITOR unset EMAIL unset NAME -add_gnupg_home () -{ +add_gnupg_home () { [ -e "${GNUPGHOME}/gpg.conf" ] && return _gnupg_exit () { gpgconf --kill all 2>/dev/null || true; } at_exit_function _gnupg_exit @@ -135,8 +134,7 @@ add_gnupg_home () printf '%s:6:\n' "$FINGERPRINT" | gpg --quiet --batch --no-tty --import-ownertrust } -add_gpgsm_home () -{ +add_gpgsm_home () { local fpr [ -e "$GNUPGHOME/gpgsm.conf" ] && return _gnupg_exit () { gpgconf --kill all 2>/dev/null || true; } @@ -268,8 +266,7 @@ then fi test_description_printed= -print_test_description () -{ +print_test_description () { test -z "$test_description_printed" || return 0 echo echo $this_test: "Testing ${test_description}" @@ -351,8 +348,7 @@ trap 'trap_signal' HUP INT TERM # history of the notmuch mailing list, which allows for reliably # testing commands that need to operate on a not-totally-trivial # number of messages. -add_email_corpus () -{ +add_email_corpus () { local corpus corpus=${1:-default} @@ -361,8 +357,7 @@ add_email_corpus () notmuch new >/dev/null || die "'notmuch new' failed while adding email corpus" } -test_begin_subtest () -{ +test_begin_subtest () { if [ -n "$inside_subtest" ]; then exec 1>&6 2>&7 # Restore stdout and stderr error "bug in test script: Missing test_expect_equal in ${BASH_SOURCE[1]}:${BASH_LINENO[0]}" @@ -382,8 +377,7 @@ test_begin_subtest () # not accept a test name. Instead, the caller should call # test_begin_subtest before calling this function in order to set the # name. -test_expect_equal () -{ +test_expect_equal () { local output expected testname exec 1>&6 2>&7 # Restore stdout and stderr if [ -z "$inside_subtest" ]; then @@ -409,8 +403,7 @@ test_expect_equal () } # Like test_expect_equal, but takes two filenames. -test_expect_equal_file () -{ +test_expect_equal_file () { local file1 file2 testname basename1 basename2 exec 1>&6 2>&7 # Restore stdout and stderr if [ -z "$inside_subtest" ]; then @@ -491,19 +484,16 @@ test_json_no
[PATCH 1/9] test: move test_ruby() inside the only client
Not much point in polluting the main library, and also will be useful to modify it in tandem with the tests. Signed-off-by: Felipe Contreras --- test/T395-ruby.sh | 4 test/test-lib.sh | 4 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index a0b76eb8..fec1f5ef 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -8,6 +8,10 @@ fi add_email_corpus +test_ruby() { +MAIL_DIR=$MAIL_DIR $NOTMUCH_RUBY -I "$NOTMUCH_BUILDDIR/bindings/ruby"> OUTPUT +} + test_begin_subtest "compare thread ids" test_ruby <<"EOF" require 'notmuch' diff --git a/test/test-lib.sh b/test/test-lib.sh index 4c9f2a21..ec0ba7f7 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -1109,10 +1109,6 @@ test_python() { $NOTMUCH_PYTHON -B - > OUTPUT } -test_ruby() { -MAIL_DIR=$MAIL_DIR $NOTMUCH_RUBY -I "$NOTMUCH_BUILDDIR/bindings/ruby"> OUTPUT -} - test_C () { local exec_file test_file exec_file="test${test_count}" -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 4/9] test: ruby: simplify MAIL_DIR initialization
There's no need to complicate the script passing the MAIL_DIR environment variable. Signed-off-by: Felipe Contreras --- test/T395-ruby.sh | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index 94fab106..67d6e205 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -10,13 +10,12 @@ add_email_corpus test_ruby() { ( - cat <<-\EOF + cat <<-EOF require 'notmuch' - $maildir = ENV['MAIL_DIR'] || abort('MAIL_DIR not set') - @db = Notmuch::Database.new($maildir) + @db = Notmuch::Database.new('$MAIL_DIR') EOF cat -) | MAIL_DIR=$MAIL_DIR $NOTMUCH_RUBY -I "$NOTMUCH_BUILDDIR/bindings/ruby"> OUTPUT +) | $NOTMUCH_RUBY -I "$NOTMUCH_BUILDDIR/bindings/ruby"> OUTPUT } test_begin_subtest "compare thread ids" -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 2/9] test: ruby: refactor test_ruby()
There's no point in repeating the same initialization in all the tests. Signed-off-by: Felipe Contreras --- test/T395-ruby.sh | 48 +++ 1 file changed, 11 insertions(+), 37 deletions(-) diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index fec1f5ef..1d27e191 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -9,17 +9,21 @@ fi add_email_corpus test_ruby() { -MAIL_DIR=$MAIL_DIR $NOTMUCH_RUBY -I "$NOTMUCH_BUILDDIR/bindings/ruby"> OUTPUT +( + cat <<-\EOF + require 'notmuch' + $maildir = ENV['MAIL_DIR'] + if not $maildir then + abort('environment variable MAIL_DIR must be set') + end + @db = Notmuch::Database.new($maildir) + EOF + cat +) | MAIL_DIR=$MAIL_DIR $NOTMUCH_RUBY -I "$NOTMUCH_BUILDDIR/bindings/ruby"> OUTPUT } test_begin_subtest "compare thread ids" test_ruby <<"EOF" -require 'notmuch' -$maildir = ENV['MAIL_DIR'] -if not $maildir then - abort('environment variable MAIL_DIR must be set') -end -@db = Notmuch::Database.new($maildir) @q = @db.query('tag:inbox') @q.sort = Notmuch::SORT_OLDEST_FIRST for t in @q.search_threads do @@ -31,12 +35,6 @@ test_expect_equal_file EXPECTED OUTPUT test_begin_subtest "compare message ids" test_ruby <<"EOF" -require 'notmuch' -$maildir = ENV['MAIL_DIR'] -if not $maildir then - abort('environment variable MAIL_DIR must be set') -end -@db = Notmuch::Database.new($maildir) @q = @db.query('tag:inbox') @q.sort = Notmuch::SORT_OLDEST_FIRST for m in @q.search_messages do @@ -48,12 +46,6 @@ test_expect_equal_file EXPECTED OUTPUT test_begin_subtest "get non-existent file" test_ruby <<"EOF" -require 'notmuch' -$maildir = ENV['MAIL_DIR'] -if not $maildir then - abort('environment variable MAIL_DIR must be set') -end -@db = Notmuch::Database.new($maildir) result = @db.find_message_by_filename('i-dont-exist') print (result == nil) EOF @@ -61,12 +53,6 @@ test_expect_equal "$(cat OUTPUT)" "true" test_begin_subtest "count messages" test_ruby <<"EOF" -require 'notmuch' -$maildir = ENV['MAIL_DIR'] -if not $maildir then - abort('environment variable MAIL_DIR must be set') -end -@db = Notmuch::Database.new($maildir) @q = @db.query('tag:inbox') print @q.count_messages(),"\n" EOF @@ -75,12 +61,6 @@ test_expect_equal_file EXPECTED OUTPUT test_begin_subtest "count threads" test_ruby <<"EOF" -require 'notmuch' -$maildir = ENV['MAIL_DIR'] -if not $maildir then - abort('environment variable MAIL_DIR must be set') -end -@db = Notmuch::Database.new($maildir) @q = @db.query('tag:inbox') print @q.count_threads(),"\n" EOF @@ -89,12 +69,6 @@ test_expect_equal_file EXPECTED OUTPUT test_begin_subtest "get all tags" test_ruby <<"EOF" -require 'notmuch' -$maildir = ENV['MAIL_DIR'] -if not $maildir then - abort('environment variable MAIL_DIR must be set') -end -@db = Notmuch::Database.new($maildir) @t = @db.all_tags() for tag in @t do print tag,"\n" -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 3/9] test: ruby: simplify MAIL_DIR check
Signed-off-by: Felipe Contreras --- test/T395-ruby.sh | 5 + 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index 1d27e191..94fab106 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -12,10 +12,7 @@ test_ruby() { ( cat <<-\EOF require 'notmuch' - $maildir = ENV['MAIL_DIR'] - if not $maildir then - abort('environment variable MAIL_DIR must be set') - end + $maildir = ENV['MAIL_DIR'] || abort('MAIL_DIR not set') @db = Notmuch::Database.new($maildir) EOF cat -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 0/9] test: ruby: several cleanups and simplifications
I found a lot of areas of improvement in the Ruby tests, so I decided to clean them up. With these changes the tests are now much simpler and follow more closely the typical Ruby idioms. Felipe Contreras (9): test: move test_ruby() inside the only client test: ruby: refactor test_ruby() test: ruby: simplify MAIL_DIR check test: ruby: simplify MAIL_DIR initialization test: ruby: simplify test_ruby() test: ruby: use much more standard puts test: ruby: use much more standard Ruby idioms test: ruby: don't use instance variables test: ruby: simplify output comparison test/T395-ruby.sh | 94 +++ test/test-lib.sh | 4 -- 2 files changed, 30 insertions(+), 68 deletions(-) -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 5/9] test: ruby: simplify test_ruby()
We always do test_expect_equal_file, so do it in test_ruby() directly. The only subtest where we don't (get non-existent file) can be easily modified. Signed-off-by: Felipe Contreras --- test/T395-ruby.sh | 18 +++--- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index 67d6e205..55bf4c2b 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -16,9 +16,11 @@ test_ruby() { EOF cat ) | $NOTMUCH_RUBY -I "$NOTMUCH_BUILDDIR/bindings/ruby"> OUTPUT +test_expect_equal_file EXPECTED OUTPUT } test_begin_subtest "compare thread ids" +notmuch search --sort=oldest-first --output=threads tag:inbox | sed s/^thread:// > EXPECTED test_ruby <<"EOF" @q = @db.query('tag:inbox') @q.sort = Notmuch::SORT_OLDEST_FIRST @@ -26,10 +28,9 @@ for t in @q.search_threads do print t.thread_id, "\n" end EOF -notmuch search --sort=oldest-first --output=threads tag:inbox | sed s/^thread:// > EXPECTED -test_expect_equal_file EXPECTED OUTPUT test_begin_subtest "compare message ids" +notmuch search --sort=oldest-first --output=messages tag:inbox | sed s/^id:// > EXPECTED test_ruby <<"EOF" @q = @db.query('tag:inbox') @q.sort = Notmuch::SORT_OLDEST_FIRST @@ -37,40 +38,35 @@ for m in @q.search_messages do print m.message_id, "\n" end EOF -notmuch search --sort=oldest-first --output=messages tag:inbox | sed s/^id:// > EXPECTED -test_expect_equal_file EXPECTED OUTPUT test_begin_subtest "get non-existent file" +echo -n true > EXPECTED test_ruby <<"EOF" result = @db.find_message_by_filename('i-dont-exist') print (result == nil) EOF -test_expect_equal "$(cat OUTPUT)" "true" test_begin_subtest "count messages" +notmuch count --output=messages tag:inbox > EXPECTED test_ruby <<"EOF" @q = @db.query('tag:inbox') print @q.count_messages(),"\n" EOF -notmuch count --output=messages tag:inbox > EXPECTED -test_expect_equal_file EXPECTED OUTPUT test_begin_subtest "count threads" +notmuch count --output=threads tag:inbox > EXPECTED test_ruby <<"EOF" @q = @db.query('tag:inbox') print @q.count_threads(),"\n" EOF -notmuch count --output=threads tag:inbox > EXPECTED -test_expect_equal_file EXPECTED OUTPUT test_begin_subtest "get all tags" +notmuch search --output=tags '*' > EXPECTED test_ruby <<"EOF" @t = @db.all_tags() for tag in @t do print tag,"\n" end EOF -notmuch search --output=tags '*' > EXPECTED -test_expect_equal_file EXPECTED OUTPUT test_done -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 6/9] test: ruby: use much more standard puts
Signed-off-by: Felipe Contreras --- test/T395-ruby.sh | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index 55bf4c2b..f871ddd9 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -25,7 +25,7 @@ test_ruby <<"EOF" @q = @db.query('tag:inbox') @q.sort = Notmuch::SORT_OLDEST_FIRST for t in @q.search_threads do - print t.thread_id, "\n" + puts t.thread_id end EOF @@ -35,29 +35,29 @@ test_ruby <<"EOF" @q = @db.query('tag:inbox') @q.sort = Notmuch::SORT_OLDEST_FIRST for m in @q.search_messages do - print m.message_id, "\n" + puts m.message_id end EOF test_begin_subtest "get non-existent file" -echo -n true > EXPECTED +echo true > EXPECTED test_ruby <<"EOF" result = @db.find_message_by_filename('i-dont-exist') -print (result == nil) +puts (result == nil) EOF test_begin_subtest "count messages" notmuch count --output=messages tag:inbox > EXPECTED test_ruby <<"EOF" @q = @db.query('tag:inbox') -print @q.count_messages(),"\n" +puts @q.count_messages() EOF test_begin_subtest "count threads" notmuch count --output=threads tag:inbox > EXPECTED test_ruby <<"EOF" @q = @db.query('tag:inbox') -print @q.count_threads(),"\n" +puts @q.count_threads() EOF test_begin_subtest "get all tags" @@ -65,7 +65,7 @@ notmuch search --output=tags '*' > EXPECTED test_ruby <<"EOF" @t = @db.all_tags() for tag in @t do - print tag,"\n" + puts tag end EOF -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 7/9] test: ruby: use much more standard Ruby idioms
Signed-off-by: Felipe Contreras --- test/T395-ruby.sh | 20 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index f871ddd9..f5a8d245 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -24,7 +24,7 @@ notmuch search --sort=oldest-first --output=threads tag:inbox | sed s/^thread:// test_ruby <<"EOF" @q = @db.query('tag:inbox') @q.sort = Notmuch::SORT_OLDEST_FIRST -for t in @q.search_threads do +@q.search_threads.each do |t| puts t.thread_id end EOF @@ -34,38 +34,34 @@ notmuch search --sort=oldest-first --output=messages tag:inbox | sed s/^id:// > test_ruby <<"EOF" @q = @db.query('tag:inbox') @q.sort = Notmuch::SORT_OLDEST_FIRST -for m in @q.search_messages do +@q.search_messages.each do |m| puts m.message_id end EOF test_begin_subtest "get non-existent file" -echo true > EXPECTED +echo nil > EXPECTED test_ruby <<"EOF" -result = @db.find_message_by_filename('i-dont-exist') -puts (result == nil) +p @db.find_message_by_filename('i-dont-exist') EOF test_begin_subtest "count messages" notmuch count --output=messages tag:inbox > EXPECTED test_ruby <<"EOF" -@q = @db.query('tag:inbox') -puts @q.count_messages() +puts @db.query('tag:inbox').count_messages() EOF test_begin_subtest "count threads" notmuch count --output=threads tag:inbox > EXPECTED test_ruby <<"EOF" -@q = @db.query('tag:inbox') -puts @q.count_threads() +puts @db.query('tag:inbox').count_threads() EOF test_begin_subtest "get all tags" notmuch search --output=tags '*' > EXPECTED test_ruby <<"EOF" -@t = @db.all_tags() -for tag in @t do - puts tag +@db.all_tags.each do |tag| + puts tag end EOF -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 8/9] test: ruby: don't use instance variables
Local variables are perfectly fine. Signed-off-by: Felipe Contreras --- test/T395-ruby.sh | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index f5a8d245..30168109 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -12,7 +12,7 @@ test_ruby() { ( cat <<-EOF require 'notmuch' - @db = Notmuch::Database.new('$MAIL_DIR') + db = Notmuch::Database.new('$MAIL_DIR') EOF cat ) | $NOTMUCH_RUBY -I "$NOTMUCH_BUILDDIR/bindings/ruby"> OUTPUT @@ -22,9 +22,9 @@ test_ruby() { test_begin_subtest "compare thread ids" notmuch search --sort=oldest-first --output=threads tag:inbox | sed s/^thread:// > EXPECTED test_ruby <<"EOF" -@q = @db.query('tag:inbox') -@q.sort = Notmuch::SORT_OLDEST_FIRST -@q.search_threads.each do |t| +q = db.query('tag:inbox') +q.sort = Notmuch::SORT_OLDEST_FIRST +q.search_threads.each do |t| puts t.thread_id end EOF @@ -32,9 +32,9 @@ EOF test_begin_subtest "compare message ids" notmuch search --sort=oldest-first --output=messages tag:inbox | sed s/^id:// > EXPECTED test_ruby <<"EOF" -@q = @db.query('tag:inbox') -@q.sort = Notmuch::SORT_OLDEST_FIRST -@q.search_messages.each do |m| +q = db.query('tag:inbox') +q.sort = Notmuch::SORT_OLDEST_FIRST +q.search_messages.each do |m| puts m.message_id end EOF @@ -42,25 +42,25 @@ EOF test_begin_subtest "get non-existent file" echo nil > EXPECTED test_ruby <<"EOF" -p @db.find_message_by_filename('i-dont-exist') +p db.find_message_by_filename('i-dont-exist') EOF test_begin_subtest "count messages" notmuch count --output=messages tag:inbox > EXPECTED test_ruby <<"EOF" -puts @db.query('tag:inbox').count_messages() +puts db.query('tag:inbox').count_messages() EOF test_begin_subtest "count threads" notmuch count --output=threads tag:inbox > EXPECTED test_ruby <<"EOF" -puts @db.query('tag:inbox').count_threads() +puts db.query('tag:inbox').count_threads() EOF test_begin_subtest "get all tags" notmuch search --output=tags '*' > EXPECTED test_ruby <<"EOF" -@db.all_tags.each do |tag| +db.all_tags.each do |tag| puts tag end EOF -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 9/9] test: ruby: simplify output comparison
Signed-off-by: Felipe Contreras --- test/T395-ruby.sh | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index 30168109..597330d3 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -20,22 +20,22 @@ test_ruby() { } test_begin_subtest "compare thread ids" -notmuch search --sort=oldest-first --output=threads tag:inbox | sed s/^thread:// > EXPECTED +notmuch search --sort=oldest-first --output=threads tag:inbox > EXPECTED test_ruby <<"EOF" q = db.query('tag:inbox') q.sort = Notmuch::SORT_OLDEST_FIRST q.search_threads.each do |t| - puts t.thread_id + puts 'thread:%s' % t.thread_id end EOF test_begin_subtest "compare message ids" -notmuch search --sort=oldest-first --output=messages tag:inbox | sed s/^id:// > EXPECTED +notmuch search --sort=oldest-first --output=messages tag:inbox > EXPECTED test_ruby <<"EOF" q = db.query('tag:inbox') q.sort = Notmuch::SORT_OLDEST_FIRST q.search_messages.each do |m| - puts m.message_id + puts 'id:%s' % m.message_id end EOF -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 0/3] ruby: improve db.query
I find it a bit annoying to have to modify the query object to add options when Notmuch::Database.query() can do that just fine. This series also adds a mapping to the notmuch_exclude_t enum in order to be able to specify NOTMUCH_EXCLUDE_ALL and others. This patch series goes on top of my ruby test cleanups [1]. [1] id:20210501115923.483816-1-felipe.contre...@gmail.com Felipe Contreras (3): ruby: use notmuch_exclude_t enum ruby: add keyword arguments to db.query test: ruby: simplify basic tests bindings/ruby/database.c | 47 +--- bindings/ruby/defs.h | 2 +- bindings/ruby/init.c | 26 +- bindings/ruby/query.c| 8 --- test/T395-ruby.sh| 47 +--- 5 files changed, 114 insertions(+), 16 deletions(-) -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 1/3] ruby: use notmuch_exclude_t enum
It exists since 2013, let's allow it to be used in Ruby. Signed-off-by: Felipe Contreras --- bindings/ruby/init.c | 24 bindings/ruby/query.c | 8 +--- test/T395-ruby.sh | 17 + 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/bindings/ruby/init.c b/bindings/ruby/init.c index 819fd1e3..fd73ed8f 100644 --- a/bindings/ruby/init.c +++ b/bindings/ruby/init.c @@ -133,6 +133,30 @@ Init_notmuch (void) * Maximum allowed length of a tag */ rb_define_const (mod, "TAG_MAX", INT2FIX (NOTMUCH_TAG_MAX)); +/* + * Document-const: Notmuch::EXCLUDE_FLAG + * + * Only flag excluded results + */ +rb_define_const (mod, "EXCLUDE_FLAG", INT2FIX (NOTMUCH_EXCLUDE_FLAG)); +/* + * Document-const: Notmuch::EXCLUDE_TRUE + * + * Exclude messages from the results + */ +rb_define_const (mod, "EXCLUDE_TRUE", INT2FIX (NOTMUCH_EXCLUDE_TRUE)); +/* + * Document-const: Notmuch::EXCLUDE_FALSE + * + * Don't exclude anything + */ +rb_define_const (mod, "EXCLUDE_FALSE", INT2FIX (NOTMUCH_EXCLUDE_FALSE)); +/* + * Document-const: Notmuch::EXCLUDE_ALL + * + * Exclude all results + */ +rb_define_const (mod, "EXCLUDE_ALL", INT2FIX (NOTMUCH_EXCLUDE_ALL)); /* * Document-class: Notmuch::BaseError diff --git a/bindings/ruby/query.c b/bindings/ruby/query.c index 8b46d700..99148c36 100644 --- a/bindings/ruby/query.c +++ b/bindings/ruby/query.c @@ -107,19 +107,21 @@ notmuch_rb_query_add_tag_exclude (VALUE self, VALUE tagv) } /* - * call-seq: QUERY.omit_excluded=(boolean) => nil + * call-seq: QUERY.omit_excluded=(fixnum) => nil * * Specify whether to omit excluded results or simply flag them. - * By default, this is set to +true+. + * By default, this is set to +Notmuch::EXCLUDE_TRUE+. */ VALUE notmuch_rb_query_set_omit_excluded (VALUE self, VALUE omitv) { notmuch_query_t *query; +notmuch_exclude_t value; Data_Get_Notmuch_Query (self, query); -notmuch_query_set_omit_excluded (query, RTEST (omitv)); +value = FIXNUM_P (omitv) ? FIX2UINT (omitv) : RTEST(omitv); +notmuch_query_set_omit_excluded (query, value); return Qnil; } diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index 597330d3..d36d4aff 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -65,4 +65,21 @@ db.all_tags.each do |tag| end EOF +notmuch config set search.exclude_tags deleted +generate_message '[subject]="Good"' +generate_message '[subject]="Bad"' "[in-reply-to]=\<$gen_msg_id\>" +notmuch new > /dev/null +notmuch tag +deleted id:$gen_msg_id + +test_begin_subtest "omit excluded all" +notmuch search --output=threads --exclude=all tag:inbox > EXPECTED +test_ruby <<"EOF" +q = db.query('tag:inbox') +q.add_tag_exclude('deleted') +q.omit_excluded = Notmuch::EXCLUDE_ALL +q.search_threads.each do |t| + puts 'thread:%s' % t.thread_id +end +EOF + test_done -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 3/3] test: ruby: simplify basic tests
We don't need to check for the order here, that is done in another test. Signed-off-by: Felipe Contreras --- test/T395-ruby.sh | 12 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index e828efed..9298bc9e 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -20,21 +20,17 @@ test_ruby() { } test_begin_subtest "compare thread ids" -notmuch search --sort=oldest-first --output=threads tag:inbox > EXPECTED +notmuch search --output=threads tag:inbox > EXPECTED test_ruby <<"EOF" -q = db.query('tag:inbox') -q.sort = Notmuch::SORT_OLDEST_FIRST -q.search_threads.each do |t| +db.query('tag:inbox').search_threads.each do |t| puts 'thread:%s' % t.thread_id end EOF test_begin_subtest "compare message ids" -notmuch search --sort=oldest-first --output=messages tag:inbox > EXPECTED +notmuch search --output=messages tag:inbox > EXPECTED test_ruby <<"EOF" -q = db.query('tag:inbox') -q.sort = Notmuch::SORT_OLDEST_FIRST -q.search_messages.each do |m| +db.query('tag:inbox').search_messages.each do |m| puts 'id:%s' % m.message_id end EOF -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 2/3] ruby: add keyword arguments to db.query
That way we don't need pass them to the query object ourselves. Signed-off-by: Felipe Contreras --- bindings/ruby/database.c | 47 +--- bindings/ruby/defs.h | 2 +- bindings/ruby/init.c | 2 +- test/T395-ruby.sh| 18 +++ 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/bindings/ruby/database.c b/bindings/ruby/database.c index 416eb709..313a4338 100644 --- a/bindings/ruby/database.c +++ b/bindings/ruby/database.c @@ -399,17 +399,24 @@ notmuch_rb_database_get_all_tags (VALUE self) } /* - * call-seq: DB.query(query) => QUERY + * call-seq: + * DB.query(query) => QUERY + * DB.query(query, sort:, excluded_tags:, omit_excluded:) => QUERY * - * Retrieve a query object for the query string 'query' + * Retrieve a query object for the query string 'query'. When using keyword + * arguments they are passwed to the query object. */ VALUE -notmuch_rb_database_query_create (VALUE self, VALUE qstrv) +notmuch_rb_database_query_create (int argc, VALUE *argv, VALUE self) { +VALUE qstrv; +VALUE opts; const char *qstr; notmuch_query_t *query; notmuch_database_t *db; +rb_scan_args (argc, argv, "1:", &qstrv, &opts); + Data_Get_Notmuch_Database (self, db); SafeStringValue (qstrv); @@ -419,5 +426,39 @@ notmuch_rb_database_query_create (VALUE self, VALUE qstrv) if (!query) rb_raise (notmuch_rb_eMemoryError, "Out of memory"); +if (!NIL_P (opts)) { + VALUE sort, exclude_tags, omit_excluded; + VALUE kwargs[3]; + static ID keyword_ids[3]; + + if (!keyword_ids[0]) { + keyword_ids[0] = rb_intern_const ("sort"); + keyword_ids[1] = rb_intern_const ("exclude_tags"); + keyword_ids[2] = rb_intern_const ("omit_excluded"); + } + + rb_get_kwargs (opts, keyword_ids, 0, 3, kwargs); + + sort = kwargs[0]; + exclude_tags = kwargs[1]; + omit_excluded = kwargs[2]; + + if (sort != Qundef) + notmuch_query_set_sort (query, FIX2UINT (sort)); + + if (exclude_tags != Qundef) { + for (int i = 0; i < RARRAY_LEN (exclude_tags); i++) { + VALUE e = RARRAY_AREF (exclude_tags, i); + notmuch_query_add_tag_exclude (query, RSTRING_PTR (e)); + } + } + + if (omit_excluded != Qundef) { + notmuch_exclude_t omit; + omit = FIXNUM_P (omit_excluded) ? FIX2UINT (omit_excluded) : RTEST(omit_excluded); + notmuch_query_set_omit_excluded (query, omit); + } +} + return Data_Wrap_Struct (notmuch_rb_cQuery, NULL, NULL, query); } diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index 48544ca2..1ceaadb5 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -181,7 +181,7 @@ VALUE notmuch_rb_database_get_all_tags (VALUE self); VALUE -notmuch_rb_database_query_create (VALUE self, VALUE qstrv); +notmuch_rb_database_query_create (int argc, VALUE *argv, VALUE self); /* directory.c */ VALUE diff --git a/bindings/ruby/init.c b/bindings/ruby/init.c index fd73ed8f..f509edbd 100644 --- a/bindings/ruby/init.c +++ b/bindings/ruby/init.c @@ -254,7 +254,7 @@ Init_notmuch (void) rb_define_method (notmuch_rb_cDatabase, "find_message_by_filename", notmuch_rb_database_find_message_by_filename, 1); /* in database.c */ rb_define_method (notmuch_rb_cDatabase, "all_tags", notmuch_rb_database_get_all_tags, 0); /* in database.c */ -rb_define_method (notmuch_rb_cDatabase, "query", notmuch_rb_database_query_create, 1); /* in database.c */ +rb_define_method (notmuch_rb_cDatabase, "query", notmuch_rb_database_query_create, -1); /* in database.c */ /* * Document-class: Notmuch::Directory diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index d36d4aff..e828efed 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -82,4 +82,22 @@ q.search_threads.each do |t| end EOF +test_begin_subtest "check sort argument" +notmuch search --sort=oldest-first --output=threads tag:inbox > EXPECTED +test_ruby <<"EOF" +q = db.query('tag:inbox', sort: Notmuch::SORT_OLDEST_FIRST) +q.search_threads.each do |t| + puts 'thread:%s' % t.thread_id +end +EOF + +test_begin_subtest "check exclude_tags argument" +notmuch search --output=threads --exclude=all tag:inbox > EXPECTED +test_ruby <<"EOF" +q = db.query('tag:inbox', exclude_tags: %w[deleted], omit_excluded: Notmuch::EXCLUDE_ALL) +q.search_threads.each do |t| + puts 'thread:%s' % t.thread_id +end +EOF + test_done -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH] Vim: Fix a deprecated call to the 'mail' gem
On Sun, May 2, 2021 at 5:43 AM David Bremner wrote: > > Jules Aguillon writes: > > > The Field.new function from the 'mail' gem changed recently (since > > 2.7.0, Nov 2017) and now prints a message on stdout: > > > >> Passing an unparsed header field to Mail::Field.new is deprecated and will > >> be removed in Mail 2.8.0. Use Mail::Field.parse instead. > > I believe this problem was fixed in a different way by Felipe's patch > applied as 8af4cd16 Indeed, but Jules' patch may be a better solution, I will investigate. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH 5/9] test: ruby: simplify test_ruby()
On Sun, May 2, 2021 at 6:02 AM David Bremner wrote: > > Felipe Contreras writes: > > > We always do test_expect_equal_file, so do it in test_ruby() directly. > > > > The only subtest where we don't (get non-existent file) can be easily > > modified. > > I'm slightly hesitent since every other test ends with test_expect_*. > OTOH it is self contained within this one file so I guess I can live > with this change. The test could be named test_ruby_expect and be passed the EXPECTED file, or something. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 2/3] ruby: improve general data get helper
There's no need to do Check_Type, Data_Get_Struct calls rb_data_object_get(), which already does that. Signed-off-by: Felipe Contreras --- bindings/ruby/defs.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index e95ea239..46e2caf8 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -57,10 +57,9 @@ extern ID ID_db_mode; #define Data_Get_Notmuch_Object(obj, type, message, ptr) \ do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, (message)); \ Data_Get_Struct ((obj), type, (ptr)); \ + if (!(ptr)) \ + rb_raise (rb_eRuntimeError, (message)); \ } while (0) #define Data_Get_Notmuch_Database(obj, ptr) \ -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 0/3] ruby: cleanups
This are simple cleanups that should not have any functional changes. Felipe Contreras (3): ruby: improve all Data_Get_Notmuch_* helpers ruby: improve general data get helper ruby: simplify data get helper bindings/ruby/defs.h | 84 1 file changed, 23 insertions(+), 61 deletions(-) -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 1/3] ruby: improve all Data_Get_Notmuch_* helpers
There's no need to repeat the same code over and over. Signed-off-by: Felipe Contreras --- bindings/ruby/defs.h | 81 1 file changed, 22 insertions(+), 59 deletions(-) diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index 48544ca2..e95ea239 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -55,77 +55,40 @@ extern ID ID_db_mode; # define RSTRING_PTR(v) (RSTRING((v))->ptr) #endif /* !defined (RSTRING_PTR) */ -#define Data_Get_Notmuch_Database(obj, ptr)\ +#define Data_Get_Notmuch_Object(obj, type, message, ptr) \ do { \ Check_Type ((obj), T_DATA); \ if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "database closed"); \ - Data_Get_Struct ((obj), notmuch_database_t, (ptr)); \ + rb_raise (rb_eRuntimeError, (message)); \ + Data_Get_Struct ((obj), type, (ptr)); \ } while (0) -#define Data_Get_Notmuch_Directory(obj, ptr) \ -do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "directory destroyed"); \ - Data_Get_Struct ((obj), notmuch_directory_t, (ptr));\ -} while (0) +#define Data_Get_Notmuch_Database(obj, ptr) \ +Data_Get_Notmuch_Object ((obj), notmuch_database_t, "database closed", (ptr)) -#define Data_Get_Notmuch_FileNames(obj, ptr) \ -do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "filenames destroyed"); \ - Data_Get_Struct ((obj), notmuch_filenames_t, (ptr));\ -} while (0) +#define Data_Get_Notmuch_Directory(obj, ptr) \ +Data_Get_Notmuch_Object ((obj), notmuch_directory_t, "directory destroyed", (ptr)) -#define Data_Get_Notmuch_Query(obj, ptr) \ -do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "query destroyed"); \ - Data_Get_Struct ((obj), notmuch_query_t, (ptr));\ -} while (0) +#define Data_Get_Notmuch_FileNames(obj, ptr) \ +Data_Get_Notmuch_Object ((obj), notmuch_filenames_t, "filenames destroyed", (ptr)) -#define Data_Get_Notmuch_Threads(obj, ptr) \ -do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "threads destroyed"); \ - Data_Get_Struct ((obj), notmuch_threads_t, (ptr)); \ -} while (0) +#define Data_Get_Notmuch_Query(obj, ptr) \ +Data_Get_Notmuch_Object ((obj), notmuch_query_t, "query destroyed", (ptr)) -#define Data_Get_Notmuch_Messages(obj, ptr)\ -do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "messages destroyed"); \ - Data_Get_Struct ((obj), notmuch_messages_t, (ptr)); \ -} while (0) +#define Data_Get_Notmuch_Threads(obj, ptr) \ +Data_Get_Notmuch_Object ((obj), notmuch_threads_t, "threads destroyed", (ptr)) -#define Data_Get_Notmuch_Thread(obj, ptr) \ -do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "thread destroyed");\ - Data_Get_Struct ((obj), notmuch_thread_t, (ptr)); \ -} while (0) +#define Data_Get_Notmuch_Messages(obj, ptr) \ +Data_Get_Notmuch_Object ((obj), notmuch_messages_t, "messages destroyed", (ptr)) -#define Data_Get_Notmuch_Message(obj, ptr) \ -do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "message destroyed"); \ - Data_Get_Struct ((obj), notmuch_message_t, (ptr)); \ -} while (0) +#define Data_Get_Not
[PATCH 3/3] ruby: simplify data get helper
The type is not actually needed. Signed-off-by: Felipe Contreras --- bindings/ruby/defs.h | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index 46e2caf8..edbcc729 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -55,39 +55,39 @@ extern ID ID_db_mode; # define RSTRING_PTR(v) (RSTRING((v))->ptr) #endif /* !defined (RSTRING_PTR) */ -#define Data_Get_Notmuch_Object(obj, type, message, ptr) \ +#define Data_Get_Notmuch_Object(obj, message, ptr) \ do { \ - Data_Get_Struct ((obj), type, (ptr)); \ + (ptr) = rb_data_object_get (obj); \ if (!(ptr)) \ rb_raise (rb_eRuntimeError, (message)); \ } while (0) #define Data_Get_Notmuch_Database(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_database_t, "database closed", (ptr)) +Data_Get_Notmuch_Object ((obj), "database closed", (ptr)) #define Data_Get_Notmuch_Directory(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_directory_t, "directory destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "directory destroyed", (ptr)) #define Data_Get_Notmuch_FileNames(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_filenames_t, "filenames destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "filenames destroyed", (ptr)) #define Data_Get_Notmuch_Query(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_query_t, "query destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "query destroyed", (ptr)) #define Data_Get_Notmuch_Threads(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_threads_t, "threads destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "threads destroyed", (ptr)) #define Data_Get_Notmuch_Messages(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_messages_t, "messages destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "messages destroyed", (ptr)) #define Data_Get_Notmuch_Thread(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_thread_t, "thread destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "thread destroyed", (ptr)) #define Data_Get_Notmuch_Message(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_message_t, "message destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "message destroyed", (ptr)) #define Data_Get_Notmuch_Tags(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_tags_t, "tags destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "tags destroyed", (ptr)) /* status.c */ void -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH v2 00/10] ruby: object cleanups
This superseeds my previous series [1] with much more cleanups. An important new change is the move towards RTypedData, which is way superior to the old RData objects. Everything should work basically the same though. [1] id: 20210503075457.649056-1-felipe.contre...@gmail.com Felipe Contreras (10): ruby: add missing Data_Get_Notmuch helpers ruby: improve all Data_Get_Notmuch_* helpers ruby: improve general data get helper ruby: simplify data get helper ruby: fetch class name in case of error ruby: add unlikely hint ruby: create Data_Wrap_Notmuch_Object helper ruby: move towards more modern RTypedData ruby: add all data types ruby: new notmuch_rb_object_destroy() helper bindings/ruby/database.c | 22 +++- bindings/ruby/defs.h | 116 ++ bindings/ruby/directory.c | 11 +--- bindings/ruby/filenames.c | 7 +-- bindings/ruby/init.c | 21 +++ bindings/ruby/message.c | 13 ++--- bindings/ruby/messages.c | 11 +--- bindings/ruby/query.c | 11 +--- bindings/ruby/tags.c | 7 +-- bindings/ruby/thread.c| 13 ++--- bindings/ruby/threads.c | 9 +-- 11 files changed, 105 insertions(+), 136 deletions(-) Range-diff against v1: -: > 1: 9c15fc44 ruby: add missing Data_Get_Notmuch helpers 1: 6d121221 = 2: c9d840d3 ruby: improve all Data_Get_Notmuch_* helpers 2: 1f19091c = 3: 299b2be1 ruby: improve general data get helper 3: b5c84295 ! 4: 19fa26de ruby: simplify data get helper @@ bindings/ruby/defs.h: extern ID ID_db_mode; +#define Data_Get_Notmuch_Object(obj, message, ptr)\ do { \ - Data_Get_Struct ((obj), type, (ptr)); \ -+ (ptr) = rb_data_object_get (obj); \ ++ (ptr) = rb_data_object_get ((obj)); \ if (!(ptr)) \ rb_raise (rb_eRuntimeError, (message)); \ } while (0) -: > 5: 1872c4b5 ruby: fetch class name in case of error -: > 6: b46bcac8 ruby: add unlikely hint -: > 7: 1bfa0334 ruby: create Data_Wrap_Notmuch_Object helper -: > 8: a9b7ac45 ruby: move towards more modern RTypedData -: > 9: e2116d5d ruby: add all data types -: > 10: f6660e5b ruby: new notmuch_rb_object_destroy() helper -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH v2 01/10] ruby: add missing Data_Get_Notmuch helpers
Apparently commit 5c9e3855 (ruby: Don't barf if an object is destroyed more than once, 2010-05-26) missed these two. Signed-off-by: Felipe Contreras --- bindings/ruby/directory.c | 2 +- bindings/ruby/threads.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/ruby/directory.c b/bindings/ruby/directory.c index 0f37b391..fe5fc46d 100644 --- a/bindings/ruby/directory.c +++ b/bindings/ruby/directory.c @@ -30,7 +30,7 @@ notmuch_rb_directory_destroy (VALUE self) { notmuch_directory_t *dir; -Data_Get_Struct (self, notmuch_directory_t, dir); +Data_Get_Notmuch_Directory (self, dir); notmuch_directory_destroy (dir); DATA_PTR (self) = NULL; diff --git a/bindings/ruby/threads.c b/bindings/ruby/threads.c index ed403a8f..5885f565 100644 --- a/bindings/ruby/threads.c +++ b/bindings/ruby/threads.c @@ -30,7 +30,7 @@ notmuch_rb_threads_destroy (VALUE self) { notmuch_threads_t *threads; -Data_Get_Struct (self, notmuch_threads_t, threads); +Data_Get_Notmuch_Threads (self, threads); notmuch_threads_destroy (threads); DATA_PTR (self) = NULL; -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH v2 02/10] ruby: improve all Data_Get_Notmuch_* helpers
There's no need to repeat the same code over and over. Signed-off-by: Felipe Contreras --- bindings/ruby/defs.h | 81 1 file changed, 22 insertions(+), 59 deletions(-) diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index 48544ca2..e95ea239 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -55,77 +55,40 @@ extern ID ID_db_mode; # define RSTRING_PTR(v) (RSTRING((v))->ptr) #endif /* !defined (RSTRING_PTR) */ -#define Data_Get_Notmuch_Database(obj, ptr)\ +#define Data_Get_Notmuch_Object(obj, type, message, ptr) \ do { \ Check_Type ((obj), T_DATA); \ if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "database closed"); \ - Data_Get_Struct ((obj), notmuch_database_t, (ptr)); \ + rb_raise (rb_eRuntimeError, (message)); \ + Data_Get_Struct ((obj), type, (ptr)); \ } while (0) -#define Data_Get_Notmuch_Directory(obj, ptr) \ -do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "directory destroyed"); \ - Data_Get_Struct ((obj), notmuch_directory_t, (ptr));\ -} while (0) +#define Data_Get_Notmuch_Database(obj, ptr) \ +Data_Get_Notmuch_Object ((obj), notmuch_database_t, "database closed", (ptr)) -#define Data_Get_Notmuch_FileNames(obj, ptr) \ -do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "filenames destroyed"); \ - Data_Get_Struct ((obj), notmuch_filenames_t, (ptr));\ -} while (0) +#define Data_Get_Notmuch_Directory(obj, ptr) \ +Data_Get_Notmuch_Object ((obj), notmuch_directory_t, "directory destroyed", (ptr)) -#define Data_Get_Notmuch_Query(obj, ptr) \ -do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "query destroyed"); \ - Data_Get_Struct ((obj), notmuch_query_t, (ptr));\ -} while (0) +#define Data_Get_Notmuch_FileNames(obj, ptr) \ +Data_Get_Notmuch_Object ((obj), notmuch_filenames_t, "filenames destroyed", (ptr)) -#define Data_Get_Notmuch_Threads(obj, ptr) \ -do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "threads destroyed"); \ - Data_Get_Struct ((obj), notmuch_threads_t, (ptr)); \ -} while (0) +#define Data_Get_Notmuch_Query(obj, ptr) \ +Data_Get_Notmuch_Object ((obj), notmuch_query_t, "query destroyed", (ptr)) -#define Data_Get_Notmuch_Messages(obj, ptr)\ -do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "messages destroyed"); \ - Data_Get_Struct ((obj), notmuch_messages_t, (ptr)); \ -} while (0) +#define Data_Get_Notmuch_Threads(obj, ptr) \ +Data_Get_Notmuch_Object ((obj), notmuch_threads_t, "threads destroyed", (ptr)) -#define Data_Get_Notmuch_Thread(obj, ptr) \ -do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "thread destroyed");\ - Data_Get_Struct ((obj), notmuch_thread_t, (ptr)); \ -} while (0) +#define Data_Get_Notmuch_Messages(obj, ptr) \ +Data_Get_Notmuch_Object ((obj), notmuch_messages_t, "messages destroyed", (ptr)) -#define Data_Get_Notmuch_Message(obj, ptr) \ -do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "message destroyed"); \ - Data_Get_Struct ((obj), notmuch_message_t, (ptr)); \ -} while (0) +#define Data_Get_Not
[PATCH v2 03/10] ruby: improve general data get helper
There's no need to do Check_Type, Data_Get_Struct calls rb_data_object_get(), which already does that. Signed-off-by: Felipe Contreras --- bindings/ruby/defs.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index e95ea239..46e2caf8 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -57,10 +57,9 @@ extern ID ID_db_mode; #define Data_Get_Notmuch_Object(obj, type, message, ptr) \ do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, (message)); \ Data_Get_Struct ((obj), type, (ptr)); \ + if (!(ptr)) \ + rb_raise (rb_eRuntimeError, (message)); \ } while (0) #define Data_Get_Notmuch_Database(obj, ptr) \ -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH v2 04/10] ruby: simplify data get helper
The type is not actually needed. Signed-off-by: Felipe Contreras --- bindings/ruby/defs.h | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index 46e2caf8..8fb47b4c 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -55,39 +55,39 @@ extern ID ID_db_mode; # define RSTRING_PTR(v) (RSTRING((v))->ptr) #endif /* !defined (RSTRING_PTR) */ -#define Data_Get_Notmuch_Object(obj, type, message, ptr) \ +#define Data_Get_Notmuch_Object(obj, message, ptr) \ do { \ - Data_Get_Struct ((obj), type, (ptr)); \ + (ptr) = rb_data_object_get ((obj)); \ if (!(ptr)) \ rb_raise (rb_eRuntimeError, (message)); \ } while (0) #define Data_Get_Notmuch_Database(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_database_t, "database closed", (ptr)) +Data_Get_Notmuch_Object ((obj), "database closed", (ptr)) #define Data_Get_Notmuch_Directory(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_directory_t, "directory destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "directory destroyed", (ptr)) #define Data_Get_Notmuch_FileNames(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_filenames_t, "filenames destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "filenames destroyed", (ptr)) #define Data_Get_Notmuch_Query(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_query_t, "query destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "query destroyed", (ptr)) #define Data_Get_Notmuch_Threads(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_threads_t, "threads destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "threads destroyed", (ptr)) #define Data_Get_Notmuch_Messages(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_messages_t, "messages destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "messages destroyed", (ptr)) #define Data_Get_Notmuch_Thread(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_thread_t, "thread destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "thread destroyed", (ptr)) #define Data_Get_Notmuch_Message(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_message_t, "message destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "message destroyed", (ptr)) #define Data_Get_Notmuch_Tags(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), notmuch_tags_t, "tags destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), "tags destroyed", (ptr)) /* status.c */ void -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH v2 05/10] ruby: fetch class name in case of error
There is not much point in complicating the code for error messages that can be easily constructed. Before: database closed (RuntimeError) After: Notmuch::Database object destroyed (RuntimeError) Signed-off-by: Felipe Contreras --- bindings/ruby/defs.h | 30 -- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index 8fb47b4c..ae3ea101 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -55,39 +55,41 @@ extern ID ID_db_mode; # define RSTRING_PTR(v) (RSTRING((v))->ptr) #endif /* !defined (RSTRING_PTR) */ -#define Data_Get_Notmuch_Object(obj, message, ptr) \ -do { \ - (ptr) = rb_data_object_get ((obj)); \ - if (!(ptr)) \ - rb_raise (rb_eRuntimeError, (message)); \ +#define Data_Get_Notmuch_Object(obj, ptr) \ +do { \ + (ptr) = rb_data_object_get ((obj)); \ + if (!(ptr)) { \ + VALUE cname = rb_class_name (CLASS_OF ((obj))); \ + rb_raise (rb_eRuntimeError, "%"PRIsVALUE" object destroyed", cname);\ + } \ } while (0) #define Data_Get_Notmuch_Database(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), "database closed", (ptr)) +Data_Get_Notmuch_Object ((obj), (ptr)) #define Data_Get_Notmuch_Directory(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), "directory destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), (ptr)) #define Data_Get_Notmuch_FileNames(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), "filenames destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), (ptr)) #define Data_Get_Notmuch_Query(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), "query destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), (ptr)) #define Data_Get_Notmuch_Threads(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), "threads destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), (ptr)) #define Data_Get_Notmuch_Messages(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), "messages destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), (ptr)) #define Data_Get_Notmuch_Thread(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), "thread destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), (ptr)) #define Data_Get_Notmuch_Message(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), "message destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), (ptr)) #define Data_Get_Notmuch_Tags(obj, ptr) \ -Data_Get_Notmuch_Object ((obj), "tags destroyed", (ptr)) +Data_Get_Notmuch_Object ((obj), (ptr)) /* status.c */ void -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH v2 06/10] ruby: add unlikely hint
The error path is very unlikely. Signed-off-by: Felipe Contreras --- bindings/ruby/defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index ae3ea101..12538a3a 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -58,7 +58,7 @@ extern ID ID_db_mode; #define Data_Get_Notmuch_Object(obj, ptr) \ do { \ (ptr) = rb_data_object_get ((obj)); \ - if (!(ptr)) { \ + if (RB_UNLIKELY (!(ptr))) { \ VALUE cname = rb_class_name (CLASS_OF ((obj))); \ rb_raise (rb_eRuntimeError, "%"PRIsVALUE" object destroyed", cname);\ } \ -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH v2 07/10] ruby: create Data_Wrap_Notmuch_Object helper
This makes the code more maintainable and will help in further patches. No functional changes. Signed-off-by: Felipe Contreras --- bindings/ruby/database.c | 14 +++--- bindings/ruby/defs.h | 3 +++ bindings/ruby/directory.c | 4 ++-- bindings/ruby/message.c | 6 +++--- bindings/ruby/messages.c | 4 ++-- bindings/ruby/query.c | 4 ++-- bindings/ruby/thread.c| 6 +++--- bindings/ruby/threads.c | 2 +- 8 files changed, 23 insertions(+), 20 deletions(-) diff --git a/bindings/ruby/database.c b/bindings/ruby/database.c index 416eb709..b9ad3373 100644 --- a/bindings/ruby/database.c +++ b/bindings/ruby/database.c @@ -23,7 +23,7 @@ VALUE notmuch_rb_database_alloc (VALUE klass) { -return Data_Wrap_Struct (klass, NULL, NULL, NULL); +return Data_Wrap_Notmuch_Object (klass, NULL); } /* @@ -266,7 +266,7 @@ notmuch_rb_database_get_directory (VALUE self, VALUE pathv) ret = notmuch_database_get_directory (db, path, &dir); notmuch_rb_status_raise (ret); if (dir) - return Data_Wrap_Struct (notmuch_rb_cDirectory, NULL, NULL, dir); + return Data_Wrap_Notmuch_Object (notmuch_rb_cDirectory, dir); return Qnil; } @@ -293,7 +293,7 @@ notmuch_rb_database_add_message (VALUE self, VALUE pathv) ret = notmuch_database_index_file (db, path, NULL, &message); notmuch_rb_status_raise (ret); -return rb_assoc_new (Data_Wrap_Struct (notmuch_rb_cMessage, NULL, NULL, message), +return rb_assoc_new (Data_Wrap_Notmuch_Object (notmuch_rb_cMessage, message), (ret == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) ? Qtrue : Qfalse); } @@ -344,7 +344,7 @@ notmuch_rb_database_find_message (VALUE self, VALUE idv) notmuch_rb_status_raise (ret); if (message) -return Data_Wrap_Struct (notmuch_rb_cMessage, NULL, NULL, message); +return Data_Wrap_Notmuch_Object (notmuch_rb_cMessage, message); return Qnil; } @@ -370,7 +370,7 @@ notmuch_rb_database_find_message_by_filename (VALUE self, VALUE pathv) notmuch_rb_status_raise (ret); if (message) -return Data_Wrap_Struct (notmuch_rb_cMessage, NULL, NULL, message); +return Data_Wrap_Notmuch_Object (notmuch_rb_cMessage, message); return Qnil; } @@ -395,7 +395,7 @@ notmuch_rb_database_get_all_tags (VALUE self) rb_raise (notmuch_rb_eBaseError, "%s", msg); } -return Data_Wrap_Struct (notmuch_rb_cTags, NULL, NULL, tags); +return Data_Wrap_Notmuch_Object (notmuch_rb_cTags, tags); } /* @@ -419,5 +419,5 @@ notmuch_rb_database_query_create (VALUE self, VALUE qstrv) if (!query) rb_raise (notmuch_rb_eMemoryError, "Out of memory"); -return Data_Wrap_Struct (notmuch_rb_cQuery, NULL, NULL, query); +return Data_Wrap_Notmuch_Object (notmuch_rb_cQuery, query); } diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index 12538a3a..fcf1ea39 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -64,6 +64,9 @@ extern ID ID_db_mode; } \ } while (0) +#define Data_Wrap_Notmuch_Object(klass, ptr) \ +Data_Wrap_Struct ((klass), NULL, NULL, (ptr)) + #define Data_Get_Notmuch_Database(obj, ptr) \ Data_Get_Notmuch_Object ((obj), (ptr)) diff --git a/bindings/ruby/directory.c b/bindings/ruby/directory.c index fe5fc46d..36ef3984 100644 --- a/bindings/ruby/directory.c +++ b/bindings/ruby/directory.c @@ -92,7 +92,7 @@ notmuch_rb_directory_get_child_files (VALUE self) fnames = notmuch_directory_get_child_files (dir); -return Data_Wrap_Struct (notmuch_rb_cFileNames, NULL, NULL, fnames); +return Data_Wrap_Notmuch_Object (notmuch_rb_cFileNames, fnames); } /* @@ -111,5 +111,5 @@ notmuch_rb_directory_get_child_directories (VALUE self) fnames = notmuch_directory_get_child_directories (dir); -return Data_Wrap_Struct (notmuch_rb_cFileNames, NULL, NULL, fnames); +return Data_Wrap_Notmuch_Object (notmuch_rb_cFileNames, fnames); } diff --git a/bindings/ruby/message.c b/bindings/ruby/message.c index 6ea82afa..1990bb97 100644 --- a/bindings/ruby/message.c +++ b/bindings/ruby/message.c @@ -89,7 +89,7 @@ notmuch_rb_message_get_replies (VALUE self) messages = notmuch_message_get_replies (message); -return Data_Wrap_Struct (notmuch_rb_cMessages, NULL, NULL, messages); +return Data_Wrap_Notmuch_Object (notmuch_rb_cMessages, messages); } /* @@ -125,7 +125,7 @@ notmuch_rb_message_get_filenames (VALUE self) fnames = notmuch_message_get_filenames (message); -return Data_Wrap_Struct (notmuch_rb_cFileNames, NULL, NULL, fnames); +return Data_Wrap_Notmuch_Object (notmuch_rb_cFileNames, fnames); } /* @@ -226,7 +226,7 @@ notmuch_rb_message_get_tags (VALUE self) if (!tags) rb_raise (notmuch_rb_eMemoryError, "Out of memory"); -return Data_Wrap_Struct (notmuch_rb_cTags, NULL, NULL, tags)
[PATCH v2 08/10] ruby: move towards more modern RTypedData
Signed-off-by: Felipe Contreras --- bindings/ruby/database.c | 2 +- bindings/ruby/defs.h | 6 -- bindings/ruby/init.c | 4 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bindings/ruby/database.c b/bindings/ruby/database.c index b9ad3373..bb4273e6 100644 --- a/bindings/ruby/database.c +++ b/bindings/ruby/database.c @@ -74,7 +74,7 @@ notmuch_rb_database_initialize (int argc, VALUE *argv, VALUE self) mode = NOTMUCH_DATABASE_MODE_READ_ONLY; } -Check_Type (self, T_DATA); +rb_check_typeddata (self, ¬much_rb_object_type); if (create) ret = notmuch_database_create (path, &database); else diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index fcf1ea39..6dbaa85d 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -55,9 +55,11 @@ extern ID ID_db_mode; # define RSTRING_PTR(v) (RSTRING((v))->ptr) #endif /* !defined (RSTRING_PTR) */ +extern const rb_data_type_t notmuch_rb_object_type; + #define Data_Get_Notmuch_Object(obj, ptr) \ do { \ - (ptr) = rb_data_object_get ((obj)); \ + (ptr) = rb_check_typeddata ((obj), ¬much_rb_object_type); \ if (RB_UNLIKELY (!(ptr))) { \ VALUE cname = rb_class_name (CLASS_OF ((obj))); \ rb_raise (rb_eRuntimeError, "%"PRIsVALUE" object destroyed", cname);\ @@ -65,7 +67,7 @@ extern ID ID_db_mode; } while (0) #define Data_Wrap_Notmuch_Object(klass, ptr) \ -Data_Wrap_Struct ((klass), NULL, NULL, (ptr)) +TypedData_Wrap_Struct ((klass), ¬much_rb_object_type, (ptr)) #define Data_Get_Notmuch_Database(obj, ptr) \ Data_Get_Notmuch_Object ((obj), (ptr)) diff --git a/bindings/ruby/init.c b/bindings/ruby/init.c index 819fd1e3..f3b2e5b1 100644 --- a/bindings/ruby/init.c +++ b/bindings/ruby/init.c @@ -46,6 +46,10 @@ ID ID_call; ID ID_db_create; ID ID_db_mode; +const rb_data_type_t notmuch_rb_object_type = { +.wrap_struct_name = "notmuch_object", +}; + /* * Document-module: Notmuch * -- 2.31.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH v2 09/10] ruby: add all data types
Signed-off-by: Felipe Contreras --- bindings/ruby/database.c | 16 bindings/ruby/defs.h | 37 +++-- bindings/ruby/directory.c | 4 ++-- bindings/ruby/init.c | 16 bindings/ruby/message.c | 6 +++--- bindings/ruby/messages.c | 4 ++-- bindings/ruby/query.c | 4 ++-- bindings/ruby/thread.c| 6 +++--- bindings/ruby/threads.c | 2 +- 9 files changed, 60 insertions(+), 35 deletions(-) diff --git a/bindings/ruby/database.c b/bindings/ruby/database.c index bb4273e6..4ecc8f78 100644 --- a/bindings/ruby/database.c +++ b/bindings/ruby/database.c @@ -23,7 +23,7 @@ VALUE notmuch_rb_database_alloc (VALUE klass) { -return Data_Wrap_Notmuch_Object (klass, NULL); +return Data_Wrap_Notmuch_Object (klass, ¬much_rb_database_type, NULL); } /* @@ -74,7 +74,7 @@ notmuch_rb_database_initialize (int argc, VALUE *argv, VALUE self) mode = NOTMUCH_DATABASE_MODE_READ_ONLY; } -rb_check_typeddata (self, ¬much_rb_object_type); +rb_check_typeddata (self, ¬much_rb_database_type); if (create) ret = notmuch_database_create (path, &database); else @@ -266,7 +266,7 @@ notmuch_rb_database_get_directory (VALUE self, VALUE pathv) ret = notmuch_database_get_directory (db, path, &dir); notmuch_rb_status_raise (ret); if (dir) - return Data_Wrap_Notmuch_Object (notmuch_rb_cDirectory, dir); + return Data_Wrap_Notmuch_Object (notmuch_rb_cDirectory, ¬much_rb_directory_type, dir); return Qnil; } @@ -293,7 +293,7 @@ notmuch_rb_database_add_message (VALUE self, VALUE pathv) ret = notmuch_database_index_file (db, path, NULL, &message); notmuch_rb_status_raise (ret); -return rb_assoc_new (Data_Wrap_Notmuch_Object (notmuch_rb_cMessage, message), +return rb_assoc_new (Data_Wrap_Notmuch_Object (notmuch_rb_cMessage, ¬much_rb_message_type, message), (ret == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) ? Qtrue : Qfalse); } @@ -344,7 +344,7 @@ notmuch_rb_database_find_message (VALUE self, VALUE idv) notmuch_rb_status_raise (ret); if (message) -return Data_Wrap_Notmuch_Object (notmuch_rb_cMessage, message); + return Data_Wrap_Notmuch_Object (notmuch_rb_cMessage, ¬much_rb_message_type, message); return Qnil; } @@ -370,7 +370,7 @@ notmuch_rb_database_find_message_by_filename (VALUE self, VALUE pathv) notmuch_rb_status_raise (ret); if (message) -return Data_Wrap_Notmuch_Object (notmuch_rb_cMessage, message); + return Data_Wrap_Notmuch_Object (notmuch_rb_cMessage, ¬much_rb_message_type, message); return Qnil; } @@ -395,7 +395,7 @@ notmuch_rb_database_get_all_tags (VALUE self) rb_raise (notmuch_rb_eBaseError, "%s", msg); } -return Data_Wrap_Notmuch_Object (notmuch_rb_cTags, tags); +return Data_Wrap_Notmuch_Object (notmuch_rb_cTags, ¬much_rb_tags_type, tags); } /* @@ -419,5 +419,5 @@ notmuch_rb_database_query_create (VALUE self, VALUE qstrv) if (!query) rb_raise (notmuch_rb_eMemoryError, "Out of memory"); -return Data_Wrap_Notmuch_Object (notmuch_rb_cQuery, query); +return Data_Wrap_Notmuch_Object (notmuch_rb_cQuery, ¬much_rb_query_type, query); } diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index 6dbaa85d..fa7b9515 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -56,45 +56,54 @@ extern ID ID_db_mode; #endif /* !defined (RSTRING_PTR) */ extern const rb_data_type_t notmuch_rb_object_type; - -#define Data_Get_Notmuch_Object(obj, ptr) \ +extern const rb_data_type_t notmuch_rb_database_type; +extern const rb_data_type_t notmuch_rb_directory_type; +extern const rb_data_type_t notmuch_rb_filenames_type; +extern const rb_data_type_t notmuch_rb_query_type; +extern const rb_data_type_t notmuch_rb_threads_type; +extern const rb_data_type_t notmuch_rb_thread_type; +extern const rb_data_type_t notmuch_rb_messages_type; +extern const rb_data_type_t notmuch_rb_message_type; +extern const rb_data_type_t notmuch_rb_tags_type; + +#define Data_Get_Notmuch_Object(obj, type, ptr) \ do { \ - (ptr) = rb_check_typeddata ((obj), ¬much_rb_object_type); \ + (ptr) = rb_check_typeddata ((obj), (type)); \ if (RB_UNLIKELY (!(ptr))) { \ VALUE cname = rb_class_name (CLASS_OF ((obj))); \ rb_raise (rb_eRuntimeError, "%"PRIsVALUE" object destroyed", cname);\ } \ } while (0) -#define Data_Wrap_Notmuch_Object(klass, ptr) \ -TypedData_Wrap_St
[PATCH v2 10/10] ruby: new notmuch_rb_object_destroy() helper
Using the rb_data_type_t data we can call the correct notmuch destroy function. Signed-off-by: Felipe Contreras --- bindings/ruby/database.c | 6 +- bindings/ruby/defs.h | 14 ++ bindings/ruby/directory.c | 7 +-- bindings/ruby/filenames.c | 7 +-- bindings/ruby/init.c | 1 + bindings/ruby/message.c | 7 +-- bindings/ruby/messages.c | 7 +-- bindings/ruby/query.c | 7 +-- bindings/ruby/tags.c | 7 +-- bindings/ruby/thread.c| 7 +-- bindings/ruby/threads.c | 7 +-- 11 files changed, 24 insertions(+), 53 deletions(-) diff --git a/bindings/ruby/database.c b/bindings/ruby/database.c index 4ecc8f78..bb993d86 100644 --- a/bindings/ruby/database.c +++ b/bindings/ruby/database.c @@ -114,11 +114,7 @@ VALUE notmuch_rb_database_close (VALUE self) { notmuch_status_t ret; -notmuch_database_t *db; - -Data_Get_Notmuch_Database (self, db); -ret = notmuch_database_destroy (db); -DATA_PTR (self) = NULL; +ret = notmuch_rb_object_destroy (self, ¬much_rb_database_type); notmuch_rb_status_raise (ret); return Qnil; diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index fa7b9515..66b476e2 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -105,6 +105,20 @@ extern const rb_data_type_t notmuch_rb_tags_type; #define Data_Get_Notmuch_Tags(obj, ptr) \ Data_Get_Notmuch_Object ((obj), ¬much_rb_tags_type, (ptr)) +static inline notmuch_status_t +notmuch_rb_object_destroy (VALUE rb_object, const rb_data_type_t *type) +{ +void *nm_object; +notmuch_status_t ret; + +Data_Get_Notmuch_Object (rb_object, type, nm_object); + +ret = ((notmuch_status_t (*)(void *)) type->data) (nm_object); +DATA_PTR (rb_object) = NULL; + +return ret; +} + /* status.c */ void notmuch_rb_status_raise (notmuch_status_t status); diff --git a/bindings/ruby/directory.c b/bindings/ruby/directory.c index 17d60d1d..910f0a99 100644 --- a/bindings/ruby/directory.c +++ b/bindings/ruby/directory.c @@ -28,12 +28,7 @@ VALUE notmuch_rb_directory_destroy (VALUE self) { -notmuch_directory_t *dir; - -Data_Get_Notmuch_Directory (self, dir); - -notmuch_directory_destroy (dir); -DATA_PTR (self) = NULL; +notmuch_rb_object_destroy (self, ¬much_rb_directory_type); return Qnil; } diff --git a/bindings/ruby/filenames.c b/bindings/ruby/filenames.c index 656c58e6..0dec1952 100644 --- a/bindings/ruby/filenames.c +++ b/bindings/ruby/filenames.c @@ -28,12 +28,7 @@ VALUE notmuch_rb_filenames_destroy (VALUE self) { -notmuch_filenames_t *fnames; - -Data_Get_Notmuch_FileNames (self, fnames); - -notmuch_filenames_destroy (fnames); -DATA_PTR (self) = NULL; +notmuch_rb_object_destroy (self, ¬much_rb_filenames_type); return Qnil; } diff --git a/bindings/ruby/init.c b/bindings/ruby/init.c index a9f863eb..62515eca 100644 --- a/bindings/ruby/init.c +++ b/bindings/ruby/init.c @@ -54,6 +54,7 @@ const rb_data_type_t notmuch_rb_object_type = { const rb_data_type_t notmuch_rb_ ## id ## _type = { \ .wrap_struct_name = "notmuch_" #id, \ .parent = ¬much_rb_object_type, \ + .data = ¬much_ ## id ## _destroy, \ } define_type (database); diff --git a/bindings/ruby/message.c b/bindings/ruby/message.c index b3aed604..f45c95cc 100644 --- a/bindings/ruby/message.c +++ b/bindings/ruby/message.c @@ -28,12 +28,7 @@ VALUE notmuch_rb_message_destroy (VALUE self) { -notmuch_message_t *message; - -Data_Get_Notmuch_Message (self, message); - -notmuch_message_destroy (message); -DATA_PTR (self) = NULL; +notmuch_rb_object_destroy (self, ¬much_rb_message_type); return Qnil; } diff --git a/bindings/ruby/messages.c b/bindings/ruby/messages.c index e04f3af1..ca5b10d0 100644 --- a/bindings/ruby/messages.c +++ b/bindings/ruby/messages.c @@ -28,12 +28,7 @@ VALUE notmuch_rb_messages_destroy (VALUE self) { -notmuch_messages_t *messages; - -Data_Get_Notmuch_Messages (self, messages); - -notmuch_messages_destroy (messages); -DATA_PTR (self) = NULL; +notmuch_rb_object_destroy (self, ¬much_rb_messages_type); return Qnil; } diff --git a/bindings/ruby/query.c b/bindings/ruby/query.c index 79727d6a..3ec98c6c 100644 --- a/bindings/ruby/query.c +++ b/bindings/ruby/query.c @@ -28,12 +28,7 @@ VALUE notmuch_rb_query_destroy (VALUE self) { -notmuch_query_t *query; - -Data_Get_Notmuch_Query (self, query); - -notmuch_query_destroy (query); -DATA_PTR (self) = NULL; +notmuch_rb_object_destroy (self, ¬much_rb_query_type); return Qnil; } diff --git a/bindings/ruby/tags.c b/bindings/ruby/tags.c index db8b4cfc..2af85e36 100644 --- a/bindings/ruby/tags.c +++ b/bindings/ruby/tags.c @@ -28,12 +28,7 @@ VALUE notmuch_rb_tags_destroy (VALUE self) { -notmuch_tags_t *tags; - -Data_Get_Notmuch_Tags (self, tags); - -notmuch_tags_destroy (tags); -DATA_PTR
Re: [PATCH v2 00/10] ruby: object cleanups
On Tue, May 4, 2021 at 3:17 AM Felipe Contreras wrote: > > This superseeds my previous series [1] with much more cleanups. > > An important new change is the move towards RTypedData, which is way superior > to the old RData > objects. > > Everything should work basically the same though. Please remove Austin Clements from the CC list, his address doesn't work anymore. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: The future of Ruby bindings
On Fri, Apr 30, 2021 at 5:14 PM Felipe Contreras wrote: > I understand why Ali Polatel did commit c7893408 (ruby: Kill garbage > collection related cruft., 2010-05-26); because the order of the object > destruction cannot be ensured in Ruby, however, there's ways to > workaround that. > > 1. We can steal the object > 2. We can increase the reference count > 3. We can add a second parent I attempted all options, and none of these worked in practice, except #1. I have the patches ready, but first they need the cleanups in [1]. Any feedback would be appreciated. Cheers. [1] id:20210504081749.715768-1-felipe.contre...@gmail.com -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: nmbug update
On Fri, Apr 23, 2021 at 8:21 PM David Bremner wrote: > Currently nmweb is not a good source of patches (it needs a "raw > download" link for a message, or perhaps a "download as mbox" link for a > thread). If you're interested in working on that (and like Django) then > let me know and I can provide you with a copy of the current source. Would you consider moving to a different web framework? If so, I could take a bite creating such a site, except probably with a Ruby framework. Cheers. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: Is there a reason why the trashed flag is not synced?
On Sun, May 9, 2021 at 4:38 AM David Bremner wrote: > Felipe Contreras writes: > > I understand deleting files is complex, but what's wrong with simply > > tagging the T (trashed) messages as 'deleted'? > > > > I'm using synchronize_flags=true. > > The current lack of synchronization is intentional, with the reasoning > explained in the commit message of [1]. I don't know if a one way sync > (only from T -> deleted) has been discussed. > https://git.notmuchmail.org/git/notmuch/commit/2c262042ac174d7bc96d6035ab9c88bd0abe7f35 This rationale makes sense to me, and I agree with the conclusion that such behavior "can be potentially dangerous". But the fact that something is potentially dangerous doesn't mean that it necessarily is. It makes sense that by default synchronize_flags=true doesn't sync the trash flag, but what's wrong with a new configuration synchronize_flags=all that does? That way it's the responsibility of the user to ensure that such potentially dangerous behavior can't happen before doing synchronize_flags=all. Cheers. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: Is there a reason why the trashed flag is not synced?
On Wed, May 12, 2021 at 3:37 AM Michael J Gruber wrote: > But really, if you use folders as a tag substitute you should think > about moving files to a trash folder rather than marking them trashed, > in which case we don't have to worry about "T". (Notmuch's lack of > T-syncing made me do this and it works fine.) In my case trashed doesn't mean deleted, it means it's no longer reachable from any of the directories I'm synchronizing. Right now I'm only tracking a single label. If I remove that label from the message in Gmail, that would translate as a trashed flag in IMAP. I'm not actually deleting anything, I just don't want to see those messages in my notmuch client (thanks to excluded_tags). -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH v2 04/10] ruby: simplify data get helper
On Wed, May 12, 2021 at 4:59 PM David Bremner wrote: > > Felipe Contreras writes: > > > The type is not actually needed. > > > > Signed-off-by: Felipe Contreras > > --- > > bindings/ruby/defs.h | 22 +++--- > > 1 file changed, 11 insertions(+), 11 deletions(-) > > > > diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h > > index 46e2caf8..8fb47b4c 100644 > > --- a/bindings/ruby/defs.h > > +++ b/bindings/ruby/defs.h > > @@ -55,39 +55,39 @@ extern ID ID_db_mode; > > # define RSTRING_PTR(v) (RSTRING((v))->ptr) > > #endif /* !defined (RSTRING_PTR) */ > > > > -#define Data_Get_Notmuch_Object(obj, type, message, ptr) \ > > +#define Data_Get_Notmuch_Object(obj, message, ptr) \ > > do { \ > > - Data_Get_Struct ((obj), type, (ptr)); \ > > + (ptr) = rb_data_object_get ((obj)); \ > > Please explain a bit more in the commit message what's going on > here. Why is it OK to replace Data_Get_Struct with rb_data_object_get? Data_Get_Struct is nothing but a macro that calls rb_data_object_get with a cast (unnecessary in C). #define Data_Get_Struct(obj, type, sval) \ ((sval) = RBIMPL_CAST((type*)rb_data_object_get(obj))) Is that explanation sufficient? -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH v2 08/10] ruby: move towards more modern RTypedData
On Wed, May 12, 2021 at 5:02 PM David Bremner wrote: > > Here I would also like a bit more back story in the commit message I'm not exactly sure what I need to explain here. RTypedData is the modern way objects are created. Data_Wrap_Struct is replaced with TypedData_Wrap_Struct, and the information is stored in a struct rb_data_type_t, rather than passed as arguments. Check_Type is replaced with Check_TypedStruct, which is a wrapper for rb_check_typeddata (with casts). -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH v2 10/10] ruby: new notmuch_rb_object_destroy() helper
On Wed, May 12, 2021 at 5:10 PM David Bremner wrote: > > Felipe Contreras writes: > > > +static inline notmuch_status_t > > +notmuch_rb_object_destroy (VALUE rb_object, const rb_data_type_t *type) > > +{ > > +void *nm_object; > > +notmuch_status_t ret; > > + > > +Data_Get_Notmuch_Object (rb_object, type, nm_object); > > + > > +ret = ((notmuch_status_t (*)(void *)) type->data) (nm_object); > > +DATA_PTR (rb_object) = NULL; > > + > > +return ret; > > +} > > + > > I see the benefit of making the code shorter, but I don't understand the > new code, while I did (mostly) understand the old code. So please > explain this in a comment as if I have no idea how ruby extensions work. The struct used to store the types (rb_data_type_t) contains a "data" field where we can store whatever we want. I use that field to store a pointer to the corresponding destroy function. For example notmuch_rb_database_type contains a pointer to notmuch_database_destroy. I cast that pointer as a notmuch_status_t (func*)(void *) and call that function passing the internal object (e.g. notmuch_database_t). Is that explanation good enough? Cheers. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH v2 2/6] test: more style fixes
In order to fit the git coding style. Signed-off-by: Felipe Contreras --- test/T140-excludes.sh | 3 +- test/T190-multipart.sh | 3 +- test/T490-parse-time-string.sh | 6 +-- test/export-dirs.sh| 3 +- test/test-lib-common.sh| 6 +-- test/test-lib.sh | 78 -- 6 files changed, 33 insertions(+), 66 deletions(-) diff --git a/test/T140-excludes.sh b/test/T140-excludes.sh index acab5381..352b3eb8 100755 --- a/test/T140-excludes.sh +++ b/test/T140-excludes.sh @@ -5,8 +5,7 @@ test_description='"notmuch search, count and show" with excludes in several vari # Generates a thread consisting of a top level message and 'length' # replies. The subject of the top message 'subject: top message" # and the subject of the nth reply in the thread is "subject: reply n" -generate_thread () -{ +generate_thread () { local subject="$1" local length="$2" generate_message '[subject]="'"${subject}: top message"'"' '[body]="'"body of top message"'"' diff --git a/test/T190-multipart.sh b/test/T190-multipart.sh index 6f715ff9..3545a599 100755 --- a/test/T190-multipart.sh +++ b/test/T190-multipart.sh @@ -725,8 +725,7 @@ EOF notmuch new > /dev/null -cat_expected_head () -{ +cat_expected_head () { cat < /dev/null } diff --git a/test/test-lib.sh b/test/test-lib.sh index 3147b782..c1395c87 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -120,8 +120,7 @@ test_require_emacs () { test_require_external_prereq dtach } -add_gnupg_home () -{ +add_gnupg_home () { [ -e "${GNUPGHOME}/gpg.conf" ] && return _gnupg_exit () { gpgconf --kill all 2>/dev/null || true; } at_exit_function _gnupg_exit @@ -141,8 +140,7 @@ add_gnupg_home () printf '%s:6:\n' "$FINGERPRINT" | gpg --quiet --batch --no-tty --import-ownertrust } -add_gpgsm_home () -{ +add_gpgsm_home () { local fpr [ -e "$GNUPGHOME/gpgsm.conf" ] && return _gnupg_exit () { gpgconf --kill all 2>/dev/null || true; } @@ -274,8 +272,7 @@ then fi test_description_printed= -print_test_description () -{ +print_test_description () { test -z "$test_description_printed" || return 0 echo echo $this_test: "Testing ${test_description}" @@ -355,8 +352,7 @@ trap 'trap_signal' HUP INT TERM # Accepts arbitrary extra emacs/elisp functions to modify the message # before sending, which is useful to doing things like attaching files # to the message and encrypting/signing. -emacs_deliver_message () -{ +emacs_deliver_message () { local subject body smtp_dummy_pid smtp_dummy_port subject="$1" body="$2" @@ -402,8 +398,7 @@ emacs_deliver_message () # If any GNU-style long-arguments (like --quiet or --decrypt=true) are # at the head of the argument list, they are sent directly to "notmuch # new" after message delivery -emacs_fcc_message () -{ +emacs_fcc_message () { local nmn_args subject body nmn_args='' while [[ "$1" =~ ^-- ]]; do @@ -441,8 +436,7 @@ emacs_fcc_message () # history of the notmuch mailing list, which allows for reliably # testing commands that need to operate on a not-totally-trivial # number of messages. -add_email_corpus () -{ +add_email_corpus () { local corpus corpus=${1:-default} @@ -451,8 +445,7 @@ add_email_corpus () notmuch new >/dev/null || die "'notmuch new' failed while adding email corpus" } -test_begin_subtest () -{ +test_begin_subtest () { if [ -n "$inside_subtest" ]; then exec 1>&6 2>&7 # Restore stdout and stderr error "bug in test script: Missing test_expect_equal in ${BASH_SOURCE[1]}:${BASH_LINENO[0]}" @@ -472,8 +465,7 @@ test_begin_subtest () # not accept a test name. Instead, the caller should call # test_begin_subtest before calling this function in order to set the # name. -test_expect_equal () -{ +test_expect_equal () { local output expected testname exec 1>&6 2>&7 # Restore stdout and stderr if [ -z "$inside_subtest" ]; then @@ -499,8 +491,7 @@ test_expect_equal () } # Like test_expect_equal, but takes two filenames. -test_expect_equal_file () -{ +test_expect_equal_file () { local file1 file2 testname basename1 basename2 exec 1>&6 2>&7 # Restore stdout and stderr if [ -z "$inside_subtest" ]; then @@ -616,19 +607,16 @@ test_emacs_expect_t () { fi } -NOTMUCH_NEW () -{ +NOTMUCH_NEW () { notmuch new "${@}" | grep -v -E -e '^Processed [0-9]*( total)? file|Found [0-9]* total fil
[PATCH v2 0/6] test: several cleanups
Many cleanups from the last time I sent this series were not picked, I've rebased and reordered the patches so they have a better chance of being picked up. I only dropped the patch about USER_FULL_NAME, maybe there's a better way to do it, and this way the entire patch series is about cleanups. Felipe Contreras (6): test: trivial style cleanups test: more style fixes test: emacs: simplify missing dependencies check test: emacs: check for configured emacs test: emacs: fix a couple of shellcheck complaints test: split emacs functionality to its own file test/T000-basic.sh | 2 +- test/T070-insert.sh| 2 +- test/T140-excludes.sh | 3 +- test/T160-json.sh | 1 + test/T170-sexp.sh | 1 + test/T190-multipart.sh | 3 +- test/T310-emacs.sh | 1 + test/T320-emacs-large-search-buffer.sh | 3 + test/T330-emacs-subject-to-filename.sh | 3 + test/T350-crypto.sh| 1 + test/T355-smime.sh | 1 + test/T357-index-decryption.sh | 1 + test/T358-emacs-protected-headers.sh | 2 + test/T420-emacs-test-functions.sh | 1 + test/T430-emacs-address-cleaning.sh| 3 + test/T440-emacs-hello.sh | 2 + test/T450-emacs-show.sh| 1 + test/T455-emacs-charsets.sh| 3 + test/T460-emacs-tree.sh| 1 + test/T490-parse-time-string.sh | 6 +- test/T510-thread-replies.sh| 1 + test/T590-thread-breakage.sh | 10 +- test/T630-emacs-draft.sh | 2 + test/T720-emacs-attachment-warnings.sh | 3 + test/T730-emacs-forwarding.sh | 1 + test/export-dirs.sh| 3 +- test/test-lib-common.sh| 6 +- test/test-lib-emacs.sh | 209 +++ test/test-lib.sh | 275 +++-- 29 files changed, 281 insertions(+), 270 deletions(-) create mode 100644 test/test-lib-emacs.sh Range-diff against v1: 1: 9b173076 < -: test: fix passwd_sanitize() 2: c0352e17 < -: test: unset NAME environment variable 3: 5f0c0ee9 < -: test: remove USER_FULL_NAME when not present 4: 2f7df848 < -: test: use correct fqdn in passwd_sanitize() 5: 586acb92 < -: test: fix wrong SKIP messages 6: c6866fdb < -: test: add prereqs check in test_emacs_expect_t 7: 966bfe4f < -: test: add external prereqs to many emacs tests 12: 795cb59a ! 1: 0a66ef17 test: trivial style cleanups @@ test/test-lib.sh: test_must_fail () { $GIT_TEST_CMP "$@" } -@@ test/test-lib.sh: test_done () { - fi +@@ test/test-lib.sh: test_emacs () { + ${TEST_EMACSCLIENT} --socket-name="$EMACS_SERVER" --eval "(notmuch-test-progn $*)" } -test_python() { @@ test/test-lib.sh: test_done () { # Note: if there is need to print debug information from python program, # use stdout = os.fdopen(6, 'w') or stderr = os.fdopen(7, 'w') PYTHONPATH="$NOTMUCH_SRCDIR/bindings/python${PYTHONPATH:+:$PYTHONPATH}" \ - $NOTMUCH_PYTHON -B - > OUTPUT - } - --test_ruby() { -+test_ruby () { - MAIL_DIR=$MAIL_DIR $NOTMUCH_RUBY -I "$NOTMUCH_BUILDDIR/bindings/ruby"> OUTPUT - } - 13: c6235983 ! 2: a273e59e test: more style fixes @@ test/test-lib-common.sh: EOF notmuch new > /dev/null } - ## test/test-lib-emacs.sh ## -@@ test/test-lib-emacs.sh: test_require_emacs () { - # Accepts arbitrary extra emacs/elisp functions to modify the message - # before sending, which is useful to doing things like attaching files - # to the message and encrypting/signing. --emacs_deliver_message () --{ -+emacs_deliver_message () { - local subject body smtp_dummy_pid smtp_dummy_port - subject="$1" - body="$2" -@@ test/test-lib-emacs.sh: emacs_deliver_message () - # If any GNU-style long-arguments (like --quiet or --decrypt=true) are - # at the head of the argument list, they are sent directly to "notmuch - # new" after message delivery --emacs_fcc_message () --{ -+emacs_fcc_message () { - local nmn_args subject body - nmn_args='' - while [[ "$1" =~ ^-- ]]; do - ## test/test-lib.sh ## -@@ test/test-lib.sh: unset ALTERNATE_EDITOR - unset EMAIL - unset NAME +@@ test/test-lib.sh: test_require_emacs () { + test_require_external_prereq dtach + } -add_gnupg_home () -{ @@ test/test-lib.sh: then echo echo $this_test: "Testing ${te
[PATCH v2 1/6] test: trivial style cleanups
Signed-off-by: Felipe Contreras --- test/T000-basic.sh | 2 +- test/T070-insert.sh | 2 +- test/T590-thread-breakage.sh | 10 +- test/export-dirs.sh | 2 +- test/test-lib.sh | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/test/T000-basic.sh b/test/T000-basic.sh index 7fbdcfa3..a2f4d93f 100755 --- a/test/T000-basic.sh +++ b/test/T000-basic.sh @@ -33,7 +33,7 @@ test_begin_subtest 'failure to clean up causes the test to fail' test_expect_code 2 'test_when_finished "(exit 2)"' EXPECTED=$NOTMUCH_SRCDIR/test/test.expected-output -suppress_diff_date() { +suppress_diff_date () { sed -e 's/\(.*\-\-\- test-verbose\.4\.\expected\).*/\1/' \ -e 's/\(.*\+\+\+ test-verbose\.4\.\output\).*/\1/' } diff --git a/test/T070-insert.sh b/test/T070-insert.sh index b37a9b67..208deb1c 100755 --- a/test/T070-insert.sh +++ b/test/T070-insert.sh @@ -15,7 +15,7 @@ notmuch new > /dev/null # They happen to be in the mail directory already but that is okay # since we do not call notmuch new hereafter. -gen_insert_msg() { +gen_insert_msg () { generate_message \ "[subject]=\"insert-subject\"" \ "[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" \ diff --git a/test/T590-thread-breakage.sh b/test/T590-thread-breakage.sh index aeb82cf4..92a70e3e 100755 --- a/test/T590-thread-breakage.sh +++ b/test/T590-thread-breakage.sh @@ -21,7 +21,7 @@ test_description='thread breakage during reindexing' . $(dirname "$0")/test-lib.sh || exit 1 -message_a() { +message_a () { mkdir -p ${MAIL_DIR}/cur cat > ${MAIL_DIR}/cur/a < ${MAIL_DIR}/cur/b <
[PATCH v2 3/6] test: emacs: simplify missing dependencies check
No functional changes. Signed-off-by: Felipe Contreras --- test/test-lib.sh | 14 ++ 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/test/test-lib.sh b/test/test-lib.sh index c1395c87..e1a597f7 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -115,9 +115,11 @@ unset EMAIL unset NAME test_require_emacs () { -test_require_external_prereq emacs -test_require_external_prereq ${TEST_EMACSCLIENT} -test_require_external_prereq dtach +local ret=0 +test_require_external_prereq emacs || ret=1 +test_require_external_prereq ${TEST_EMACSCLIENT} || ret=1 +test_require_external_prereq dtach || ret=1 +return $ret } add_gnupg_home () { @@ -1048,11 +1050,7 @@ EOF test_emacs () { # test dependencies beforehand to avoid the waiting loop below - missing_dependencies= - test_require_external_prereq dtach || missing_dependencies=1 - test_require_external_prereq emacs || missing_dependencies=1 - test_require_external_prereq ${TEST_EMACSCLIENT} || missing_dependencies=1 - test -z "$missing_dependencies" || return + test_require_emacs || return if [ -z "$EMACS_SERVER" ]; then emacs_tests="$NOTMUCH_SRCDIR/test/${this_test_bare}.el" -- 2.31.1 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH v2 4/6] test: emacs: check for configured emacs
Commit d59d9c81 (test: Make the emacsclient binary user-configurable, 2012-11-27) modified the prereq check for the configured emacsclient, but we probably want to do the same for emacs itself. Signed-off-by: Felipe Contreras --- test/test-lib.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-lib.sh b/test/test-lib.sh index e1a597f7..5c56bc22 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -116,7 +116,7 @@ unset NAME test_require_emacs () { local ret=0 -test_require_external_prereq emacs || ret=1 +test_require_external_prereq ${TEST_EMACS} || ret=1 test_require_external_prereq ${TEST_EMACSCLIENT} || ret=1 test_require_external_prereq dtach || ret=1 return $ret -- 2.31.1 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH v2 5/6] test: emacs: fix a couple of shellcheck complaints
In test-lib-emacs.sh line 20: test_require_external_prereq ${TEST_EMACS} || ret=1 ^---^ SC2086: Double quote to prevent globbing and word splitting. Did you mean: test_require_external_prereq "${TEST_EMACS}" || ret=1 In test-lib-emacs.sh line 21: test_require_external_prereq ${TEST_EMACSCLIENT} || ret=1 ^-^ SC2086: Double quote to prevent globbing and word splitting. Did you mean: test_require_external_prereq "${TEST_EMACSCLIENT}" || ret=1 Signed-off-by: Felipe Contreras --- test/test-lib.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test-lib.sh b/test/test-lib.sh index 5c56bc22..756e5baf 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -116,8 +116,8 @@ unset NAME test_require_emacs () { local ret=0 -test_require_external_prereq ${TEST_EMACS} || ret=1 -test_require_external_prereq ${TEST_EMACSCLIENT} || ret=1 +test_require_external_prereq "$TEST_EMACS" || ret=1 +test_require_external_prereq "$TEST_EMACSCLIENT" || ret=1 test_require_external_prereq dtach || ret=1 return $ret } -- 2.31.1 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH v2 6/6] test: split emacs functionality to its own file
This way it's easier to identify the tests that do require emacs stuff. Signed-off-by: Felipe Contreras --- test/T160-json.sh | 1 + test/T170-sexp.sh | 1 + test/T310-emacs.sh | 1 + test/T320-emacs-large-search-buffer.sh | 3 + test/T330-emacs-subject-to-filename.sh | 3 + test/T350-crypto.sh| 1 + test/T355-smime.sh | 1 + test/T357-index-decryption.sh | 1 + test/T358-emacs-protected-headers.sh | 2 + test/T420-emacs-test-functions.sh | 1 + test/T430-emacs-address-cleaning.sh| 3 + test/T440-emacs-hello.sh | 2 + test/T450-emacs-show.sh| 1 + test/T455-emacs-charsets.sh| 3 + test/T460-emacs-tree.sh| 1 + test/T510-thread-replies.sh| 1 + test/T630-emacs-draft.sh | 2 + test/T720-emacs-attachment-warnings.sh | 3 + test/T730-emacs-forwarding.sh | 1 + test/test-lib-emacs.sh | 209 + test/test-lib.sh | 195 --- 21 files changed, 241 insertions(+), 195 deletions(-) create mode 100644 test/test-lib-emacs.sh diff --git a/test/T160-json.sh b/test/T160-json.sh index e8b75605..638afb4d 100755 --- a/test/T160-json.sh +++ b/test/T160-json.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash test_description="--format=json output" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 test_begin_subtest "Show message: json" add_message "[subject]=\"json-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" "[bcc]=\"test_suite+...@notmuchmail.org\"" "[reply-to]=\"test_suite+repl...@notmuchmail.org\"" "[body]=\"json-show-message\"" diff --git a/test/T170-sexp.sh b/test/T170-sexp.sh index 24be8351..af8c4b44 100755 --- a/test/T170-sexp.sh +++ b/test/T170-sexp.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash test_description="--format=sexp output" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 test_begin_subtest "Show message: sexp" add_message "[subject]=\"sexp-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" "[bcc]=\"test_suite+...@notmuchmail.org\"" "[reply-to]=\"test_suite+repl...@notmuchmail.org\"" "[body]=\"sexp-show-message\"" diff --git a/test/T310-emacs.sh b/test/T310-emacs.sh index 851ef64e..1ece6e00 100755 --- a/test/T310-emacs.sh +++ b/test/T310-emacs.sh @@ -2,6 +2,7 @@ test_description="emacs interface" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 EXPECTED=$NOTMUCH_SRCDIR/test/emacs.expected-output diff --git a/test/T320-emacs-large-search-buffer.sh b/test/T320-emacs-large-search-buffer.sh index f61e8a97..d2638c8b 100755 --- a/test/T320-emacs-large-search-buffer.sh +++ b/test/T320-emacs-large-search-buffer.sh @@ -1,11 +1,14 @@ #!/usr/bin/env bash test_description="Emacs with large search results buffer" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 x=xx # 10 x=$x$x$x$x$x$x$x$x$x$x # 100 x=$x$x$x$x$x$x$x$x$x # 900 +test_require_emacs + # We generate a long subject here (over 900 bytes) so that the emacs # search results get large quickly. With 30 such messages we should # cross several 4kB page boundaries and see the bug. diff --git a/test/T330-emacs-subject-to-filename.sh b/test/T330-emacs-subject-to-filename.sh index eaf7c980..6e09a048 100755 --- a/test/T330-emacs-subject-to-filename.sh +++ b/test/T330-emacs-subject-to-filename.sh @@ -2,6 +2,9 @@ test_description="emacs: mail subject to filename" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 + +test_require_emacs # emacs server can't be started in a child process with $(test_emacs ...) test_emacs '(ignore)' > /dev/null diff --git a/test/T350-crypto.sh b/test/T350-crypto.sh index ae1d6a98..4508c984 100755 --- a/test/T350-crypto.sh +++ b/test/T350-crypto.sh @@ -6,6 +6,7 @@ test_description='PGP/MIME signature verification and decryption' . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 ## diff --git a/test/T355-smime.sh b/test/T355-smime.sh index 12ac2525..69bdcfac 100755 --- a/test/T355-smime.sh +++ b/test/T355-smime.sh @@ -2,6 +2,7 @@ test_description='S/MIME signature verification and decryption' . $(dirname "$0")/test-lib.sh ||
[PATCH] ruby: improve compilation with CFLAGS
The ruby MakeMakefile generates a makefile that is suboptimal, which has CFLAGS like this: CFLAGS = $(CCDLFLAGS) -march=x86-64 -mtune=generic \ -O2 -pipe -fno-plt -fPIC $(ARCH_FLAG) This works as long as the user doesn't modify the Makefile. Certain flags (namely -fPIC) need to be present regardless of what CFLAGS are specified. The Makefile should have done this instead: CFLAGS = -march=x86-64 -mtune=generic -O2 override CFLAGS += $(CCDLFLAGS) -pipe -fno-plt -fPIC $(ARCH_FLAG) Unfortunately they didn't, so we need to workaround their lack of foresight. We can simply add the necessary flags in the parent Makefile so everyone is happy. Signed-off-by: Felipe Contreras --- bindings/Makefile.local | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/Makefile.local b/bindings/Makefile.local index bc960bbc..3672e69f 100644 --- a/bindings/Makefile.local +++ b/bindings/Makefile.local @@ -10,7 +10,7 @@ ifeq ($(HAVE_RUBY_DEV),1) LIBNOTMUCH="../../lib/$(LINKER_NAME)" \ NOTMUCH_SRCDIR='$(NOTMUCH_SRCDIR)' \ $(RUBY) extconf.rb --vendor - $(MAKE) -C $(dir)/ruby + $(MAKE) -C $(dir)/ruby CFLAGS="$(CFLAGS) -pipe -fno-plt -fPIC" endif python-cffi-bindings: lib/$(LINKER_NAME) -- 2.31.1 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH] ruby: improve compilation with CFLAGS
On Mon, May 17, 2021 at 12:48 AM Felipe Contreras wrote: > > The ruby MakeMakefile generates a makefile that is suboptimal, which has > CFLAGS like this: > > CFLAGS = $(CCDLFLAGS) -march=x86-64 -mtune=generic \ > -O2 -pipe -fno-plt -fPIC $(ARCH_FLAG) > > This works as long as the user doesn't modify the Makefile. Great... doesn't modify the CFLAGS. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 0/2] ruby: enable garbage collection
Ruby is a gc language, we shouldn't be doing workaround to free memory when Ruby is perfectly capable of doing so. The problem is that talloc wants to be smart, and Ruby and talloc both fight to free memory. We can let Ruby win by stealing all the objects from talloc control. Thanks to the previous cleanup patches it's now possible to easily do this. In order to test this series I've used the following script: require 'notmuch' $db = Notmuch::Database.new(ENV['HOME'] + '/mail') $do_destroy = true while true query = $db.query('') threads = query.search_threads threads.each do |thread| puts '%s: %s' % [thread.thread_id, thread.subject] thread.destroy! if $do_destroy end threads.destroy! if $do_destroy query.destroy! if $do_destroy end $db.close All threads from the database are fetched over and over with no significant increase in memory. The old method of destroying objects with destroy! still works, but now it's not necessary. I tried other methods, like increasing the reference counter and adding a second parent to talloc objects, but for some reason they didn't work. I investiged why but couldn't reach any conclussion. On the other hand the talloc_steal approach works perfectly fine. Felipe Contreras (2): ruby: create an actual wrapper struct ruby: enable garbage collection using talloc bindings/ruby/database.c | 2 +- bindings/ruby/defs.h | 42 +++- bindings/ruby/extconf.rb | 1 + bindings/ruby/init.c | 6 ++ 4 files changed, 45 insertions(+), 6 deletions(-) -- 2.31.1 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 2/2] ruby: enable garbage collection using talloc
We basically steal all the objects from their notmuch parents, therefore they are completely under Ruby's gc control. The order at which these objects are freed does not matter any more, because destroying the database does not destroy all the children objects, since they belong to Ruby now. Signed-off-by: Felipe Contreras --- bindings/ruby/database.c | 2 +- bindings/ruby/defs.h | 11 +++ bindings/ruby/extconf.rb | 1 + 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/bindings/ruby/database.c b/bindings/ruby/database.c index 66100de2..3737be17 100644 --- a/bindings/ruby/database.c +++ b/bindings/ruby/database.c @@ -81,7 +81,7 @@ notmuch_rb_database_initialize (int argc, VALUE *argv, VALUE self) ret = notmuch_database_open (path, mode, &database); notmuch_rb_status_raise (ret); -DATA_PTR (self) = notmuch_rb_object_create (database); +DATA_PTR (self) = notmuch_rb_object_create (database, "notmuch_rb_database"); return self; } diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index 1413eb72..5cebd5fa 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -23,6 +23,7 @@ #include #include +#include extern VALUE notmuch_rb_cDatabase; extern VALUE notmuch_rb_cDirectory; @@ -83,7 +84,7 @@ extern const rb_data_type_t notmuch_rb_tags_type; } while (0) #define Data_Wrap_Notmuch_Object(klass, type, ptr) \ -TypedData_Wrap_Struct ((klass), (type), notmuch_rb_object_create ((ptr))) +TypedData_Wrap_Struct ((klass), (type), notmuch_rb_object_create ((ptr), "notmuch_rb_object: " __location__)) #define Data_Get_Notmuch_Database(obj, ptr) \ Data_Get_Notmuch_Object ((obj), ¬much_rb_database_type, (ptr)) @@ -117,20 +118,22 @@ typedef struct { } notmuch_rb_object_t; static inline void * -notmuch_rb_object_create (void *nm_object) +notmuch_rb_object_create (void *nm_object, const char *name) { -notmuch_rb_object_t *rb_wrapper = malloc (sizeof (*rb_wrapper)); +notmuch_rb_object_t *rb_wrapper = talloc_named_const (NULL, sizeof (*rb_wrapper), name); + if (RB_UNLIKELY (!rb_wrapper)) return NULL; rb_wrapper->nm_object = nm_object; +talloc_steal (rb_wrapper, nm_object); return rb_wrapper; } static inline void notmuch_rb_object_free (void *rb_wrapper) { -free (rb_wrapper); +talloc_free (rb_wrapper); } static inline notmuch_status_t diff --git a/bindings/ruby/extconf.rb b/bindings/ruby/extconf.rb index 161de5a2..d914537c 100644 --- a/bindings/ruby/extconf.rb +++ b/bindings/ruby/extconf.rb @@ -19,6 +19,7 @@ if not ENV['LIBNOTMUCH'] end $LOCAL_LIBS += ENV['LIBNOTMUCH'] +$LIBS += " -ltalloc" # Create Makefile dir_config('notmuch') -- 2.31.1 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 1/2] ruby: create an actual wrapper struct
Currently Ruby data points directly to a notmuch object (e.g. notmuch_database_t), since we don't need any extra data that is fine. However, in the next commit we will need extra data, therefore we create a new struct notmuch_rb_object_t wrapper which contains nothing but a pointer to the current pointer (e.g. notmuch_database_t). This struct is tied to the Ruby object, and is freed when the Ruby object is freed by the garbage collector. We do nothing with this wrapper, so no functionality should be changed. Signed-off-by: Felipe Contreras --- bindings/ruby/database.c | 2 +- bindings/ruby/defs.h | 39 ++- bindings/ruby/init.c | 6 ++ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/bindings/ruby/database.c b/bindings/ruby/database.c index bb993d86..66100de2 100644 --- a/bindings/ruby/database.c +++ b/bindings/ruby/database.c @@ -81,7 +81,7 @@ notmuch_rb_database_initialize (int argc, VALUE *argv, VALUE self) ret = notmuch_database_open (path, mode, &database); notmuch_rb_status_raise (ret); -DATA_PTR (self) = database; +DATA_PTR (self) = notmuch_rb_object_create (database); return self; } diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index 9860ee17..1413eb72 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -66,7 +66,7 @@ extern const rb_data_type_t notmuch_rb_messages_type; extern const rb_data_type_t notmuch_rb_message_type; extern const rb_data_type_t notmuch_rb_tags_type; -#define Data_Get_Notmuch_Object(obj, type, ptr) \ +#define Data_Get_Notmuch_Rb_Object(obj, type, ptr) \ do { \ (ptr) = rb_check_typeddata ((obj), (type)); \ if (RB_UNLIKELY (!(ptr))) { \ @@ -75,8 +75,15 @@ extern const rb_data_type_t notmuch_rb_tags_type; } \ } while (0) +#define Data_Get_Notmuch_Object(obj, type, ptr)\ +do { \ + notmuch_rb_object_t *rb_wrapper;\ + Data_Get_Notmuch_Rb_Object ((obj), (type), rb_wrapper); \ + (ptr) = rb_wrapper->nm_object; \ +} while (0) + #define Data_Wrap_Notmuch_Object(klass, type, ptr) \ -TypedData_Wrap_Struct ((klass), (type), (ptr)) +TypedData_Wrap_Struct ((klass), (type), notmuch_rb_object_create ((ptr))) #define Data_Get_Notmuch_Database(obj, ptr) \ Data_Get_Notmuch_Object ((obj), ¬much_rb_database_type, (ptr)) @@ -105,16 +112,38 @@ extern const rb_data_type_t notmuch_rb_tags_type; #define Data_Get_Notmuch_Tags(obj, ptr) \ Data_Get_Notmuch_Object ((obj), ¬much_rb_tags_type, (ptr)) +typedef struct { +void *nm_object; +} notmuch_rb_object_t; + +static inline void * +notmuch_rb_object_create (void *nm_object) +{ +notmuch_rb_object_t *rb_wrapper = malloc (sizeof (*rb_wrapper)); +if (RB_UNLIKELY (!rb_wrapper)) + return NULL; + +rb_wrapper->nm_object = nm_object; +return rb_wrapper; +} + +static inline void +notmuch_rb_object_free (void *rb_wrapper) +{ +free (rb_wrapper); +} + static inline notmuch_status_t notmuch_rb_object_destroy (VALUE rb_object, const rb_data_type_t *type) { -void *nm_object; +notmuch_rb_object_t *rb_wrapper; notmuch_status_t ret; -Data_Get_Notmuch_Object (rb_object, type, nm_object); +Data_Get_Notmuch_Rb_Object (rb_object, type, rb_wrapper); /* Call the corresponding notmuch_*_destroy function */ -ret = ((notmuch_status_t (*)(void *)) type->data) (nm_object); +ret = ((notmuch_status_t (*)(void *)) type->data) (rb_wrapper->nm_object); +notmuch_rb_object_free (rb_wrapper); DATA_PTR (rb_object) = NULL; return ret; diff --git a/bindings/ruby/init.c b/bindings/ruby/init.c index 62515eca..831f7695 100644 --- a/bindings/ruby/init.c +++ b/bindings/ruby/init.c @@ -48,6 +48,9 @@ ID ID_db_mode; const rb_data_type_t notmuch_rb_object_type = { .wrap_struct_name = "notmuch_object", +.function = { + .dfree = notmuch_rb_object_free, +}, }; #define define_type(id) \ @@ -55,6 +58,9 @@ const rb_data_type_t notmuch_rb_object_type = { .wrap_struct_name = "notmuch_" #id, \ .parent = ¬much_rb_object_type, \ .data = ¬much_ ## id ## _destroy, \ + .function = { \ + .dfree = notmuch_rb_object_free, \ + }, \ } define_type (database); -- 2.31.1 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH v2] test: replace notmuch_passwd_sanitize() with _libconfig_sanitize()
On Mon, May 17, 2021 at 2:33 PM Tomi Ollila wrote: > > notmuch_passwd_sanitize() in test-lib.sh is too generic, it cannot > work in many cases... > > The more specific version _libconfig_sanitize() replaces it in > T590-libconfig.sh and the code that uses it is modified to output > the keys (ascending numbers printed in hex) so the sanitizer knows > what to sanitize in which lines... > > In addition to ".(none)" now also ".localdomain" if filtered from > USERNAME@FQDN. > --- > > Rebase of id:20210502181535.31292-1-tomi.oll...@iki.fi > > * 'fn () {' style change > * added @ to fqdn replace, as it could be subset of user > > test/T590-libconfig.sh | 97 +- > test/test-lib.sh | 20 - > 2 files changed, 59 insertions(+), 58 deletions(-) > > diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh > index 745e1bb4..8e70b7b2 100755 > --- a/test/T590-libconfig.sh > +++ b/test/T590-libconfig.sh > @@ -5,6 +5,26 @@ test_description="library config API" > > add_email_corpus > > +_libconfig_sanitize() { > +${NOTMUCH_PYTHON} -c ' > +import os, sys, pwd, socket > + > +pw = pwd.getpwuid(os.getuid()) > +user = pw.pw_name > +name = pw.pw_gecos.partition(",")[0] > +fqdn = socket.getaddrinfo(socket.gethostname(), 0, 0, > + socket.SOCK_STREAM, 0, socket.AI_CANONNAME)[0][3] > +for l in sys.stdin: > +if l[:3] == "8: ": > +# fqdn could be subset of user; therefore @ > +l = l.replace(user, "USERNAME").replace("@" + fqdn, "@FQDN") > +l = l.replace(".(none)", "").replace(".localdomain", "") > +elif l[:3] == "a: ": > +l = l.replace(name, "USER_FULL_NAME") This generates garbage when name is null. See ff5f141b (test: fix passwd_sanitize(), 2021-05-01). At the very least we need to check for that, even better if we generate the proper output: if name: l = l.replace(name, "USER_FULL_NAME") else: l = "a: \'USER_FULL_NAME\'\\n" This makes the test pass with no geckos name, but we need to use bash strings: $'string'. Otherwise we would need to do something much more weird. Cheers. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH v3] test: replace notmuch_passwd_sanitize() with _libconfig_sanitize()
On Tue, May 18, 2021 at 12:55 AM Tomi Ollila wrote: > > notmuch_passwd_sanitize() in test-lib.sh is too generic, it cannot > work in many cases... > > The more specific version _libconfig_sanitize() replaces it in > T590-libconfig.sh and the code that uses it is modified to output > the keys (ascending numbers printed in hex) so the sanitizer knows > what to sanitize in which lines... > > "@" + fqdn -> "@FQDN" replacement is used as fqdn could -- > in theory -- be substring of 'USERNAME'. > > 'user -> 'USER_FULL_NAME replacement to work in cases where user > is empty -- as only first ' is replaced that works as expected. > > In addition to ".(none)" now also ".localdomain" is filtered from > USERNAME@FQDN. > --- > > Changes to [v2]: > > * work in cases of empty user (e.g. in passwd gecos field) > * replace only 1st match; e.g. fqdn could contain substring of user > > v2: id:20210517193315.11343-1-tomi.oll...@iki.fi > v1: id:20210502181535.31292-1-tomi.oll...@iki.fi > > When tried w/ one replacement and w/o sq usage and emptied gecos, got > > . @@ -9,5 +9,5 @@ > . 7: 'true' > . 8: 'USERNAME@FQDN' > . 9: 'NULL' > . -a: 'USER_FULL_NAME' > . +USER_FULL_NAMEa: '' > > test/T590-libconfig.sh | 97 +- > test/test-lib.sh | 20 - > 2 files changed, 59 insertions(+), 58 deletions(-) > > diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh > index 745e1bb4..42cbe6e0 100755 > --- a/test/T590-libconfig.sh > +++ b/test/T590-libconfig.sh > @@ -5,6 +5,26 @@ test_description="library config API" > > add_email_corpus > > +_libconfig_sanitize() { > +${NOTMUCH_PYTHON} -c ' > +import os, sys, pwd, socket Why not use a heredoc? python <<-EOF .. EOF > +pw = pwd.getpwuid(os.getuid()) > +user = pw.pw_name > +name = pw.pw_gecos.partition(",")[0] > +fqdn = socket.getaddrinfo(socket.gethostname(), 0, 0, > + socket.SOCK_STREAM, 0, socket.AI_CANONNAME)[0][3] > +for l in sys.stdin: > +if l[:3] == "8: ": > +l = l.replace(user, "USERNAME", 1).replace("@" + fqdn, "@FQDN", 1) > +l = l.replace(".(none)", "", 1).replace(".localdomain", "", 1) > +elif l[:3] == "a: ": > +sq = chr(39) # single quote > +l = l.replace(sq + name, sq + "USER_FULL_NAME", 1) Then we can simply do: l.replace("'" + name, "'USER_FULL_NAME", 1) The rest looks fine to me. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH v3] test: replace notmuch_passwd_sanitize() with _libconfig_sanitize()
On Wed, May 19, 2021 at 12:34 PM Tomi Ollila wrote: > Haha, as we do _libconfig_sanitize < OUTPUT > OUTPUT.clean > reading python script from stdin don't work (perl has __DATA__ ;). > (bitten again, I did and tested the change... :D). That can be fixed with: python /dev/fd/3 3<
Re: [PATCH v3] test: replace notmuch_passwd_sanitize() with _libconfig_sanitize()
On Thu, May 20, 2021 at 2:43 AM Tomi Ollila wrote: > > On Wed, May 19 2021, Felipe Contreras wrote: > > > On Wed, May 19, 2021 at 12:34 PM Tomi Ollila wrote: > > > >> Haha, as we do _libconfig_sanitize < OUTPUT > OUTPUT.clean > >> reading python script from stdin don't work (perl has __DATA__ ;). > >> (bitten again, I did and tested the change... :D). > > > > That can be fixed with: > > > > python /dev/fd/3 3< > EOF > > According to > > https://unix.stackexchange.com/questions/123602/portability-of-file-descriptor-links > > that solution could be portable enough. What the operating system does doesn't really matter, bash emulates /dev/fd/x: "If the operating system on which Bash is running provides these special files, bash will use them; otherwise it will emulate them internally with the behavior described below." https://www.gnu.org/software/bash/manual/html_node/Redirections.html And as far as I know the testing framework only works correctly on bash... So... > Another way still using -c ... I've played to look how it actually looks is > (diff since patch v3) > > -sq = chr(39) # single quote > -l = l.replace(sq + name, sq + "USER_FULL_NAME", 1) > +l = l.replace("'\''" + name, "'\''USER_FULL_NAME", 1) Yes, that works too. But that's what I said in another mail that is weird stuff. I had to read it again three times and then copy to a proper text editor with monospace font to see if it was correct. > Tested the above. That python /dev/fd/3 3< have to be tested to see how it looks like and behaves... :D Yeap. Took me a while to find the right documentation to figure that out, but in my opinion it's better to write a helper for the tests once, and then forget about it and just re-use it for all. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH 3/3] test: ruby: simplify basic tests
On Sun, May 23, 2021 at 7:32 AM David Bremner wrote: > > Felipe Contreras writes: > > > We don't need to check for the order here, that is done in another test. > > > > Signed-off-by: Felipe Contreras > > --- > > test/T395-ruby.sh | 12 > > 1 file changed, 4 insertions(+), 8 deletions(-) > > > > diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh > > index e828efed..9298bc9e 100755 > > --- a/test/T395-ruby.sh > > +++ b/test/T395-ruby.sh > > @@ -20,21 +20,17 @@ test_ruby() { > > } > > > > test_begin_subtest "compare thread ids" > > -notmuch search --sort=oldest-first --output=threads tag:inbox > EXPECTED > > +notmuch search --output=threads tag:inbox > EXPECTED > > test_ruby <<"EOF" > > -q = db.query('tag:inbox') > > -q.sort = Notmuch::SORT_OLDEST_FIRST > > -q.search_threads.each do |t| > > +db.query('tag:inbox').search_threads.each do |t| > >puts 'thread:%s' % t.thread_id > > end > > EOF > > > > Is this assuming that the sort order in the CLI is the same as in the > library / bindings? that seems a bit fragile if so. Both the CLI and the bindings are using the same libnotmuch library. If neither of them specify a sort order, the default sort order of libnotmuch would be used (I presume). Exactly the same order I would get if I write a C program that uses libnotmuch and doesn't specify any order. Why would the CLI specify an order the user didn't specify to libnotmuch? -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH v2 1/2] ruby: add keyword arguments to db.query
That way we don't need pass them to the query object ourselves. Signed-off-by: Felipe Contreras --- bindings/ruby/database.c | 47 +--- bindings/ruby/defs.h | 2 +- bindings/ruby/init.c | 2 +- test/T395-ruby.sh| 18 +++ 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/bindings/ruby/database.c b/bindings/ruby/database.c index bb993d86..d6c804ac 100644 --- a/bindings/ruby/database.c +++ b/bindings/ruby/database.c @@ -395,17 +395,24 @@ notmuch_rb_database_get_all_tags (VALUE self) } /* - * call-seq: DB.query(query) => QUERY + * call-seq: + * DB.query(query) => QUERY + * DB.query(query, sort:, excluded_tags:, omit_excluded:) => QUERY * - * Retrieve a query object for the query string 'query' + * Retrieve a query object for the query string 'query'. When using keyword + * arguments they are passwed to the query object. */ VALUE -notmuch_rb_database_query_create (VALUE self, VALUE qstrv) +notmuch_rb_database_query_create (int argc, VALUE *argv, VALUE self) { +VALUE qstrv; +VALUE opts; const char *qstr; notmuch_query_t *query; notmuch_database_t *db; +rb_scan_args (argc, argv, "1:", &qstrv, &opts); + Data_Get_Notmuch_Database (self, db); SafeStringValue (qstrv); @@ -415,5 +422,39 @@ notmuch_rb_database_query_create (VALUE self, VALUE qstrv) if (!query) rb_raise (notmuch_rb_eMemoryError, "Out of memory"); +if (!NIL_P (opts)) { + VALUE sort, exclude_tags, omit_excluded; + VALUE kwargs[3]; + static ID keyword_ids[3]; + + if (!keyword_ids[0]) { + keyword_ids[0] = rb_intern_const ("sort"); + keyword_ids[1] = rb_intern_const ("exclude_tags"); + keyword_ids[2] = rb_intern_const ("omit_excluded"); + } + + rb_get_kwargs (opts, keyword_ids, 0, 3, kwargs); + + sort = kwargs[0]; + exclude_tags = kwargs[1]; + omit_excluded = kwargs[2]; + + if (sort != Qundef) + notmuch_query_set_sort (query, FIX2UINT (sort)); + + if (exclude_tags != Qundef) { + for (int i = 0; i < RARRAY_LEN (exclude_tags); i++) { + VALUE e = RARRAY_AREF (exclude_tags, i); + notmuch_query_add_tag_exclude (query, RSTRING_PTR (e)); + } + } + + if (omit_excluded != Qundef) { + notmuch_exclude_t omit; + omit = FIXNUM_P (omit_excluded) ? FIX2UINT (omit_excluded) : RTEST(omit_excluded); + notmuch_query_set_omit_excluded (query, omit); + } +} + return Data_Wrap_Notmuch_Object (notmuch_rb_cQuery, ¬much_rb_query_type, query); } diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index 9860ee17..995bcafd 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -174,7 +174,7 @@ VALUE notmuch_rb_database_get_all_tags (VALUE self); VALUE -notmuch_rb_database_query_create (VALUE self, VALUE qstrv); +notmuch_rb_database_query_create (int argc, VALUE *argv, VALUE self); /* directory.c */ VALUE diff --git a/bindings/ruby/init.c b/bindings/ruby/init.c index bedfbf60..d421c601 100644 --- a/bindings/ruby/init.c +++ b/bindings/ruby/init.c @@ -275,7 +275,7 @@ Init_notmuch (void) rb_define_method (notmuch_rb_cDatabase, "find_message_by_filename", notmuch_rb_database_find_message_by_filename, 1); /* in database.c */ rb_define_method (notmuch_rb_cDatabase, "all_tags", notmuch_rb_database_get_all_tags, 0); /* in database.c */ -rb_define_method (notmuch_rb_cDatabase, "query", notmuch_rb_database_query_create, 1); /* in database.c */ +rb_define_method (notmuch_rb_cDatabase, "query", notmuch_rb_database_query_create, -1); /* in database.c */ /* * Document-class: Notmuch::Directory diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index d36d4aff..e828efed 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -82,4 +82,22 @@ q.search_threads.each do |t| end EOF +test_begin_subtest "check sort argument" +notmuch search --sort=oldest-first --output=threads tag:inbox > EXPECTED +test_ruby <<"EOF" +q = db.query('tag:inbox', sort: Notmuch::SORT_OLDEST_FIRST) +q.search_threads.each do |t| + puts 'thread:%s' % t.thread_id +end +EOF + +test_begin_subtest "check exclude_tags argument" +notmuch search --output=threads --exclude=all tag:inbox > EXPECTED +test_ruby <<"EOF" +q = db.query('tag:inbox', exclude_tags: %w[deleted], omit_excluded: Notmuch::EXCLUDE_ALL) +q.search_threads.each do |t| + puts 'thread:%s' % t.thread_id +end +EOF + test_done -- 2.32.0.rc0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH v2 2/2] test: ruby: simplify basic tests
We don't need to check for the order here, that is done in another test. Signed-off-by: Felipe Contreras --- test/T395-ruby.sh | 12 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index e828efed..9298bc9e 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -20,21 +20,17 @@ test_ruby() { } test_begin_subtest "compare thread ids" -notmuch search --sort=oldest-first --output=threads tag:inbox > EXPECTED +notmuch search --output=threads tag:inbox > EXPECTED test_ruby <<"EOF" -q = db.query('tag:inbox') -q.sort = Notmuch::SORT_OLDEST_FIRST -q.search_threads.each do |t| +db.query('tag:inbox').search_threads.each do |t| puts 'thread:%s' % t.thread_id end EOF test_begin_subtest "compare message ids" -notmuch search --sort=oldest-first --output=messages tag:inbox > EXPECTED +notmuch search --output=messages tag:inbox > EXPECTED test_ruby <<"EOF" -q = db.query('tag:inbox') -q.sort = Notmuch::SORT_OLDEST_FIRST -q.search_messages.each do |m| +db.query('tag:inbox').search_messages.each do |m| puts 'id:%s' % m.message_id end EOF -- 2.32.0.rc0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH v2 0/2] ruby: improve db.query
I find it a bit annoying to have to modify the query object to add options when Notmuch::Database.query() can do that just fine. This series also adds a mapping to the notmuch_exclude_t enum in order to be able to specify NOTMUCH_EXCLUDE_ALL and others. Nothing changed from v1 except rebased on master of May 23. Felipe Contreras (2): ruby: add keyword arguments to db.query test: ruby: simplify basic tests bindings/ruby/database.c | 47 +--- bindings/ruby/defs.h | 2 +- bindings/ruby/init.c | 2 +- test/T395-ruby.sh| 30 ++--- 4 files changed, 68 insertions(+), 13 deletions(-) Range-diff against v1: 1: 8cc8cedd < -: ruby: use notmuch_exclude_t enum 2: 70938802 ! 1: ec8b5d1a ruby: add keyword arguments to db.query @@ bindings/ruby/database.c: notmuch_rb_database_query_create (VALUE self, VALUE qs + } +} + - return Data_Wrap_Struct (notmuch_rb_cQuery, NULL, NULL, query); + return Data_Wrap_Notmuch_Object (notmuch_rb_cQuery, ¬much_rb_query_type, query); } ## bindings/ruby/defs.h ## 3: 26519f68 = 2: 29c15ec1 test: ruby: simplify basic tests -- 2.32.0.rc0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH 2/3] ruby: add keyword arguments to db.query
On Sun, May 23, 2021 at 7:29 AM David Bremner wrote: > > Felipe Contreras writes: > > > That way we don't need pass them to the query object ourselves. > > LGTM, but when I tried to resolve the conflicts I messed something up > and the ruby sort test(s) started failing. Rebase please? Not sure what happened there, my rebase happened without conflicts. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH v3] test: replace notmuch_passwd_sanitize() with _libconfig_sanitize()
On Fri, May 21, 2021 at 1:22 PM Tomi Ollila wrote: > > On Fri, May 21 2021, Felipe Contreras wrote: > > > On Thu, May 20, 2021 at 2:43 AM Tomi Ollila wrote: > >> > >> On Wed, May 19 2021, Felipe Contreras wrote: > >> > >> > On Wed, May 19, 2021 at 12:34 PM Tomi Ollila wrote: > >> > > >> >> Haha, as we do _libconfig_sanitize < OUTPUT > OUTPUT.clean > >> >> reading python script from stdin don't work (perl has __DATA__ ;). > >> >> (bitten again, I did and tested the change... :D). > >> > > >> > That can be fixed with: > >> > > >> > python /dev/fd/3 3< >> > EOF > >> > >> According to > >> > >> https://unix.stackexchange.com/questions/123602/portability-of-file-descriptor-links > >> > >> that solution could be portable enough. > > > > What the operating system does doesn't really matter, bash emulates > > /dev/fd/x: > > In this case, /dev/fd/3 is given as a parameter to a command, not part of > redirections -- bash cannot know how the program is going to use the > arguments it gets... Right. I did try doing the redirection inside the python code. That also works fine, but I don't think there's a need of doing that unless there's an actual issue with /dev/fd/3. > > And as far as I know the testing framework only works correctly on bash... > > So... > > > >> Another way still using -c ... I've played to look how it actually looks is > >> (diff since patch v3) > >> > >> -sq = chr(39) # single quote > >> -l = l.replace(sq + name, sq + "USER_FULL_NAME", 1) > >> +l = l.replace("'\''" + name, "'\''USER_FULL_NAME", 1) > > > > Yes, that works too. But that's what I said in another mail that is > > weird stuff. I had to read it again three times and then copy to a > > proper text editor with monospace font to see if it was correct. > > To me '\'' is /idiomatic/ way to embed ' in the middle of a long argument > string... Maybe. I've written a lot of shell code and whenever that happens I switch to double quotes. "foo 'quote' bar" is much more readable to me than 'foo '\''quote'\'' bar'. Cheers. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH 0/2] ruby: enable garbage collection
On Sat, May 22, 2021 at 5:49 AM David Bremner wrote: > > Felipe Contreras writes: > > > Ruby is a gc language, we shouldn't be doing workaround to free memory when > > Ruby is perfectly > > capable of doing so. > > > > The problem is that talloc wants to be smart, and Ruby and talloc both > > fight to free memory. We can > > let Ruby win by stealing all the objects from talloc control. > > > > Thanks to the previous cleanup patches it's now possible to easily do this. > > > > In order to test this series I've used the following script: > > I still haven't had a chance to look at the series, but how about making > this script either a test or a performance-test, as appropriate? I gave this a try, and even compiled Ruby with --with-valgrind (apparently Arch Linux doesn't do that), but doesn't seem to work right: % valgrind /opt/ruby/bin/ruby -e 'p true' HEAP SUMMARY: in use at exit: 37,193,788 bytes in 21,951 blocks total heap usage: 61,729 allocs, 39,778 frees, 51,503,615 bytes allocated LEAK SUMMARY: definitely lost: 510,491 bytes in 4,617 blocks indirectly lost: 795,436 bytes in 9,411 blocks possibly lost: 2,128,254 bytes in 7,100 blocks still reachable: 33,759,607 bytes in 823 blocks suppressed: 0 bytes in 0 blocks Rerun with --leak-check=full to see details of leaked memory Trying to run the simplest of Ruby commands throws a log 93,000 lines long. I did try to search online resources to use valgrind with Ruby to no avail. Apparently everyone is using valgrind with a baseline (if valgrind shows 500 KiB lost as a start, how much does it change after my changes?). Sure, we could try to massage a valgrind suppression file, but is it worth the effort if the Ruby project itself hasn't even tried to do that? If we wanted to measure the memory performance of such a command (which I think would be very nice) a different strategy is needed. I also didn't see any talloc output. For now I don't think the series should be blocked by this setback. Just try to run the command yourself with top. You can see it works. Cheers. -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 0/3] ruby: add latest config API
Currently the simplest way to open the notmuch database properly a client must do: $config = IO.popen(%w[notmuch config list]) do |io| io.each(chomp: true).map { |e| e.split('=') }.to_h end $db_name = config['database.path'] $db = Notmuch::Database.new($db_name) While this works and it's not too overly complicated, the notmuch API already has much better constucts. This patch series allows the user to simply do: $db = Notmuch::Database.open_with_config $config = $db.config.to_h And much more. Felipe Contreras (3): ruby: add new Database.open_with_config ruby: add db.config ruby: make db.config return an enumerator bindings/ruby/database.c | 95 bindings/ruby/defs.h | 10 + bindings/ruby/init.c | 2 + test/T395-ruby.sh| 13 ++ 4 files changed, 120 insertions(+) -- 2.32.0.rc2 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 1/3] ruby: add new Database.open_with_config
In order to make use of notmuch_database_open_with_config. Signed-off-by: Felipe Contreras --- bindings/ruby/database.c | 62 bindings/ruby/defs.h | 6 bindings/ruby/init.c | 1 + test/T395-ruby.sh| 6 4 files changed, 75 insertions(+) diff --git a/bindings/ruby/database.c b/bindings/ruby/database.c index bb993d86..bc0c22cb 100644 --- a/bindings/ruby/database.c +++ b/bindings/ruby/database.c @@ -105,6 +105,68 @@ notmuch_rb_database_open (int argc, VALUE *argv, VALUE klass) return rb_ensure (rb_yield, obj, notmuch_rb_database_close, obj); } +/* + * call-seq: Notmuch::Database.open_with_config([database_path:, mode:, config_path:, profile:]) [{|db| ... }] + * + * Opens a database with a configuration file. + * + */ +VALUE +notmuch_rb_database_open_with_config (int argc, VALUE *argv, VALUE klass) +{ +VALUE obj; +notmuch_database_t *db; +notmuch_status_t ret; +VALUE opts; +const char *database_path = NULL; +notmuch_database_mode_t mode = NOTMUCH_DATABASE_MODE_READ_ONLY; +const char *config_path = NULL; +const char *profile = NULL; + +rb_scan_args (argc, argv, ":", &opts); + +if (!NIL_P (opts)) { + VALUE rdatabase_path, rmode, rconfig_path, rprofile; + VALUE kwargs[4]; + static ID keyword_ids[4]; + + if (!keyword_ids[0]) { + keyword_ids[0] = rb_intern_const ("database_path"); + keyword_ids[1] = rb_intern_const ("mode"); + keyword_ids[2] = rb_intern_const ("config_path"); + keyword_ids[3] = rb_intern_const ("profile"); + } + + rb_get_kwargs (opts, keyword_ids, 0, 4, kwargs); + + rdatabase_path = kwargs[0]; + rmode = kwargs[1]; + rconfig_path = kwargs[2]; + rprofile = kwargs[3]; + + if (rdatabase_path != Qundef) + database_path = nm_str (rdatabase_path); + if (rmode != Qundef) + mode = FIX2INT (rmode); + if (rconfig_path != Qundef) + config_path = nm_str (rconfig_path); + if (rprofile != Qundef) + profile = nm_str (rprofile); +} + +ret = notmuch_database_open_with_config (database_path, mode, +config_path, profile, &db, +NULL); +notmuch_rb_status_raise (ret); +obj = notmuch_rb_database_alloc (klass); +DATA_PTR (obj) = db; + +if (!rb_block_given_p ()) + return obj; + +return rb_ensure (rb_yield, obj, notmuch_rb_database_close, obj); +} + /* * call-seq: DB.close => nil * diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index 9860ee17..78239229 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -55,6 +55,9 @@ extern ID ID_db_mode; # define RSTRING_PTR(v) (RSTRING((v))->ptr) #endif /* !defined (RSTRING_PTR) */ +/* Simple string helpers */ +#define nm_str(str) (str != Qnil ? RSTRING_PTR (str) : NULL) + extern const rb_data_type_t notmuch_rb_object_type; extern const rb_data_type_t notmuch_rb_database_type; extern const rb_data_type_t notmuch_rb_directory_type; @@ -134,6 +137,9 @@ notmuch_rb_database_initialize (int argc, VALUE *argv, VALUE klass); VALUE notmuch_rb_database_open (int argc, VALUE *argv, VALUE klass); +VALUE +notmuch_rb_database_open_with_config (int argc, VALUE *argv, VALUE klass); + VALUE notmuch_rb_database_close (VALUE self); diff --git a/bindings/ruby/init.c b/bindings/ruby/init.c index bedfbf60..27c7eba3 100644 --- a/bindings/ruby/init.c +++ b/bindings/ruby/init.c @@ -259,6 +259,7 @@ Init_notmuch (void) notmuch_rb_cDatabase = rb_define_class_under (mod, "Database", rb_cObject); rb_define_alloc_func (notmuch_rb_cDatabase, notmuch_rb_database_alloc); rb_define_singleton_method (notmuch_rb_cDatabase, "open", notmuch_rb_database_open, -1); /* in database.c */ +rb_define_singleton_method (notmuch_rb_cDatabase, "open_with_config", notmuch_rb_database_open_with_config, -1); /* in database.c */ rb_define_method (notmuch_rb_cDatabase, "initialize", notmuch_rb_database_initialize, -1); /* in database.c */ rb_define_method (notmuch_rb_cDatabase, "close", notmuch_rb_database_close, 0); /* in database.c */ rb_define_method (notmuch_rb_cDatabase, "path", notmuch_rb_database_path, 0); /* in database.c */ diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index d36d4aff..27ac4cc8 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -82,4 +82,10 @@ q.search_threads.each do |t| end EOF +test_begin_subtest "open with config" +echo "$MAIL_DIR" > EXPECTED +test_ruby <
[PATCH 2/3] ruby: add db.config
In order to use notmuch_config_get_pairs. Signed-off-by: Felipe Contreras --- bindings/ruby/database.c | 31 +++ bindings/ruby/defs.h | 4 bindings/ruby/init.c | 1 + test/T395-ruby.sh| 7 +++ 4 files changed, 43 insertions(+) diff --git a/bindings/ruby/database.c b/bindings/ruby/database.c index bc0c22cb..934cbfe8 100644 --- a/bindings/ruby/database.c +++ b/bindings/ruby/database.c @@ -479,3 +479,34 @@ notmuch_rb_database_query_create (VALUE self, VALUE qstrv) return Data_Wrap_Notmuch_Object (notmuch_rb_cQuery, ¬much_rb_query_type, query); } + +/* + * call-seq: DB.config(prefix) {|key, value| block} => nil + * + * Calls +block+ once for each key/value pair. + * + */ +VALUE +notmuch_rb_database_config (int argc, VALUE *argv, VALUE self) +{ +VALUE prefix; +notmuch_database_t *db; +notmuch_config_pairs_t *list; +const char *cprefix; + +Data_Get_Notmuch_Database (self, db); + +rb_scan_args (argc, argv, "01", &prefix); + +cprefix = prefix != Qnil ? RSTRING_PTR (prefix) : ""; + +list = notmuch_config_get_pairs (db, cprefix); +for (; notmuch_config_pairs_valid (list); notmuch_config_pairs_move_to_next (list)) { + const char *key = notmuch_config_pairs_key (list); + const char *value = notmuch_config_pairs_value (list); + rb_yield (rb_ary_new3(2, nm_str_new (key), nm_str_new (value))); +} +notmuch_config_pairs_destroy (list); + +return Qnil; +} diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index 78239229..f31e563b 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -57,6 +57,7 @@ extern ID ID_db_mode; /* Simple string helpers */ #define nm_str(str) (str != Qnil ? RSTRING_PTR (str) : NULL) +#define nm_str_new(str) (str ? rb_str_new_cstr (str) : Qnil) extern const rb_data_type_t notmuch_rb_object_type; extern const rb_data_type_t notmuch_rb_database_type; @@ -182,6 +183,9 @@ notmuch_rb_database_get_all_tags (VALUE self); VALUE notmuch_rb_database_query_create (VALUE self, VALUE qstrv); +VALUE +notmuch_rb_database_config (int argc, VALUE *argv, VALUE self); + /* directory.c */ VALUE notmuch_rb_directory_destroy (VALUE self); diff --git a/bindings/ruby/init.c b/bindings/ruby/init.c index 27c7eba3..4b2f8655 100644 --- a/bindings/ruby/init.c +++ b/bindings/ruby/init.c @@ -277,6 +277,7 @@ Init_notmuch (void) notmuch_rb_database_find_message_by_filename, 1); /* in database.c */ rb_define_method (notmuch_rb_cDatabase, "all_tags", notmuch_rb_database_get_all_tags, 0); /* in database.c */ rb_define_method (notmuch_rb_cDatabase, "query", notmuch_rb_database_query_create, 1); /* in database.c */ +rb_define_method (notmuch_rb_cDatabase, "config", notmuch_rb_database_config, -1); /* in database.c */ /* * Document-class: Notmuch::Directory diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index 27ac4cc8..a7b09589 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -88,4 +88,11 @@ test_ruby < EXPECTED +test_ruby <<"EOF" +config_db = Notmuch::Database.open_with_config +config_db.config { |e| puts '%s=%s' % e } +EOF + test_done -- 2.32.0.rc2 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
[PATCH 3/3] ruby: make db.config return an enumerator
Currently db.config requires a block to work: db.config { |k, v| puts '%s=%s' % [k, v] } If you try to use it without a block you, get an error like: in `config': no block given (LocalJumpError) In Ruby most methods should return an Enumerator if no block is given, like: (1..10).each => # This allows us to do: db.config.to_a db.config.to_h db.config.each { |k, v| ... } And of course what is already possible: db.config { |k, v| ... } Signed-off-by: Felipe Contreras --- bindings/ruby/database.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bindings/ruby/database.c b/bindings/ruby/database.c index 934cbfe8..9316b32d 100644 --- a/bindings/ruby/database.c +++ b/bindings/ruby/database.c @@ -494,6 +494,8 @@ notmuch_rb_database_config (int argc, VALUE *argv, VALUE self) notmuch_config_pairs_t *list; const char *cprefix; +RETURN_ENUMERATOR(self, argc, argv); + Data_Get_Notmuch_Database (self, db); rb_scan_args (argc, argv, "01", &prefix); -- 2.32.0.rc2 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH 2/3] ruby: add db.config
On Thu, Jun 3, 2021 at 10:29 PM Felipe Contreras wrote: > --- a/test/T395-ruby.sh > +++ b/test/T395-ruby.sh > @@ -88,4 +88,11 @@ test_ruby < puts Notmuch::Database.open_with_config.path > EOF > > +test_begin_subtest "config" > +notmuch config list | grep -v '^built_with\.' > EXPECTED > +test_ruby <<"EOF" > +config_db = Notmuch::Database.open_with_config > +config_db.config { |e| puts '%s=%s' % e } > +EOF > + I just noticed this might a little more idiomatic: Notmuch::Database.open_with_config do |db| db.config { |e| puts '%s=%s' % e } end -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH v2 0/2] ruby: improve db.query
On Sun, May 23, 2021 at 9:19 PM Felipe Contreras wrote: > > I find it a bit annoying to have to modify the query object to add > options when Notmuch::Database.query() can do that just fine. > > This series also adds a mapping to the notmuch_exclude_t enum in order > to be able to specify NOTMUCH_EXCLUDE_ALL and others. > > Nothing changed from v1 except rebased on master of May 23. Any update? -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
How to recover from this permanent fatal error?
Hello, I can't use notmuch anymore, I get this error: A Xapian exception occurred opening database: The revision being read has been discarded - you should call Xapian::Database::reopen() and retry the operation Context. In order to investigate a bug about mbsync I moved away the folder ~/mail/.notmuch. I have a timer that calls notmuch new after mbsync, so I paused that timer. Initially I used notmuch, only to see everything empty. Then I recalled what I did, removed all the files, and moved back the .nomuch directory. IIRC I was able to use notmuch without problems once, and then I got the issue. All I can find about the issue is that somebody reported the exact same message to the mailing list (id:87txmb4xyz@mcs.anl.gov), but did not receive any feedback. Ideas? -- Felipe Contreras ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org