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).
Using the rb_data_type_t data we can call the correct notmuch destroy
function.
Therefore this:
ret = ((notmuch_status_t (*)(void *)) type->data) (nm_object);
Is effectively the same as this:
ret = notmuch_database_destroy (database);
The advantage of doing it this way is that much less code is necesary
since each rb_data_type_t has the corresponding destroy function stored
in it.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Virtually the whole ruby core moved from RData to RTypeData, let's do so
ourselves too.
Basically the information typically passed through Data_Wrap_Struct is
now stored in a struct rb_data_type_t (mark and free functions). This
has the advantage that more information can be easily added, like the
name of the type, a custom data ponter, and more.
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).
#define Check_TypedStruct(v, t) \
rb_check_typeddata(RBIMPL_CAST((VALUE)(v)), (t))
We can use rb_check_typeddata directly, just like we use rb_data_object_get
directly.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
This makes the code more maintainable and will help in further patches.
No functional changes.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
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 <felipe.contreras@gmail.com>
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)))
We can use rb_data_object_get directly, and this way we don't need to
pass the type, which is unnecessary information.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
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 <felipe.contreras@gmail.com>
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 <felipe.contreras@gmail.com>
init.c:214:5: warning: ‘rb_cData’ is deprecated: by: rb_cObject. Will be removed in 3.1. [-Wdeprecated-declarations]
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
This is the last bit of "python" left in the notmuch codebase.
https://www.python.org/dev/peps/pep-0394/#recommendation encourages
"third-party distributors" to use more-specific shebang lines. I'm
not certain that the notmuch project itself is a "third-party
contributor" but I think this is a safe way to encourage people to use
python3 when they're developing notmuch.
We already have python3 explicitly elsewhere in the codebase for
developers (in nmbug).
Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
This will allow client code to provide more meaningful diagnostics. In
particular it will enable "notmuch new" to continue suggsting the user
run "notmuch setup" to create a config after "notmuch new" is
transitioned to the new configuration framework.
A typo in Database._create_query lost the exclude_tag names during the
string to utf-8 conversion.
Amended by DB: fixed patch format and updated commit message.
Building Notmuch on macOS is known to cause problems because the Notmuch
distribution archive contains two files named "version". These names
clash with the <version> header as defined in C++20. Therefore, the
existing naming will likely become a problem on other platforms as well,
once compilers adopt the new standard.
Signed-off-by: Ralph Seichter <github@seichter.de>
Amended-by: db s/keyword/header/ in commit message.
Use `makefile-gmake-mode' instead of `makefile-mode' because the
former also highlights ifdef et al. while the latter does not.
"./Makefile.global" and one "Makefile.local" failed to specify any
major mode at all but doing so is necessary because Emacs does not
automatically figure out that these are Makefiles (of any flavor).
Since it is possible to use an atomic context to abort a number of
changes support this usage. Because the only way to actually abort
the transaction is to close the database this must also do so.
Amended by db: Note the limitation requiring close is a limitation of
the underlying notmuch API, which should be fixed in a future notmuch
release.
This reverses the logic of StandaloneMessage to instead create a
OwnedMessage. Only the Thread class allows retrieving messages more
then once so it can explicitly create such messages.
The added test fails with SIGABRT without the fix for the message
re-use in threads being present.
Any messages retrieved from a query - either directly via
search_messages() or indirectly via thread objects - are owned by that
query. Retrieving the same message (i.e. corresponding to the same
message ID / database object) several times will always yield the same
C object.
The caller is allowed to destroy message objects owned by a query before
the query itself - which can save memory for long-lived queries.
However, that message must then never be retrieved again from that
query.
The python-notmuch2 bindings will currently destroy every message object
in Message._destroy(), which will lead to an invalid free if the same
message is then retrieved again. E.g. the following python program leads
to libtalloc abort()ing:
import notmuch2
db = notmuch2.Database(mode = notmuch2.Database.MODE.READ_ONLY)
t = next(db.threads('*'))
msgs = list(zip(t.toplevel(), t.toplevel()))
msgs = list(zip(t.toplevel(), t.toplevel()))
Fix this issue by creating a subclass of Message, which is used for
"standalone" message which have to be freed by the caller. Message class
is then used only for messages descended from a query, which do not need
to be freed by the caller.
Even though we use collections.abc.Set which implements all these
methods under their operator names, the actual named variations of
these methods are shockingly missing. So let's add them manually.