[PATCH 10/13] vim: option to add reply quote datetime

2021-04-18 Thread Felipe Contreras
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

2021-04-18 Thread Felipe Contreras
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

2021-04-18 Thread Felipe Contreras
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

2021-04-18 Thread Felipe Contreras
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

2021-04-18 Thread Felipe Contreras
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

2021-04-19 Thread Felipe Contreras
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

2021-04-19 Thread Felipe Contreras
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

2021-04-19 Thread Felipe Contreras
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

2021-04-25 Thread Felipe Contreras
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

2021-04-25 Thread Felipe Contreras
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

2021-04-27 Thread Felipe Contreras
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

2021-04-27 Thread Felipe Contreras
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

2021-04-27 Thread Felipe Contreras
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

2021-04-27 Thread Felipe Contreras
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

2021-04-30 Thread Felipe Contreras
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

2021-04-30 Thread Felipe Contreras
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

2021-04-30 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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()

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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()

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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()

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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()

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-01 Thread Felipe Contreras
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

2021-05-02 Thread Felipe Contreras
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()

2021-05-02 Thread Felipe Contreras
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

2021-05-03 Thread Felipe Contreras
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

2021-05-03 Thread Felipe Contreras
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

2021-05-03 Thread Felipe Contreras
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

2021-05-03 Thread Felipe Contreras
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

2021-05-04 Thread Felipe Contreras
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

2021-05-04 Thread Felipe Contreras
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

2021-05-04 Thread Felipe Contreras
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

2021-05-04 Thread Felipe Contreras
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

2021-05-04 Thread Felipe Contreras
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

2021-05-04 Thread Felipe Contreras
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

2021-05-04 Thread Felipe Contreras
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

2021-05-04 Thread Felipe Contreras
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

2021-05-04 Thread Felipe Contreras
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

2021-05-04 Thread Felipe Contreras
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

2021-05-04 Thread Felipe Contreras
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

2021-05-04 Thread Felipe Contreras
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

2021-05-07 Thread Felipe Contreras
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

2021-05-08 Thread Felipe Contreras
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?

2021-05-09 Thread Felipe Contreras
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?

2021-05-12 Thread Felipe Contreras
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

2021-05-12 Thread Felipe Contreras
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

2021-05-12 Thread Felipe Contreras
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

2021-05-12 Thread Felipe Contreras
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

2021-05-15 Thread Felipe Contreras
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

2021-05-15 Thread Felipe Contreras
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

2021-05-15 Thread Felipe Contreras
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

2021-05-15 Thread Felipe Contreras
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

2021-05-15 Thread Felipe Contreras
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

2021-05-15 Thread Felipe Contreras
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

2021-05-15 Thread Felipe Contreras
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

2021-05-16 Thread Felipe Contreras
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

2021-05-16 Thread Felipe Contreras
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

2021-05-17 Thread Felipe Contreras
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

2021-05-17 Thread Felipe Contreras
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

2021-05-17 Thread Felipe Contreras
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()

2021-05-17 Thread Felipe Contreras
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()

2021-05-19 Thread Felipe Contreras
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()

2021-05-19 Thread Felipe Contreras
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()

2021-05-21 Thread Felipe Contreras
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

2021-05-23 Thread Felipe Contreras
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

2021-05-23 Thread Felipe Contreras
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

2021-05-23 Thread Felipe Contreras
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

2021-05-23 Thread Felipe Contreras
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

2021-05-23 Thread Felipe Contreras
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()

2021-05-23 Thread Felipe Contreras
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

2021-05-27 Thread Felipe Contreras
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

2021-06-03 Thread Felipe Contreras
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

2021-06-03 Thread Felipe Contreras
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

2021-06-03 Thread Felipe Contreras
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

2021-06-03 Thread Felipe Contreras
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

2021-06-03 Thread Felipe Contreras
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

2021-06-03 Thread Felipe Contreras
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?

2021-06-04 Thread Felipe Contreras
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


<    1   2   3   4   5   6   7   >