From: David Bremner Date: Sat, 22 May 2021 12:34:55 +0000 (-0300) Subject: Merge branch 'release' X-Git-Tag: archive/debian/0.33_rc0-1~81 X-Git-Url: https://git.notmuchmail.org/git?a=commitdiff_plain;h=702635d5f61729b5d0453f73d8eaa4bc6eb50ed4;hp=3f4de98e7c8c70f9a86a4f899147126f79907bd9;p=notmuch Merge branch 'release' --- diff --git a/Makefile.local b/Makefile.local index bbb8f0b6..e12b94cd 100644 --- a/Makefile.local +++ b/Makefile.local @@ -231,6 +231,7 @@ notmuch_client_srcs = \ gmime-filter-reply.c \ hooks.c \ notmuch.c \ + notmuch-client-init.c \ notmuch-compact.c \ notmuch-config.c \ notmuch-count.c \ diff --git a/NEWS b/NEWS index e1fa2d73..c0ae6afe 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,11 @@ +Notmuch 0.33 (UNRELEASED) +========================= + +Vim +--- + +Respect excluded tags when showing a thread. + Notmuch 0.32.1 (2021-05-15) =========================== 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) diff --git a/bindings/ruby/database.c b/bindings/ruby/database.c index 416eb709..bb993d86 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, ¬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; } - Check_Type (self, T_DATA); + rb_check_typeddata (self, ¬much_rb_database_type); if (create) ret = notmuch_database_create (path, &database); else @@ -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; @@ -266,7 +262,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, ¬much_rb_directory_type, dir); return Qnil; } @@ -293,7 +289,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, ¬much_rb_message_type, message), (ret == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) ? Qtrue : Qfalse); } @@ -344,7 +340,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, ¬much_rb_message_type, message); return Qnil; } @@ -370,7 +366,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, ¬much_rb_message_type, message); return Qnil; } @@ -395,7 +391,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, ¬much_rb_tags_type, tags); } /* @@ -419,5 +415,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, ¬much_rb_query_type, query); } diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h index 48544ca2..9860ee17 100644 --- a/bindings/ruby/defs.h +++ b/bindings/ruby/defs.h @@ -55,77 +55,70 @@ extern ID ID_db_mode; # define RSTRING_PTR(v) (RSTRING((v))->ptr) #endif /* !defined (RSTRING_PTR) */ -#define Data_Get_Notmuch_Database(obj, 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)); \ +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; +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), (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_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_Wrap_Notmuch_Object(klass, type, ptr) \ + TypedData_Wrap_Struct ((klass), (type), (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_Database(obj, ptr) \ + Data_Get_Notmuch_Object ((obj), ¬much_rb_database_type, (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_Directory(obj, ptr) \ + Data_Get_Notmuch_Object ((obj), ¬much_rb_directory_type, (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_FileNames(obj, ptr) \ + Data_Get_Notmuch_Object ((obj), ¬much_rb_filenames_type, (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_Query(obj, ptr) \ + Data_Get_Notmuch_Object ((obj), ¬much_rb_query_type, (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_Threads(obj, ptr) \ + Data_Get_Notmuch_Object ((obj), ¬much_rb_threads_type, (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_Notmuch_Messages(obj, ptr) \ + Data_Get_Notmuch_Object ((obj), ¬much_rb_messages_type, (ptr)) -#define Data_Get_Notmuch_Tags(obj, ptr) \ - do { \ - Check_Type ((obj), T_DATA); \ - if (DATA_PTR ((obj)) == NULL) \ - rb_raise (rb_eRuntimeError, "tags destroyed"); \ - Data_Get_Struct ((obj), notmuch_tags_t, (ptr)); \ - } while (0) +#define Data_Get_Notmuch_Thread(obj, ptr) \ + Data_Get_Notmuch_Object ((obj), ¬much_rb_thread_type, (ptr)) + +#define Data_Get_Notmuch_Message(obj, ptr) \ + Data_Get_Notmuch_Object ((obj), ¬much_rb_message_type, (ptr)) + +#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); + + /* Call the corresponding notmuch_*_destroy function */ + ret = ((notmuch_status_t (*)(void *)) type->data) (nm_object); + DATA_PTR (rb_object) = NULL; + + return ret; +} /* status.c */ void diff --git a/bindings/ruby/directory.c b/bindings/ruby/directory.c index 0f37b391..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_Struct (self, notmuch_directory_t, dir); - - notmuch_directory_destroy (dir); - DATA_PTR (self) = NULL; + notmuch_rb_object_destroy (self, ¬much_rb_directory_type); return Qnil; } @@ -92,7 +87,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, ¬much_rb_filenames_type, fnames); } /* @@ -111,5 +106,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, ¬much_rb_filenames_type, fnames); } 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 819fd1e3..62515eca 100644 --- a/bindings/ruby/init.c +++ b/bindings/ruby/init.c @@ -46,6 +46,27 @@ 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", +}; + +#define define_type(id) \ + 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); +define_type (directory); +define_type (filenames); +define_type (query); +define_type (threads); +define_type (thread); +define_type (messages); +define_type (message); +define_type (tags); + /* * Document-module: Notmuch * diff --git a/bindings/ruby/message.c b/bindings/ruby/message.c index 6ea82afa..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; } @@ -89,7 +84,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, ¬much_rb_messages_type, messages); } /* @@ -125,7 +120,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, ¬much_rb_filenames_type, fnames); } /* @@ -226,7 +221,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); + return Data_Wrap_Notmuch_Object (notmuch_rb_cTags, ¬much_rb_tags_type, tags); } /* diff --git a/bindings/ruby/messages.c b/bindings/ruby/messages.c index a337feeb..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; } @@ -53,7 +48,7 @@ notmuch_rb_messages_each (VALUE self) for (; notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { message = notmuch_messages_get (messages); - rb_yield (Data_Wrap_Struct (notmuch_rb_cMessage, NULL, NULL, message)); + rb_yield (Data_Wrap_Notmuch_Object (notmuch_rb_cMessage, ¬much_rb_message_type, message)); } return self; @@ -76,5 +71,5 @@ notmuch_rb_messages_collect_tags (VALUE self) if (!tags) rb_raise (notmuch_rb_eMemoryError, "Out of memory"); - return Data_Wrap_Struct (notmuch_rb_cTags, NULL, NULL, tags); + return Data_Wrap_Notmuch_Object (notmuch_rb_cTags, ¬much_rb_tags_type, tags); } diff --git a/bindings/ruby/query.c b/bindings/ruby/query.c index 8b46d700..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; } @@ -142,7 +137,7 @@ notmuch_rb_query_search_threads (VALUE self) if (status) notmuch_rb_status_raise (status); - return Data_Wrap_Struct (notmuch_rb_cThreads, NULL, NULL, threads); + return Data_Wrap_Notmuch_Object (notmuch_rb_cThreads, ¬much_rb_threads_type, threads); } /* @@ -163,7 +158,7 @@ notmuch_rb_query_search_messages (VALUE self) if (status) notmuch_rb_status_raise (status); - return Data_Wrap_Struct (notmuch_rb_cMessages, NULL, NULL, messages); + return Data_Wrap_Notmuch_Object (notmuch_rb_cMessages, ¬much_rb_messages_type, messages); } /* 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 (self) = NULL; + notmuch_rb_object_destroy (self, ¬much_rb_tags_type); return Qnil; } diff --git a/bindings/ruby/thread.c b/bindings/ruby/thread.c index 9b295981..7cb2a3dc 100644 --- a/bindings/ruby/thread.c +++ b/bindings/ruby/thread.c @@ -28,12 +28,7 @@ VALUE notmuch_rb_thread_destroy (VALUE self) { - notmuch_thread_t *thread; - - Data_Get_Notmuch_Thread (self, thread); - - notmuch_thread_destroy (thread); - DATA_PTR (self) = NULL; + notmuch_rb_object_destroy (self, ¬much_rb_thread_type); return Qnil; } @@ -88,7 +83,7 @@ notmuch_rb_thread_get_toplevel_messages (VALUE self) if (!messages) rb_raise (notmuch_rb_eMemoryError, "Out of memory"); - return Data_Wrap_Struct (notmuch_rb_cMessages, NULL, NULL, messages); + return Data_Wrap_Notmuch_Object (notmuch_rb_cMessages, ¬much_rb_messages_type, messages); } /* @@ -108,7 +103,7 @@ notmuch_rb_thread_get_messages (VALUE self) if (!messages) rb_raise (notmuch_rb_eMemoryError, "Out of memory"); - return Data_Wrap_Struct (notmuch_rb_cMessages, NULL, NULL, messages); + return Data_Wrap_Notmuch_Object (notmuch_rb_cMessages, ¬much_rb_messages_type, messages); } /* @@ -209,5 +204,5 @@ notmuch_rb_thread_get_tags (VALUE self) if (!tags) rb_raise (notmuch_rb_eMemoryError, "Out of memory"); - return Data_Wrap_Struct (notmuch_rb_cTags, NULL, NULL, tags); + return Data_Wrap_Notmuch_Object (notmuch_rb_cTags, ¬much_rb_tags_type, tags); } diff --git a/bindings/ruby/threads.c b/bindings/ruby/threads.c index ed403a8f..50280260 100644 --- a/bindings/ruby/threads.c +++ b/bindings/ruby/threads.c @@ -28,12 +28,7 @@ VALUE notmuch_rb_threads_destroy (VALUE self) { - notmuch_threads_t *threads; - - Data_Get_Struct (self, notmuch_threads_t, threads); - - notmuch_threads_destroy (threads); - DATA_PTR (self) = NULL; + notmuch_rb_object_destroy (self, ¬much_rb_threads_type); return Qnil; } @@ -53,7 +48,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 (Data_Wrap_Notmuch_Object (notmuch_rb_cThread, ¬much_rb_thread_type, thread)); } return self; diff --git a/gmime-filter-reply.c b/gmime-filter-reply.c index 2b067669..35349cc8 100644 --- a/gmime-filter-reply.c +++ b/gmime-filter-reply.c @@ -43,29 +43,31 @@ static void filter_reset (GMimeFilter *filter); static GMimeFilterClass *parent_class = NULL; +static GType type = 0; +static const GTypeInfo info = { + .class_size = sizeof (GMimeFilterReplyClass), + .base_init = NULL, + .base_finalize = NULL, + .class_init = (GClassInitFunc) g_mime_filter_reply_class_init, + .class_finalize = NULL, + .class_data = NULL, + .instance_size = sizeof (GMimeFilterReply), + .n_preallocs = 0, + .instance_init = (GInstanceInitFunc) g_mime_filter_reply_init, + .value_table = NULL, +}; + + +void +g_mime_filter_reply_module_init (void) +{ + type = g_type_register_static (GMIME_TYPE_FILTER, "GMimeFilterReply", &info, (GTypeFlags) 0); + parent_class = (GMimeFilterClass *) g_type_class_ref (GMIME_TYPE_FILTER); +} GType g_mime_filter_reply_get_type (void) { - static GType type = 0; - - if (! type) { - static const GTypeInfo info = { - .class_size = sizeof (GMimeFilterReplyClass), - .base_init = NULL, - .base_finalize = NULL, - .class_init = (GClassInitFunc) g_mime_filter_reply_class_init, - .class_finalize = NULL, - .class_data = NULL, - .instance_size = sizeof (GMimeFilterReply), - .n_preallocs = 0, - .instance_init = (GInstanceInitFunc) g_mime_filter_reply_init, - .value_table = NULL, - }; - - type = g_type_register_static (GMIME_TYPE_FILTER, "GMimeFilterReply", &info, (GTypeFlags) 0); - } - return type; } @@ -76,8 +78,6 @@ g_mime_filter_reply_class_init (GMimeFilterReplyClass *klass, unused (void *clas GObjectClass *object_class = G_OBJECT_CLASS (klass); GMimeFilterClass *filter_class = GMIME_FILTER_CLASS (klass); - parent_class = (GMimeFilterClass *) g_type_class_ref (GMIME_TYPE_FILTER); - object_class->finalize = g_mime_filter_reply_finalize; filter_class->copy = filter_copy; diff --git a/gmime-filter-reply.h b/gmime-filter-reply.h index 7cdefcd1..988fe2d6 100644 --- a/gmime-filter-reply.h +++ b/gmime-filter-reply.h @@ -21,6 +21,8 @@ #include +void g_mime_filter_reply_module_init (void); + G_BEGIN_DECLS #define GMIME_TYPE_FILTER_REPLY (g_mime_filter_reply_get_type ()) diff --git a/lib/Makefile.local b/lib/Makefile.local index 01cbb3f2..e2d4b91d 100644 --- a/lib/Makefile.local +++ b/lib/Makefile.local @@ -62,7 +62,8 @@ libnotmuch_cxx_srcs = \ $(dir)/thread-fp.cc \ $(dir)/features.cc \ $(dir)/prefix.cc \ - $(dir)/open.cc + $(dir)/open.cc \ + $(dir)/init.cc libnotmuch_modules := $(libnotmuch_c_srcs:.c=.o) $(libnotmuch_cxx_srcs:.cc=.o) diff --git a/lib/add-message.cc b/lib/add-message.cc index d6e5e73d..b16748fd 100644 --- a/lib/add-message.cc +++ b/lib/add-message.cc @@ -40,17 +40,14 @@ parse_references (void *ctx, static const char * _notmuch_database_generate_thread_id (notmuch_database_t *notmuch) { - /* 16 bytes (+ terminator) for hexadecimal representation of - * a 64-bit integer. */ - static char thread_id[17]; notmuch->last_thread_id++; - sprintf (thread_id, "%016" PRIx64, notmuch->last_thread_id); + sprintf (notmuch->thread_id_str, "%016" PRIx64, notmuch->last_thread_id); - notmuch->writable_xapian_db->set_metadata ("last_thread_id", thread_id); + notmuch->writable_xapian_db->set_metadata ("last_thread_id", notmuch->thread_id_str); - return thread_id; + return notmuch->thread_id_str; } static char * diff --git a/lib/database-private.h b/lib/database-private.h index 0d12ec1e..1a73dacc 100644 --- a/lib/database-private.h +++ b/lib/database-private.h @@ -206,6 +206,10 @@ struct _notmuch_database { enum _notmuch_features features; unsigned int last_doc_id; + + /* 16 bytes (+ terminator) for hexadecimal representation of + * a 64-bit integer. */ + char thread_id_str[17]; uint64_t last_thread_id; /* error reporting; this value persists only until the diff --git a/lib/index.cc b/lib/index.cc index 55c8372e..728bfb22 100644 --- a/lib/index.cc +++ b/lib/index.cc @@ -148,8 +148,6 @@ notmuch_filter_discard_non_term_class_init (NotmuchFilterDiscardNonTermClass *kl GObjectClass *object_class = G_OBJECT_CLASS (klass); GMimeFilterClass *filter_class = GMIME_FILTER_CLASS (klass); - parent_class = (GMimeFilterClass *) g_type_class_ref (GMIME_TYPE_FILTER); - object_class->finalize = notmuch_filter_discard_non_term_finalize; filter_class->copy = filter_copy; @@ -240,30 +238,33 @@ filter_reset (GMimeFilter *gmime_filter) * * Returns: a new #NotmuchFilterDiscardNonTerm filter. **/ +static GType type = 0; + +static const GTypeInfo info = { + .class_size = sizeof (NotmuchFilterDiscardNonTermClass), + .base_init = NULL, + .base_finalize = NULL, + .class_init = (GClassInitFunc) notmuch_filter_discard_non_term_class_init, + .class_finalize = NULL, + .class_data = NULL, + .instance_size = sizeof (NotmuchFilterDiscardNonTerm), + .n_preallocs = 0, + .instance_init = NULL, + .value_table = NULL, +}; + +void +_notmuch_filter_init () { + type = g_type_register_static (GMIME_TYPE_FILTER, "NotmuchFilterDiscardNonTerm", &info, + (GTypeFlags) 0); + parent_class = (GMimeFilterClass *) g_type_class_ref (GMIME_TYPE_FILTER); +} + static GMimeFilter * notmuch_filter_discard_non_term_new (GMimeContentType *content_type) { - static GType type = 0; NotmuchFilterDiscardNonTerm *filter; - if (! type) { - static const GTypeInfo info = { - .class_size = sizeof (NotmuchFilterDiscardNonTermClass), - .base_init = NULL, - .base_finalize = NULL, - .class_init = (GClassInitFunc) notmuch_filter_discard_non_term_class_init, - .class_finalize = NULL, - .class_data = NULL, - .instance_size = sizeof (NotmuchFilterDiscardNonTerm), - .n_preallocs = 0, - .instance_init = NULL, - .value_table = NULL, - }; - - type = g_type_register_static (GMIME_TYPE_FILTER, "NotmuchFilterDiscardNonTerm", &info, - (GTypeFlags) 0); - } - filter = (NotmuchFilterDiscardNonTerm *) g_object_new (type, NULL); filter->content_type = content_type; filter->state = 0; diff --git a/lib/init.cc b/lib/init.cc new file mode 100644 index 00000000..cf29200f --- /dev/null +++ b/lib/init.cc @@ -0,0 +1,21 @@ +#include "notmuch-private.h" + +#include + +static void do_init () +{ + /* Initialize the GLib type system and threads */ +#if ! GLIB_CHECK_VERSION (2, 35, 1) + g_type_init (); +#endif + + g_mime_init (); + _notmuch_filter_init (); +} + +void +_notmuch_init () +{ + static std::once_flag initialized; + std::call_once (initialized, do_init); +} diff --git a/lib/message-file.c b/lib/message-file.c index 9e9b387f..647ccf3a 100644 --- a/lib/message-file.c +++ b/lib/message-file.c @@ -141,7 +141,6 @@ _notmuch_message_file_parse (notmuch_message_file_t *message) { GMimeParser *parser; notmuch_status_t status = NOTMUCH_STATUS_SUCCESS; - static int initialized = 0; bool is_mbox; if (message->message) @@ -149,10 +148,7 @@ _notmuch_message_file_parse (notmuch_message_file_t *message) is_mbox = _is_mbox (message->stream); - if (! initialized) { - g_mime_init (); - initialized = 1; - } + _notmuch_init (); message->headers = g_hash_table_new_full (strcase_hash, strcase_equal, free, g_free); diff --git a/lib/message.cc b/lib/message.cc index 42d56acb..7af6ab82 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -68,7 +68,7 @@ struct maildir_flag_tag { }; /* ASCII ordered table of Maildir flags and associated tags */ -static struct maildir_flag_tag flag2tag[] = { +static const struct maildir_flag_tag flag2tag[] = { { 'D', "draft", false }, { 'F', "flagged", false }, { 'P', "passed", false }, diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index 10b1b024..093c29b1 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -469,11 +469,18 @@ _notmuch_database_link_message_to_parents (notmuch_database_t *notmuch, const char **thread_id); /* index.cc */ +void +_notmuch_filter_init (); + notmuch_status_t _notmuch_message_index_file (notmuch_message_t *message, notmuch_indexopts_t *indexopts, notmuch_message_file_t *message_file); +/* init.cc */ +void +_notmuch_init (); + /* messages.c */ typedef struct _notmuch_message_node { diff --git a/lib/open.cc b/lib/open.cc index 3325e725..1ca69665 100644 --- a/lib/open.cc +++ b/lib/open.cc @@ -324,24 +324,6 @@ _set_database_path (notmuch_database_t *notmuch, _notmuch_config_cache (notmuch, NOTMUCH_CONFIG_DATABASE_PATH, path); } -static void -_init_libs () -{ - - static int initialized = 0; - - /* Initialize the GLib type system and threads */ -#if ! GLIB_CHECK_VERSION (2, 35, 1) - g_type_init (); -#endif - - /* Initialize gmime */ - if (! initialized) { - g_mime_init (); - initialized = 1; - } -} - static void _load_database_state (notmuch_database_t *notmuch) { @@ -515,7 +497,7 @@ notmuch_database_open_with_config (const char *database_path, GKeyFile *key_file = NULL; bool split = false; - _init_libs (); + _notmuch_init (); notmuch = _alloc_notmuch (); if (! notmuch) { @@ -612,7 +594,7 @@ notmuch_database_create_with_config (const char *database_path, int err; bool split = false; - _init_libs (); + _notmuch_init (); notmuch = _alloc_notmuch (); if (! notmuch) { @@ -808,7 +790,7 @@ notmuch_database_load_config (const char *database_path, GKeyFile *key_file = NULL; bool split = false; - _init_libs (); + _notmuch_init (); notmuch = _alloc_notmuch (); if (! notmuch) { diff --git a/notmuch-client-init.c b/notmuch-client-init.c new file mode 100644 index 00000000..60db6ba4 --- /dev/null +++ b/notmuch-client-init.c @@ -0,0 +1,18 @@ +#include "notmuch-client.h" +#include "gmime-filter-reply.h" + +/* Caller is responsible for only calling this once */ + +void +notmuch_client_init (void) +{ +#if ! GLIB_CHECK_VERSION (2, 35, 1) + g_type_init (); +#endif + + g_mime_init (); + + g_mime_filter_reply_module_init (); + + talloc_enable_null_tracking (); +} diff --git a/notmuch-client.h b/notmuch-client.h index 270553ad..8227fea4 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -250,6 +250,10 @@ json_quote_chararray (const void *ctx, const char *str, const size_t len); char * json_quote_str (const void *ctx, const char *str); +/* notmuch-client-init.c */ + +void notmuch_client_init (void); + /* notmuch-config.c */ typedef enum { diff --git a/notmuch-config.c b/notmuch-config.c index d9390c4d..3430a3d3 100644 --- a/notmuch-config.c +++ b/notmuch-config.c @@ -32,7 +32,7 @@ static const char toplevel_config_comment[] = "\n" " For more information about notmuch, see https://notmuchmail.org"; -struct config_group { +static const struct config_group { const char *group_name; const char *comment; } group_comment_table [] = { @@ -512,14 +512,14 @@ typedef struct config_key { bool (*validate)(const char *); } config_key_info_t; -static struct config_key +static const struct config_key config_key_table[] = { { "index.decrypt", false, NULL }, { "index.header.", true, validate_field_name }, { "query.", true, NULL }, }; -static config_key_info_t * +static const config_key_info_t * _config_key_info (const char *item) { for (size_t i = 0; i < ARRAY_SIZE (config_key_table); i++) { @@ -583,7 +583,7 @@ notmuch_config_command_set (notmuch_database_t *notmuch, int argc, char *argv[]) { char *group, *key; - config_key_info_t *key_info; + const config_key_info_t *key_info; notmuch_conffile_t *config; bool update_database = false; int opt_index, ret; diff --git a/notmuch-insert.c b/notmuch-insert.c index 00c00468..e3d87e4a 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -34,7 +34,7 @@ static volatile sig_atomic_t interrupted; static void handle_sigint (unused (int sig)) { - static char msg[] = "Stopping... \n"; + static const char msg[] = "Stopping... \n"; /* This write is "opportunistic", so it's okay to ignore the * result. It is not required for correctness, and if it does diff --git a/notmuch-new.c b/notmuch-new.c index 993359d6..1ee498fa 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -81,7 +81,7 @@ static volatile sig_atomic_t interrupted; static void handle_sigint (unused (int sig)) { - static char msg[] = "Stopping... \n"; + static const char msg[] = "Stopping... \n"; /* This write is "opportunistic", so it's okay to ignore the * result. It is not required for correctness, and if it does @@ -403,8 +403,11 @@ add_file (notmuch_database_t *notmuch, const char *filename, break; /* Non-fatal issues (go on to next file). */ case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID: - if (state->synchronize_flags) - notmuch_message_maildir_flags_to_tags (message); + if (state->synchronize_flags) { + status = notmuch_message_maildir_flags_to_tags (message); + if (print_status_message ("add_file", message, status)) + goto DONE; + } break; case NOTMUCH_STATUS_FILE_NOT_EMAIL: fprintf (stderr, "Note: Ignoring non-mail file: %s\n", filename); diff --git a/notmuch-reindex.c b/notmuch-reindex.c index 8904c1f4..a7380a4b 100644 --- a/notmuch-reindex.c +++ b/notmuch-reindex.c @@ -26,7 +26,7 @@ static volatile sig_atomic_t interrupted; static void handle_sigint (unused (int sig)) { - static char msg[] = "Stopping... \n"; + static const char msg[] = "Stopping... \n"; /* This write is "opportunistic", so it's okay to ignore the * result. It is not required for correctness, and if it does diff --git a/notmuch-tag.c b/notmuch-tag.c index 667a75d6..de428c8e 100644 --- a/notmuch-tag.c +++ b/notmuch-tag.c @@ -27,7 +27,7 @@ static volatile sig_atomic_t interrupted; static void handle_sigint (unused (int sig)) { - static char msg[] = "Stopping... \n"; + static const char msg[] = "Stopping... \n"; /* This write is "opportunistic", so it's okay to ignore the * result. It is not required for correctness, and if it does diff --git a/notmuch.c b/notmuch.c index 2429999c..d0a94fc2 100644 --- a/notmuch.c +++ b/notmuch.c @@ -139,7 +139,7 @@ notmuch_process_shared_indexing_options (notmuch_database_t *notmuch) } -static command_t commands[] = { +static const command_t commands[] = { { NULL, notmuch_command, NOTMUCH_COMMAND_CONFIG_CREATE | NOTMUCH_COMMAND_CONFIG_LOAD, "Notmuch main command." }, { "setup", notmuch_setup_command, NOTMUCH_COMMAND_CONFIG_CREATE | NOTMUCH_COMMAND_CONFIG_LOAD, @@ -189,7 +189,7 @@ typedef struct help_topic { const char *summary; } help_topic_t; -static help_topic_t help_topics[] = { +static const help_topic_t help_topics[] = { { "search-terms", "Common search term syntax." }, { "hooks", @@ -198,7 +198,7 @@ static help_topic_t help_topics[] = { "Message property conventions and documentation." }, }; -static command_t * +static const command_t * find_command (const char *name) { size_t i; @@ -216,8 +216,8 @@ int notmuch_format_version; static void usage (FILE *out) { - command_t *command; - help_topic_t *topic; + const command_t *command; + const help_topic_t *topic; unsigned int i; fprintf (out, @@ -308,8 +308,8 @@ exec_man (const char *page) static int _help_for (const char *topic_name) { - command_t *command; - help_topic_t *topic; + const command_t *command; + const help_topic_t *topic; unsigned int i; if (! topic_name) { @@ -452,7 +452,7 @@ main (int argc, char *argv[]) void *local; char *talloc_report; const char *command_name = NULL; - command_t *command; + const command_t *command; const char *config_file_name = NULL; notmuch_database_t *notmuch = NULL; int opt_index; @@ -464,15 +464,10 @@ main (int argc, char *argv[]) { } }; - talloc_enable_null_tracking (); + notmuch_client_init (); local = talloc_new (NULL); - g_mime_init (); -#if ! GLIB_CHECK_VERSION (2, 35, 1) - g_type_init (); -#endif - /* Globally default to the current output format version. */ notmuch_format_version = NOTMUCH_FORMAT_CUR; diff --git a/performance-test/README b/performance-test/README index fbc61028..59b37b1b 100644 --- a/performance-test/README +++ b/performance-test/README @@ -16,6 +16,7 @@ In addition to having notmuch, you need: - xz. Some speedup can be gotten by installing "pixz", but this is probably only worthwhile if you are debugging the tests. - valgrind (for the memory tests) +- perf (optional, for more fine-grained timing) Getting set up to run tests: ---------------------------- @@ -56,11 +57,24 @@ supports the following arguments --small / --medium / --large Choose corpus size. --debug Enable debugging. In particular don't delete - temporary directories. + temporary directories. +--perf Run perf record in place of /usr/bin/time. Perf output can be + found in a log directory. +--call-graph {fp,lbr,dwarf} Call graph option for perf record. Default is 'lbr'. When using the make targets, you can pass arguments to all test scripts by defining the make variable OPTIONS. +Log Directory +------------- + +The memory tests, and the time tests when option '--perf' is given +save their output in a directory named as follows + + log.$test_name-$corpus_size-$timestamp + +These directories are removed by "make clean". + Writing tests ------------- diff --git a/performance-test/perf-test-lib.sh b/performance-test/perf-test-lib.sh index b70288cc..e7c502b6 100644 --- a/performance-test/perf-test-lib.sh +++ b/performance-test/perf-test-lib.sh @@ -1,6 +1,9 @@ . $(dirname "$0")/version.sh || exit 1 +debug="" corpus_size=large +perf_callgraph=lbr +use_perf=0 while test "$#" -ne 0 do @@ -9,6 +12,15 @@ do debug=t; shift ;; + -p|--perf) + use_perf=1; + shift + ;; + -c|--call-graph) + shift + perf_callgraph=$1 + shift + ;; -s|--small) corpus_size=small; shift @@ -127,10 +139,20 @@ notmuch_new_with_cache () fi } +make_log_dir () { + local timestamp=$(date +%Y%m%dT%H%M%S) + log_dir=${TEST_DIRECTORY}/log.$(basename $0)-$corpus_size-${timestamp} + mkdir -p "${log_dir}" +} + time_start () { add_email_corpus + if [[ "$use_perf" = 1 ]]; then + make_log_dir + fi + print_header notmuch_new_with_cache time_run @@ -140,9 +162,7 @@ memory_start () { add_email_corpus - local timestamp=$(date +%Y%m%dT%H%M%S) - log_dir="${TEST_DIRECTORY}/log.$(basename $0)-$corpus_size-${timestamp}" - mkdir -p ${log_dir} + make_log_dir notmuch_new_with_cache memory_run } @@ -193,7 +213,13 @@ time_run () printf " %-22s" "$1" test_count=$(($test_count+1)) if test "$verbose" != "t"; then exec 4>test.output 3>&4; fi - if ! eval >&3 "/usr/bin/time -f '%e\t%U\t%S\t%M\t%I/%O' $2" ; then + if [[ "$use_perf" = 1 ]]; then + command_str="perf record --call-graph=${perf_callgraph} -o ${log_dir}/${test_count}.perf $2" + else + command_str="/usr/bin/time -f '%e\t%U\t%S\t%M\t%I/%O' $2" + fi + + if ! eval >&3 "$command_str" ; then test_failure=$(($test_failure + 1)) return 1 fi 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 -0000\"" \ 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/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 -0000\"" "[bcc]=\"test_suite+bcc@notmuchmail.org\"" "[reply-to]=\"test_suite+replyto@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 -0000\"" "[bcc]=\"test_suite+bcc@notmuchmail.org\"" "[reply-to]=\"test_suite+replyto@notmuchmail.org\"" "[body]=\"sexp-show-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/T350-crypto.sh b/test/T350-crypto.sh index 0aada4df..4508c984 100755 --- a/test/T350-crypto.sh +++ b/test/T350-crypto.sh @@ -6,9 +6,11 @@ test_description='PGP/MIME signature verification and decryption' . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 ################################################## +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..69bdcfac 100755 --- a/test/T355-smime.sh +++ b/test/T355-smime.sh @@ -2,7 +2,9 @@ test_description='S/MIME signature verification and decryption' . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.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 1951ef78..0d30e566 100755 --- a/test/T357-index-decryption.sh +++ b/test/T357-index-decryption.sh @@ -4,9 +4,11 @@ test_description='indexing decrypted mail' . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 ################################################## +test_require_emacs add_gnupg_home # create a test encrypted message diff --git a/test/T358-emacs-protected-headers.sh b/test/T358-emacs-protected-headers.sh index bca78531..b25d7ea7 100755 --- a/test/T358-emacs-protected-headers.sh +++ b/test/T358-emacs-protected-headers.sh @@ -2,8 +2,10 @@ test_description="protected headers in emacs interface" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 # testing protected headers with emacs +test_require_emacs add_gnupg_home add_email_corpus protected-headers diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index a0b76eb8..597330d3 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -8,95 +8,61 @@ fi add_email_corpus +test_ruby() { + ( + cat <<-EOF + require 'notmuch' + db = Notmuch::Database.new('$MAIL_DIR') + 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 > EXPECTED 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 - print t.thread_id, "\n" +q = db.query('tag:inbox') +q.sort = Notmuch::SORT_OLDEST_FIRST +q.search_threads.each do |t| + puts 'thread:%s' % t.thread_id 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 > EXPECTED 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 - print m.message_id, "\n" +q = db.query('tag:inbox') +q.sort = Notmuch::SORT_OLDEST_FIRST +q.search_messages.each do |m| + puts 'id:%s' % m.message_id 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 nil > EXPECTED 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) +p db.find_message_by_filename('i-dont-exist') EOF -test_expect_equal "$(cat OUTPUT)" "true" test_begin_subtest "count messages" +notmuch count --output=messages tag:inbox > EXPECTED 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" +puts db.query('tag:inbox').count_messages() 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" -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" +puts db.query('tag:inbox').count_threads() 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" -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" +db.all_tags.each do |tag| + puts tag end EOF -notmuch search --output=tags '*' > EXPECTED -test_expect_equal_file EXPECTED OUTPUT test_done diff --git a/test/T420-emacs-test-functions.sh b/test/T420-emacs-test-functions.sh index bfc10be3..22e4f01e 100755 --- a/test/T420-emacs-test-functions.sh +++ b/test/T420-emacs-test-functions.sh @@ -2,6 +2,7 @@ test_description="emacs test function sanity" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 test_begin_subtest "emacs test function sanity" test_emacs_expect_t 't' diff --git a/test/T430-emacs-address-cleaning.sh b/test/T430-emacs-address-cleaning.sh index 02d3b411..640bff3f 100755 --- a/test/T430-emacs-address-cleaning.sh +++ b/test/T430-emacs-address-cleaning.sh @@ -2,6 +2,9 @@ test_description="emacs address cleaning" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 + +test_require_emacs test_begin_subtest "notmuch-test-address-clean part 1" test_emacs_expect_t '(notmuch-test-address-cleaning-1)' diff --git a/test/T440-emacs-hello.sh b/test/T440-emacs-hello.sh index d23c1fca..642aa3cc 100755 --- a/test/T440-emacs-hello.sh +++ b/test/T440-emacs-hello.sh @@ -2,9 +2,11 @@ test_description="emacs notmuch-hello view" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 EXPECTED=$NOTMUCH_SRCDIR/test/emacs.expected-output +test_require_emacs add_email_corpus test_begin_subtest "User-defined section with inbox tag" diff --git a/test/T450-emacs-show.sh b/test/T450-emacs-show.sh index cca56ca3..e58124d4 100755 --- a/test/T450-emacs-show.sh +++ b/test/T450-emacs-show.sh @@ -2,9 +2,11 @@ test_description="emacs notmuch-show view" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 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/T455-emacs-charsets.sh b/test/T455-emacs-charsets.sh index cb1297ca..a0f4dc24 100755 --- a/test/T455-emacs-charsets.sh +++ b/test/T455-emacs-charsets.sh @@ -2,11 +2,14 @@ test_description="emacs notmuch-show charset handling" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 UTF8_YEN=$'\xef\xbf\xa5' BIG5_YEN=$'\xa2\x44' +test_require_emacs + # Add four messages with unusual encoding requirements: # # 1) text/plain in quoted-printable big5 diff --git a/test/T460-emacs-tree.sh b/test/T460-emacs-tree.sh index cb2c90b8..dfc69049 100755 --- a/test/T460-emacs-tree.sh +++ b/test/T460-emacs-tree.sh @@ -2,9 +2,11 @@ test_description="emacs tree view interface" . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 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/T490-parse-time-string.sh b/test/T490-parse-time-string.sh index d1c70cfa..f89755ed 100755 --- a/test/T490-parse-time-string.sh +++ b/test/T490-parse-time-string.sh @@ -4,13 +4,11 @@ test_description="date/time parser module" # Sanity/smoke tests for the date/time parser independent of notmuch -_date () -{ +_date () { date -d "$*" +%s } -_parse_time () -{ +_parse_time () { ${TEST_DIRECTORY}/parse-time --format=%s "$*" } diff --git a/test/T510-thread-replies.sh b/test/T510-thread-replies.sh index 2859d29f..cdb4be44 100755 --- a/test/T510-thread-replies.sh +++ b/test/T510-thread-replies.sh @@ -10,6 +10,7 @@ test_description='test of proper handling of in-reply-to and references headers' # non-RFC-compliant headers' . $(dirname "$0")/test-lib.sh || exit 1 +. $(dirname "$0")/test-lib-emacs.sh || exit 1 test_begin_subtest "Use References when In-Reply-To is broken" add_message '[id]="foo@one.com"' \ 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 < /dev/null } diff --git a/test/test-lib-emacs.sh b/test/test-lib-emacs.sh new file mode 100644 index 00000000..dde32177 --- /dev/null +++ b/test/test-lib-emacs.sh @@ -0,0 +1,209 @@ +# +# Copyright (c) 2010-2020 Notmuch Developers +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see https://www.gnu.org/licenses/ . + +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 dtach || ret=1 + return $ret +} + +# Deliver a message with emacs and add it to the database +# +# Uses emacs to generate and deliver a message to the mail store. +# 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 () { + local subject body smtp_dummy_pid smtp_dummy_port + subject="$1" + body="$2" + shift 2 + # before we can send a message, we have to prepare the FCC maildir + mkdir -p "$MAIL_DIR"/sent/{cur,new,tmp} + # eval'ing smtp-dummy --background will set smtp_dummy_pid and -_port + smtp_dummy_pid= smtp_dummy_port= + eval `$TEST_DIRECTORY/smtp-dummy --background sent_message` + test -n "$smtp_dummy_pid" || return 1 + test -n "$smtp_dummy_port" || return 1 + + test_emacs \ + "(let ((message-send-mail-function 'message-smtpmail-send-it) + (mail-host-address \"example.com\") + (smtpmail-smtp-server \"localhost\") + (smtpmail-smtp-service \"${smtp_dummy_port}\")) + (notmuch-mua-mail) + (message-goto-to) + (insert \"test_suite@notmuchmail.org\nDate: 01 Jan 2000 12:00:00 -0000\") + (message-goto-subject) + (insert \"${subject}\") + (message-goto-body) + (insert \"${body}\") + $* + (notmuch-mua-send-and-exit))" + + # In case message was sent properly, client waits for confirmation + # before exiting and resuming control here; therefore making sure + # that server exits by sending (KILL) signal to it is safe. + kill -9 $smtp_dummy_pid + notmuch new >/dev/null +} + +# Pretend to deliver a message with emacs. Really save it to a file +# and add it to the database +# +# Uses emacs to generate and deliver a message to the mail store. +# 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. +# +# 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 () { + local nmn_args subject body + nmn_args='' + while [[ "$1" =~ ^-- ]]; do + nmn_args="$nmn_args $1" + shift + done + subject="$1" + body="$2" + shift 2 + # before we can send a message, we have to prepare the FCC maildir + mkdir -p "$MAIL_DIR"/sent/{cur,new,tmp} + + test_emacs \ + "(let ((message-send-mail-function (lambda () t)) + (mail-host-address \"example.com\")) + (notmuch-mua-mail) + (message-goto-to) + (insert \"test_suite@notmuchmail.org\nDate: 01 Jan 2000 12:00:00 -0000\") + (message-goto-subject) + (insert \"${subject}\") + (message-goto-body) + (insert \"${body}\") + $* + (let ((mml-secure-smime-sign-with-sender t) + (mml-secure-openpgp-sign-with-sender t)) + (notmuch-mua-send-and-exit)))" || return 1 + notmuch new $nmn_args >/dev/null +} + +test_emacs_expect_t () { + local result + test "$#" = 1 || + error "bug in the test script: not 1 parameter to test_emacs_expect_t" + if [ -z "$inside_subtest" ]; then + error "bug in the test script: test_emacs_expect_t without test_begin_subtest" + fi + + # Run the test. + if ! test_skip "$test_subtest_name" + then + test_emacs "(notmuch-test-run $1)" >/dev/null + + # Restore state after the test. + 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 ] + then + test_ok_ + else + test_failure_ "${result}" + fi + else + # Restore state after the (non) test. + exec 1>&6 2>&7 # Restore stdout and stderr + inside_subtest= + fi +} + +emacs_generate_script () { + # Construct a little test script here for the benefit of the user, + # (who can easily run "run_emacs" to get the same emacs environment + # for investigating any failures). + cat <"$TMP_DIRECTORY/run_emacs" +#!/bin/sh +export PATH=$PATH +export NOTMUCH_CONFIG=$NOTMUCH_CONFIG + +# Here's what we are using here: +# +# --quick Use minimal customization. This implies --no-init-file, +# --no-site-file and (emacs 24) --no-site-lisp +# +# --directory Ensure that the local elisp sources are found +# +# --load Force loading of notmuch.el and test-lib.el + +exec ${TEST_EMACS} --quick \ + --directory "$NOTMUCH_BUILDDIR/emacs" --load notmuch.el \ + --directory "$NOTMUCH_SRCDIR/test" --load test-lib.el \ + "\$@" +EOF + chmod a+x "$TMP_DIRECTORY/run_emacs" +} + +test_emacs () { + # test dependencies beforehand to avoid the waiting loop below + test_require_emacs || return + + if [ -z "$EMACS_SERVER" ]; then + emacs_tests="$NOTMUCH_SRCDIR/test/${this_test_bare}.el" + if [ -f "$emacs_tests" ]; then + load_emacs_tests="--eval '(load \"$emacs_tests\")'" + else + load_emacs_tests= + fi + server_name="notmuch-test-suite-$$" + # start a detached session with an emacs server + # user's TERM (or 'vt100' in case user's TERM is known dumb + # or unknown) is given to dtach which assumes a minimally + # VT100-compatible terminal -- and emacs inherits that + TERM=$SMART_TERM dtach -n "$TEST_TMPDIR/emacs-dtach-socket.$$" \ + sh -c "stty rows 24 cols 80; exec '$TMP_DIRECTORY/run_emacs' \ + --no-window-system \ + $load_emacs_tests \ + --eval '(setq server-name \"$server_name\")' \ + --eval '(server-start)' \ + --eval '(orphan-watchdog $$)'" || return + EMACS_SERVER="$server_name" + # wait until the emacs server is up + until test_emacs '()' >/dev/null 2>/dev/null; do + sleep 1 + done + fi + + # Clear test-output output file. Most Emacs tests end with a + # call to (test-output). If the test code fails with an + # exception before this call, the output file won't get + # updated. Since we don't want to compare against an output + # file from another test, so start out with an empty file. + rm -f OUTPUT + touch OUTPUT + + ${TEST_EMACSCLIENT} --socket-name="$EMACS_SERVER" --eval "(notmuch-test-progn $*)" +} + +emacs_generate_script diff --git a/test/test-lib.sh b/test/test-lib.sh index 4c9f2a21..89eb744d 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -112,9 +112,9 @@ unset ALTERNATE_EDITOR # for reproducibility 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 @@ -134,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; } @@ -267,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}" @@ -342,90 +340,6 @@ export GNUPGHOME="${TEST_TMPDIR}/gnupg" trap 'trap_exit' EXIT trap 'trap_signal' HUP INT TERM -# Deliver a message with emacs and add it to the database -# -# Uses emacs to generate and deliver a message to the mail store. -# 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 () -{ - local subject body smtp_dummy_pid smtp_dummy_port - subject="$1" - body="$2" - shift 2 - # before we can send a message, we have to prepare the FCC maildir - mkdir -p "$MAIL_DIR"/sent/{cur,new,tmp} - # eval'ing smtp-dummy --background will set smtp_dummy_pid and -_port - smtp_dummy_pid= smtp_dummy_port= - eval `$TEST_DIRECTORY/smtp-dummy --background sent_message` - test -n "$smtp_dummy_pid" || return 1 - test -n "$smtp_dummy_port" || return 1 - - test_emacs \ - "(let ((message-send-mail-function 'message-smtpmail-send-it) - (mail-host-address \"example.com\") - (smtpmail-smtp-server \"localhost\") - (smtpmail-smtp-service \"${smtp_dummy_port}\")) - (notmuch-mua-mail) - (message-goto-to) - (insert \"test_suite@notmuchmail.org\nDate: 01 Jan 2000 12:00:00 -0000\") - (message-goto-subject) - (insert \"${subject}\") - (message-goto-body) - (insert \"${body}\") - $* - (notmuch-mua-send-and-exit))" - - # In case message was sent properly, client waits for confirmation - # before exiting and resuming control here; therefore making sure - # that server exits by sending (KILL) signal to it is safe. - kill -9 $smtp_dummy_pid - notmuch new >/dev/null -} - -# Pretend to deliver a message with emacs. Really save it to a file -# and add it to the database -# -# Uses emacs to generate and deliver a message to the mail store. -# 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. -# -# 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 () -{ - local nmn_args subject body - nmn_args='' - while [[ "$1" =~ ^-- ]]; do - nmn_args="$nmn_args $1" - shift - done - subject="$1" - body="$2" - shift 2 - # before we can send a message, we have to prepare the FCC maildir - mkdir -p "$MAIL_DIR"/sent/{cur,new,tmp} - - test_emacs \ - "(let ((message-send-mail-function (lambda () t)) - (mail-host-address \"example.com\")) - (notmuch-mua-mail) - (message-goto-to) - (insert \"test_suite@notmuchmail.org\nDate: 01 Jan 2000 12:00:00 -0000\") - (message-goto-subject) - (insert \"${subject}\") - (message-goto-body) - (insert \"${body}\") - $* - (let ((mml-secure-smime-sign-with-sender t) - (mml-secure-openpgp-sign-with-sender t)) - (notmuch-mua-send-and-exit)))" || return 1 - notmuch new $nmn_args >/dev/null -} - # Add an existing, fixed corpus of email to the database. # # $1 is the corpus dir under corpora to add, using "default" if unset. @@ -434,8 +348,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} @@ -444,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]}" @@ -465,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 @@ -492,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 @@ -574,51 +484,16 @@ test_json_nodes () { fi } -test_emacs_expect_t () { - local result - test "$#" = 1 || - error "bug in the test script: not 1 parameter to test_emacs_expect_t" - if [ -z "$inside_subtest" ]; then - error "bug in the test script: test_emacs_expect_t without test_begin_subtest" - fi - - # Run the test. - if ! test_skip "$test_subtest_name" - then - test_emacs "(notmuch-test-run $1)" >/dev/null - - # Restore state after the test. - exec 1>&6 2>&7 # Restore stdout and stderr - inside_subtest= - - # Report success/failure. - result=$(cat OUTPUT) - if [ "$result" = t ] - then - test_ok_ - else - test_failure_ "${result}" - fi - else - # Restore state after the (non) test. - exec 1>&6 2>&7 # Restore stdout and stderr - inside_subtest= - fi -} - -NOTMUCH_NEW () -{ +NOTMUCH_NEW () { notmuch new "${@}" | grep -v -E -e '^Processed [0-9]*( total)? file|Found [0-9]* total file' } -NOTMUCH_DUMP_TAGS () -{ +NOTMUCH_DUMP_TAGS () { # this relies on the default format being batch-tag, otherwise some tests will break notmuch dump --include=tags "${@}" | sed '/^#/d' | sort } -notmuch_drop_mail_headers () -{ +notmuch_drop_mail_headers () { $NOTMUCH_PYTHON -c ' import email, sys msg = email.message_from_file(sys.stdin) @@ -627,41 +502,34 @@ print(msg.as_string(False)) ' "$@" } -notmuch_exception_sanitize () -{ +notmuch_exception_sanitize () { perl -pe 's/(A Xapian exception occurred at .*[.]cc?):([0-9]*)/\1:XXX/' } -notmuch_search_sanitize () -{ +notmuch_search_sanitize () { perl -pe 's/("?thread"?: ?)("?)................("?)/\1\2XXX\3/' } -notmuch_search_files_sanitize () -{ +notmuch_search_files_sanitize () { notmuch_dir_sanitize } -notmuch_dir_sanitize () -{ +notmuch_dir_sanitize () { sed -e "s,$MAIL_DIR,MAIL_DIR," -e "s,${PWD},CWD,g" "$@" } NOTMUCH_SHOW_FILENAME_SQUELCH='s,filename:.*/mail,filename:/XXX/mail,' -notmuch_show_sanitize () -{ +notmuch_show_sanitize () { sed -e "$NOTMUCH_SHOW_FILENAME_SQUELCH" } -notmuch_show_sanitize_all () -{ +notmuch_show_sanitize_all () { sed \ -e 's| filename:.*| filename:XXXXX|' \ -e 's| id:[^ ]* | id:XXXXX |' | \ notmuch_date_sanitize } -notmuch_json_show_sanitize () -{ +notmuch_json_show_sanitize () { sed \ -e 's|"id": "[^"]*",|"id": "XXXXX",|g' \ -e 's|"Date": "Fri, 05 Jan 2001 [^"]*0000"|"Date": "GENERATED_DATE"|g' \ @@ -671,8 +539,7 @@ notmuch_json_show_sanitize () -e 's|"content-length": [1-9][0-9]*|"content-length": "NONZERO"|g' } -notmuch_emacs_error_sanitize () -{ +notmuch_emacs_error_sanitize () { local command command=$1 shift @@ -684,45 +551,44 @@ notmuch_emacs_error_sanitize () -e "s|^\(command: \)\{0,1\}/.*/$command|\1YYY/$command|" } -notmuch_date_sanitize () -{ +notmuch_date_sanitize () { sed \ -e 's/^Date: Fri, 05 Jan 2001 .*0000/Date: GENERATED_DATE/' } -notmuch_uuid_sanitize () -{ +notmuch_uuid_sanitize () { sed 's/[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}/UUID/g' } -notmuch_built_with_sanitize () -{ +notmuch_built_with_sanitize () { sed 's/^built_with[.]\(.*\)=.*$/built_with.\1=something/' } -notmuch_passwd_sanitize() -{ +notmuch_passwd_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.getfqdn() +fqdn = socket.getaddrinfo(socket.gethostname(), 0, 0, socket.SOCK_STREAM, 0, socket.AI_CANONNAME)[0][3] 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) ' } -notmuch_config_sanitize () -{ +notmuch_config_sanitize () { notmuch_dir_sanitize | notmuch_built_with_sanitize } -notmuch_show_part () -{ +notmuch_show_part () { awk '/^\014part}/{ f=0 }; { if (f) { print $0 } } /^\014part{ ID: '"$1"'/{ f=1 }' } @@ -913,7 +779,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_ @@ -937,7 +803,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_ @@ -977,7 +843,7 @@ test_must_fail () { # - cmp's output is not nearly as easy to read as diff -u # - not all diff versions understand "-u" -test_cmp() { +test_cmp () { $GIT_TEST_CMP "$@" } @@ -1031,88 +897,13 @@ test_done () { fi } -emacs_generate_script () { - # Construct a little test script here for the benefit of the user, - # (who can easily run "run_emacs" to get the same emacs environment - # for investigating any failures). - cat <"$TMP_DIRECTORY/run_emacs" -#!/bin/sh -export PATH=$PATH -export NOTMUCH_CONFIG=$NOTMUCH_CONFIG - -# Here's what we are using here: -# -# --quick Use minimal customization. This implies --no-init-file, -# --no-site-file and (emacs 24) --no-site-lisp -# -# --directory Ensure that the local elisp sources are found -# -# --load Force loading of notmuch.el and test-lib.el - -exec ${TEST_EMACS} --quick \ - --directory "$NOTMUCH_BUILDDIR/emacs" --load notmuch.el \ - --directory "$NOTMUCH_SRCDIR/test" --load test-lib.el \ - "\$@" -EOF - chmod a+x "$TMP_DIRECTORY/run_emacs" -} - -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 - - if [ -z "$EMACS_SERVER" ]; then - emacs_tests="$NOTMUCH_SRCDIR/test/${this_test_bare}.el" - if [ -f "$emacs_tests" ]; then - load_emacs_tests="--eval '(load \"$emacs_tests\")'" - else - load_emacs_tests= - fi - server_name="notmuch-test-suite-$$" - # start a detached session with an emacs server - # user's TERM (or 'vt100' in case user's TERM is known dumb - # or unknown) is given to dtach which assumes a minimally - # VT100-compatible terminal -- and emacs inherits that - TERM=$SMART_TERM dtach -n "$TEST_TMPDIR/emacs-dtach-socket.$$" \ - sh -c "stty rows 24 cols 80; exec '$TMP_DIRECTORY/run_emacs' \ - --no-window-system \ - $load_emacs_tests \ - --eval '(setq server-name \"$server_name\")' \ - --eval '(server-start)' \ - --eval '(orphan-watchdog $$)'" || return - EMACS_SERVER="$server_name" - # wait until the emacs server is up - until test_emacs '()' >/dev/null 2>/dev/null; do - sleep 1 - done - fi - - # Clear test-output output file. Most Emacs tests end with a - # call to (test-output). If the test code fails with an - # exception before this call, the output file won't get - # updated. Since we don't want to compare against an output - # file from another test, so start out with an empty file. - rm -f OUTPUT - touch OUTPUT - - ${TEST_EMACSCLIENT} --socket-name="$EMACS_SERVER" --eval "(notmuch-test-progn $*)" -} - -test_python() { +test_python () { # 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() { - MAIL_DIR=$MAIL_DIR $NOTMUCH_RUBY -I "$NOTMUCH_BUILDDIR/bindings/ruby"> OUTPUT -} - test_C () { local exec_file test_file exec_file="test${test_count}" @@ -1195,9 +986,6 @@ TEST_DIRECTORY=$NOTMUCH_BUILDDIR/test . "$NOTMUCH_SRCDIR/test/test-lib-common.sh" || exit 1 -emacs_generate_script - - # Use -P to resolve symlinks in our working directory so that the cwd # in subprocesses like git equals our $PWD (for pathname comparisons). cd -P "$TMP_DIRECTORY" || error "Cannot set up test environment" diff --git a/vim/notmuch.vim b/vim/notmuch.vim index 541698cd..c1c2f63d 100644 --- a/vim/notmuch.vim +++ b/vim/notmuch.vim @@ -317,6 +317,9 @@ ruby << EOF $curbuf.render do |b| q = $curbuf.query(get_cur_view) q.sort = Notmuch::SORT_OLDEST_FIRST + $exclude_tags.each { |t| + q.add_tag_exclude(t) + } msgs = q.search_messages msgs.each do |msg| m = Mail.read(msg.filename)