mirror of https://github.com/djcb/mu.git
guile: re-enable the guile support
Update for the internal (Mu::Message) APIs. Update build.
This commit is contained in:
parent
ce46c44ea9
commit
8eac392221
|
@ -28,7 +28,7 @@ compile_scm=configure_file(
|
||||||
run_command('chmod', '+x', compile_scm, check: true)
|
run_command('chmod', '+x', compile_scm, check: true)
|
||||||
scm_compiler=join_paths(meson.current_build_dir(), 'compile-scm')
|
scm_compiler=join_paths(meson.current_build_dir(), 'compile-scm')
|
||||||
|
|
||||||
snarf = find_program('guile-snarf')
|
snarf = find_program('guile-snarf3.0','guile-snarf')
|
||||||
# there must be a better way of feeding the include paths to snarf...
|
# there must be a better way of feeding the include paths to snarf...
|
||||||
snarf_args=['-o', '@OUTPUT@', '@INPUT@', '-I' + meson.current_source_dir() + '/..',
|
snarf_args=['-o', '@OUTPUT@', '@INPUT@', '-I' + meson.current_source_dir() + '/..',
|
||||||
'-I' + meson.current_source_dir() + '/../lib',
|
'-I' + meson.current_source_dir() + '/../lib',
|
||||||
|
|
|
@ -17,11 +17,18 @@
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
#include "mu-guile-message.hh"
|
#include "mu-guile-message.hh"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
#include "libguile/scm.h"
|
#include "libguile/scm.h"
|
||||||
|
#include "libguile/strings.h"
|
||||||
|
}
|
||||||
|
|
||||||
#include "message/mu-message.hh"
|
#include "message/mu-message.hh"
|
||||||
|
#include "utils/mu-utils.hh"
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
#include <memory>
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
||||||
#include <libguile.h>
|
#include <libguile.h>
|
||||||
|
@ -44,24 +51,51 @@ static std::array<SCM, AllMessageFlagInfos.size()> SYMB_FLAGS;
|
||||||
static SCM SYMB_CONTACT_TO, SYMB_CONTACT_CC, SYMB_CONTACT_BCC, SYMB_CONTACT_FROM;
|
static SCM SYMB_CONTACT_TO, SYMB_CONTACT_CC, SYMB_CONTACT_BCC, SYMB_CONTACT_FROM;
|
||||||
static long MSG_TAG;
|
static long MSG_TAG;
|
||||||
|
|
||||||
|
|
||||||
|
using MessageSPtr = std::unique_ptr<Message>;
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
mu_guile_scm_is_msg(SCM scm)
|
mu_guile_scm_is_msg(SCM scm)
|
||||||
{
|
{
|
||||||
return SCM_NIMP(scm) && (long)SCM_CAR(scm) == MSG_TAG;
|
return SCM_NIMP(scm) && (long)SCM_CAR(scm) == MSG_TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
SCM
|
static SCM
|
||||||
mu_guile_msg_to_scm(Message&& msg)
|
message_scm_create(Xapian::Document&& doc)
|
||||||
{
|
{
|
||||||
void *data{scm_gc_malloc(sizeof(Message), "msg")};
|
/* placement-new */
|
||||||
auto msgptr = reinterpret_cast<MuMsgWrapper*>(
|
|
||||||
scm_gc_malloc(sizeof(MuMsgWrapper), "msg"));
|
|
||||||
msgwrap->_msg = std::move(msg);
|
|
||||||
msgwrap->_unrefme = false;
|
|
||||||
|
|
||||||
SCM_RETURN_NEWSMOB(MSG_TAG,
|
void *scm_mem{scm_gc_malloc(sizeof(Message), "msg")};
|
||||||
|
Message* msgp = new(scm_mem)Message(std::move(doc));
|
||||||
|
|
||||||
msgwrap);
|
SCM_RETURN_NEWSMOB(MSG_TAG, msgp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Message*
|
||||||
|
message_from_scm(SCM msg_smob)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<Message*>(SCM_CDR(msg_smob));
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
message_scm_free(SCM msg_smob)
|
||||||
|
{
|
||||||
|
if (auto msg = message_from_scm(msg_smob); msg)
|
||||||
|
msg->~Message();
|
||||||
|
|
||||||
|
return sizeof(Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
message_scm_print(SCM msg_smob, SCM port, scm_print_state* pstate)
|
||||||
|
{
|
||||||
|
scm_puts("#<msg ", port);
|
||||||
|
|
||||||
|
if (auto msg = message_from_scm(msg_smob); msg)
|
||||||
|
scm_puts(msg->path().c_str(), port);
|
||||||
|
|
||||||
|
scm_puts(">", port);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FlagData {
|
struct FlagData {
|
||||||
|
@ -121,6 +155,13 @@ msg_string_list_field(const Message& msg, Field::Id field_id)
|
||||||
return scmlst;
|
return scmlst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SCM
|
||||||
|
msg_contact_list_field(const Message& msg, Field::Id field_id)
|
||||||
|
{
|
||||||
|
return scm_from_utf8_string(
|
||||||
|
to_string(msg.document().contacts_value(field_id)).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
static SCM
|
static SCM
|
||||||
get_body(const Message& msg, bool html)
|
get_body(const Message& msg, bool html)
|
||||||
{
|
{
|
||||||
|
@ -139,46 +180,37 @@ SCM_DEFINE(get_field,
|
||||||
"Get the field FIELD from message MSG.\n")
|
"Get the field FIELD from message MSG.\n")
|
||||||
#define FUNC_NAME s_get_field
|
#define FUNC_NAME s_get_field
|
||||||
{
|
{
|
||||||
MuMsgWrapper* msgwrap;
|
|
||||||
size_t field_id;
|
|
||||||
msgwrap = (MuMsgWrapper*)SCM_CDR(MSG);
|
|
||||||
const auto& msg{msgwrap->_msg};
|
|
||||||
|
|
||||||
MU_GUILE_INITIALIZED_OR_ERROR;
|
|
||||||
|
|
||||||
SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||||
|
auto msg{message_from_scm(MSG)};
|
||||||
|
SCM_ASSERT(msg, MSG, SCM_ARG1, FUNC_NAME);
|
||||||
|
|
||||||
SCM_ASSERT(scm_integer_p(FIELD), FIELD, SCM_ARG2, FUNC_NAME);
|
SCM_ASSERT(scm_integer_p(FIELD), FIELD, SCM_ARG2, FUNC_NAME);
|
||||||
|
const auto field_opt{field_from_number(static_cast<size_t>(scm_to_int(FIELD)))};
|
||||||
field_id = scm_to_int(FIELD);
|
|
||||||
if (field_id == MU_GUILE_MSG_FIELD_ID_TIMESTAMP)
|
|
||||||
return scm_from_uint((unsigned)msgwrap->_msg.date());
|
|
||||||
|
|
||||||
const auto field_opt{field_from_number(static_cast<size_t>(field_id))};
|
|
||||||
SCM_ASSERT(!!field_opt, FIELD, SCM_ARG2, FUNC_NAME);
|
SCM_ASSERT(!!field_opt, FIELD, SCM_ARG2, FUNC_NAME);
|
||||||
|
|
||||||
switch (field_opt->id) {
|
switch (field_opt->id) {
|
||||||
case Field::Id::Priority:
|
case Field::Id::Priority:
|
||||||
return get_prio_scm(msg);
|
return get_prio_scm(*msg);
|
||||||
case Field::Id::Flags:
|
case Field::Id::Flags:
|
||||||
return get_flags_scm(msg);
|
return get_flags_scm(*msg);
|
||||||
case Field::Id::BodyHtml:
|
|
||||||
return get_body(msg, true);
|
|
||||||
case Field::Id::BodyText:
|
case Field::Id::BodyText:
|
||||||
return get_body(msg, false);
|
return get_body(*msg, false);
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (field_opt->type) {
|
switch (field_opt->type) {
|
||||||
case Field::Type::String:
|
case Field::Type::String:
|
||||||
return mu_guile_scm_from_string(msg.document().string_value(field_opt->id));
|
return mu_guile_scm_from_string(msg->document().string_value(field_opt->id));
|
||||||
case Field::Type::ByteSize:
|
case Field::Type::ByteSize:
|
||||||
case Field::Type::TimeT:
|
case Field::Type::TimeT:
|
||||||
case Field::Type::Integer:
|
case Field::Type::Integer:
|
||||||
return scm_from_uint(msg.document().integer_value(field_opt->id));
|
return scm_from_uint(msg->document().integer_value(field_opt->id));
|
||||||
case Field::Type::StringList:
|
case Field::Type::StringList:
|
||||||
return msg_string_list_field(msg, field_opt->id);
|
return msg_string_list_field(*msg, field_opt->id);
|
||||||
default: SCM_ASSERT(0, FIELD, SCM_ARG2, FUNC_NAME);
|
case Field::Type::ContactList:
|
||||||
|
return msg_contact_list_field(*msg, field_opt->id);
|
||||||
|
default:
|
||||||
|
SCM_ASSERT(0, FIELD, SCM_ARG2, FUNC_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
@ -211,13 +243,14 @@ SCM_DEFINE(get_contacts,
|
||||||
"Get a list of contact information pairs.\n")
|
"Get a list of contact information pairs.\n")
|
||||||
#define FUNC_NAME s_get_contacts
|
#define FUNC_NAME s_get_contacts
|
||||||
{
|
{
|
||||||
MuMsgWrapper* msgwrap;
|
SCM list;
|
||||||
SCM list;
|
|
||||||
|
|
||||||
|
|
||||||
MU_GUILE_INITIALIZED_OR_ERROR;
|
MU_GUILE_INITIALIZED_OR_ERROR;
|
||||||
|
|
||||||
SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||||
|
auto msg{message_from_scm(MSG)};
|
||||||
|
SCM_ASSERT(msg, MSG, SCM_ARG1, FUNC_NAME);
|
||||||
|
|
||||||
SCM_ASSERT(scm_symbol_p(CONTACT_TYPE) || scm_is_bool(CONTACT_TYPE),
|
SCM_ASSERT(scm_symbol_p(CONTACT_TYPE) || scm_is_bool(CONTACT_TYPE),
|
||||||
CONTACT_TYPE,
|
CONTACT_TYPE,
|
||||||
SCM_ARG2,
|
SCM_ARG2,
|
||||||
|
@ -244,11 +277,9 @@ SCM_DEFINE(get_contacts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
msgwrap = (MuMsgWrapper*)SCM_CDR(MSG);
|
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||||
list = contacts_to_list(msgwrap->_msg, field_id);
|
list = contacts_to_list(*msg, field_id);
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
/* explicitly close the file backend, so we won't run out of fds */
|
/* explicitly close the file backend, so we won't run out of fds */
|
||||||
|
@ -269,19 +300,18 @@ SCM_DEFINE(get_parts,
|
||||||
"elements which are list of the form (index name mime-type size).\n")
|
"elements which are list of the form (index name mime-type size).\n")
|
||||||
#define FUNC_NAME s_get_parts
|
#define FUNC_NAME s_get_parts
|
||||||
{
|
{
|
||||||
MuMsgWrapper* msgwrap;
|
|
||||||
|
|
||||||
MU_GUILE_INITIALIZED_OR_ERROR;
|
MU_GUILE_INITIALIZED_OR_ERROR;
|
||||||
|
|
||||||
SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||||
|
auto msg{message_from_scm(MSG)};
|
||||||
|
SCM_ASSERT(msg, MSG, SCM_ARG1, FUNC_NAME);
|
||||||
SCM_ASSERT(scm_is_bool(ATTS_ONLY), ATTS_ONLY, SCM_ARG2, FUNC_NAME);
|
SCM_ASSERT(scm_is_bool(ATTS_ONLY), ATTS_ONLY, SCM_ARG2, FUNC_NAME);
|
||||||
|
|
||||||
SCM attlist = SCM_EOL; /* empty list */
|
SCM attlist = SCM_EOL; /* empty list */
|
||||||
bool attachments_only = ATTS_ONLY == SCM_BOOL_T ? TRUE : FALSE;
|
bool attachments_only = ATTS_ONLY == SCM_BOOL_T ? TRUE : FALSE;
|
||||||
|
|
||||||
const Message& msg{reinterpret_cast<MuMsgWrapper*>(SCM_CDR(MSG))->_msg};
|
|
||||||
size_t n{};
|
size_t n{};
|
||||||
for (auto&& part: msg.parts()) {
|
for (auto&& part: msg->parts()) {
|
||||||
|
|
||||||
if (attachments_only && !part.is_attachment())
|
if (attachments_only && !part.is_attachment())
|
||||||
continue;
|
continue;
|
||||||
|
@ -291,7 +321,7 @@ SCM_DEFINE(get_parts,
|
||||||
|
|
||||||
SCM elm = scm_list_5(
|
SCM elm = scm_list_5(
|
||||||
/* msg */
|
/* msg */
|
||||||
mu_guile_scm_from_string(msgwrap->_msg.path()),
|
mu_guile_scm_from_string(msg->path().c_str()),
|
||||||
/* index */
|
/* index */
|
||||||
scm_from_uint(n++),
|
scm_from_uint(n++),
|
||||||
/* filename or #f */
|
/* filename or #f */
|
||||||
|
@ -305,7 +335,7 @@ SCM_DEFINE(get_parts,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* explicitly close the file backend, so we won't run of fds */
|
/* explicitly close the file backend, so we won't run of fds */
|
||||||
msg.unload_mime_message();
|
msg->unload_mime_message();
|
||||||
|
|
||||||
return attlist;
|
return attlist;
|
||||||
}
|
}
|
||||||
|
@ -323,27 +353,21 @@ SCM_DEFINE(get_header,
|
||||||
MU_GUILE_INITIALIZED_OR_ERROR;
|
MU_GUILE_INITIALIZED_OR_ERROR;
|
||||||
|
|
||||||
SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
SCM_ASSERT(mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||||
|
auto msg{message_from_scm(MSG)};
|
||||||
|
SCM_ASSERT(msg, MSG, SCM_ARG1, FUNC_NAME);
|
||||||
|
|
||||||
SCM_ASSERT(scm_is_string(HEADER) || HEADER == SCM_UNDEFINED, HEADER, SCM_ARG2, FUNC_NAME);
|
SCM_ASSERT(scm_is_string(HEADER) || HEADER == SCM_UNDEFINED, HEADER, SCM_ARG2, FUNC_NAME);
|
||||||
|
|
||||||
const Message& msg{reinterpret_cast<MuMsgWrapper*>(SCM_CDR(MSG))->_msg};
|
|
||||||
|
|
||||||
char *header = scm_to_utf8_string(HEADER);
|
char *header = scm_to_utf8_string(HEADER);
|
||||||
SCM val = mu_guile_scm_from_string(msg.header(header).value_or(""));
|
SCM val = mu_guile_scm_from_string(msg->header(header).value_or(""));
|
||||||
free(header);
|
free(header);
|
||||||
|
|
||||||
/* explicitly close the file backend, so we won't run of fds */
|
/* explicitly close the file backend, so we won't run of fds */
|
||||||
msg.unload_mime_message();
|
msg->unload_mime_message();
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
static Mu::Option<Mu::QueryResults>
|
|
||||||
get_query_results(Mu::Store& store, const char* expr, int maxnum)
|
|
||||||
{
|
|
||||||
return store.run_query(expr, {}, Mu::QueryFlags::None, maxnum);
|
|
||||||
}
|
|
||||||
|
|
||||||
SCM_DEFINE(for_each_message,
|
SCM_DEFINE(for_each_message,
|
||||||
"mu:c:for-each-message",
|
"mu:c:for-each-message",
|
||||||
3,
|
3,
|
||||||
|
@ -369,19 +393,18 @@ SCM_DEFINE(for_each_message,
|
||||||
return SCM_UNSPECIFIED; /* nothing to do */
|
return SCM_UNSPECIFIED; /* nothing to do */
|
||||||
|
|
||||||
if (EXPR == SCM_BOOL_T)
|
if (EXPR == SCM_BOOL_T)
|
||||||
expr = strdup(""); /* note, "" matches *all* messages */
|
expr = strdup("\"\""); /* note, "" matches *all* messages */
|
||||||
else
|
else
|
||||||
expr = scm_to_utf8_string(EXPR);
|
expr = scm_to_utf8_string(EXPR);
|
||||||
|
|
||||||
const auto res{get_query_results(mu_guile_store(), expr, scm_to_int(MAXNUM))};
|
const auto res = mu_guile_store().run_query(expr,{}, {}, scm_to_int(MAXNUM));
|
||||||
free(expr);
|
free(expr);
|
||||||
if (!res)
|
if (!res)
|
||||||
return SCM_UNSPECIFIED;
|
return SCM_UNSPECIFIED;
|
||||||
|
|
||||||
for (auto&& mi : *res) {
|
for (auto&& mi : *res) {
|
||||||
if (auto msg{mi.message()}; msg) {
|
if (auto xdoc{mi.document()}; xdoc) {
|
||||||
auto msgsmob{mu_guile_msg_to_scm(std::move(msg.value()))};
|
scm_call_1(FUNC, message_scm_create(std::move(xdoc.value())));
|
||||||
scm_call_1(FUNC, msgsmob);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,7 +446,8 @@ static void
|
||||||
define_vars(void)
|
define_vars(void)
|
||||||
{
|
{
|
||||||
field_for_each([](auto&& field){
|
field_for_each([](auto&& field){
|
||||||
const auto name{"mu:field:" + std::string{field.name}};
|
const auto name{"mu:field:" +
|
||||||
|
std::string{field.alias.empty() ? field.name : field.alias}};
|
||||||
scm_c_define(name.c_str(), scm_from_uint(field.value_no()));
|
scm_c_define(name.c_str(), scm_from_uint(field.value_no()));
|
||||||
scm_c_export(name.c_str(), NULL);
|
scm_c_export(name.c_str(), NULL);
|
||||||
});
|
});
|
||||||
|
@ -435,43 +459,13 @@ define_vars(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
|
||||||
msg_free(SCM msg_smob)
|
|
||||||
{
|
|
||||||
MuMsgWrapper* msgwrap;
|
|
||||||
msgwrap = (MuMsgWrapper*)SCM_CDR(msg_smob);
|
|
||||||
|
|
||||||
if (msgwrap->_unrefme)
|
|
||||||
mu_msg_unref(msgwrap->_msg);
|
|
||||||
|
|
||||||
return sizeof(MuMsgWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
msg_print(SCM msg_smob, SCM port, scm_print_state* pstate)
|
|
||||||
{
|
|
||||||
MuMsgWrapper* msgwrap;
|
|
||||||
msgwrap = (MuMsgWrapper*)SCM_CDR(msg_smob);
|
|
||||||
|
|
||||||
scm_puts("#<msg ", port);
|
|
||||||
|
|
||||||
if (msg_smob == SCM_BOOL_F)
|
|
||||||
scm_puts("#f", port);
|
|
||||||
else
|
|
||||||
scm_puts(mu_msg_get_path(msgwrap->_msg), port);
|
|
||||||
|
|
||||||
scm_puts(">", port);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void*
|
void*
|
||||||
mu_guile_message_init(void* data)
|
mu_guile_message_init(void* data)
|
||||||
{
|
{
|
||||||
MSG_TAG = scm_make_smob_type("msg", sizeof(MuMsgWrapper));
|
MSG_TAG = scm_make_smob_type("message", sizeof(Message));
|
||||||
|
|
||||||
scm_set_smob_free(MSG_TAG, msg_free);
|
scm_set_smob_free(MSG_TAG, message_scm_free);
|
||||||
scm_set_smob_print(MSG_TAG, msg_print);
|
scm_set_smob_print(MSG_TAG, message_scm_print);
|
||||||
|
|
||||||
define_vars();
|
define_vars();
|
||||||
define_symbols();
|
define_symbols();
|
||||||
|
|
|
@ -23,9 +23,12 @@
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
||||||
|
extern "C" {
|
||||||
#include <libguile.h>
|
#include <libguile.h>
|
||||||
|
}
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
#include <mu-runtime.hh>
|
#include <mu-runtime.hh>
|
||||||
|
@ -71,26 +74,42 @@ mu_guile_g_error(const char* func_name, GError* err)
|
||||||
|
|
||||||
/* there can be only one */
|
/* there can be only one */
|
||||||
|
|
||||||
static std::unique_ptr<Mu::Store> StoreSingleton;
|
static Option<Mu::Store> StoreSingleton = Nothing;
|
||||||
|
|
||||||
static gboolean
|
static bool
|
||||||
mu_guile_init_instance(const char* muhome)
|
mu_guile_init_instance(const char* muhome)
|
||||||
try {
|
try {
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
if (!mu_runtime_init(muhome, "guile", true) || StoreSingleton)
|
if (!mu_runtime_init(muhome, "guile", true) || StoreSingleton)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
StoreSingleton = std::make_unique<Mu::Store>(mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB));
|
const auto path{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB)};
|
||||||
|
auto store = Store::make(path);
|
||||||
|
if (!store) {
|
||||||
|
g_critical("error creating store @ %s: %s", path, store.error().what());
|
||||||
|
throw store.error();
|
||||||
|
} else
|
||||||
|
StoreSingleton.emplace(std::move(store.value()));
|
||||||
|
|
||||||
g_debug("mu-guile: opened store @ %s (n=%zu); maildir: %s",
|
g_debug("mu-guile: opened store @ %s (n=%zu); maildir: %s",
|
||||||
StoreSingleton->properties().database_path.c_str(),
|
StoreSingleton->properties().database_path.c_str(),
|
||||||
StoreSingleton->size(),
|
StoreSingleton->size(),
|
||||||
StoreSingleton->properties().root_maildir.c_str());
|
StoreSingleton->properties().root_maildir.c_str());
|
||||||
|
|
||||||
return TRUE;
|
return true;
|
||||||
|
|
||||||
|
} catch (const Xapian::Error& xerr) {
|
||||||
|
g_critical("%s: xapian error '%s'", __func__, xerr.get_msg().c_str());
|
||||||
|
return false;
|
||||||
|
} catch (const std::runtime_error& re) {
|
||||||
|
g_critical("%s: error: %s", __func__, re.what());
|
||||||
|
return false;
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
g_critical("%s: caught exception: %s", __func__, e.what());
|
||||||
|
return false;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return FALSE;
|
g_critical("%s: caught exception", __func__);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -107,7 +126,7 @@ mu_guile_store()
|
||||||
if (!StoreSingleton)
|
if (!StoreSingleton)
|
||||||
g_error("mu guile not initialized");
|
g_error("mu guile not initialized");
|
||||||
|
|
||||||
return *StoreSingleton.get();
|
return StoreSingleton.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
@ -131,7 +150,6 @@ SCM_DEFINE_PUBLIC(mu_initialize,
|
||||||
#define FUNC_NAME s_mu_initialize
|
#define FUNC_NAME s_mu_initialize
|
||||||
{
|
{
|
||||||
char* muhome;
|
char* muhome;
|
||||||
gboolean rv;
|
|
||||||
|
|
||||||
SCM_ASSERT(scm_is_string(MUHOME) || MUHOME == SCM_BOOL_F || SCM_UNBNDP(MUHOME),
|
SCM_ASSERT(scm_is_string(MUHOME) || MUHOME == SCM_BOOL_F || SCM_UNBNDP(MUHOME),
|
||||||
MUHOME,
|
MUHOME,
|
||||||
|
@ -146,14 +164,12 @@ SCM_DEFINE_PUBLIC(mu_initialize,
|
||||||
else
|
else
|
||||||
muhome = scm_to_utf8_string(MUHOME);
|
muhome = scm_to_utf8_string(MUHOME);
|
||||||
|
|
||||||
rv = mu_guile_init_instance(muhome);
|
if (!mu_guile_init_instance(muhome)) {
|
||||||
if (!rv) {
|
|
||||||
free(muhome);
|
free(muhome);
|
||||||
mu_guile_error(FUNC_NAME, 0, "Failed to initialize mu", SCM_UNSPECIFIED);
|
mu_guile_error(FUNC_NAME, 0, "Failed to initialize mu", SCM_UNSPECIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_debug("mu-guile: initialized @ %s (%p)",
|
g_debug("mu-guile: initialized @ %s", muhome ? muhome : "<default>");
|
||||||
muhome ? muhome : "<default>", StoreSingleton.get());
|
|
||||||
free(muhome);
|
free(muhome);
|
||||||
|
|
||||||
/* cleanup when we're exiting */
|
/* cleanup when we're exiting */
|
||||||
|
|
|
@ -21,7 +21,9 @@
|
||||||
#define __MU_GUILE_H__
|
#define __MU_GUILE_H__
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
extern "C" {
|
||||||
#include <libguile.h>
|
#include <libguile.h>
|
||||||
|
}
|
||||||
#include <mu-query.hh>
|
#include <mu-query.hh>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -25,6 +25,7 @@ test('test-mu-guile',
|
||||||
install: false,
|
install: false,
|
||||||
cpp_args: [
|
cpp_args: [
|
||||||
'-DABS_SRCDIR="' + meson.current_source_dir() + '"',
|
'-DABS_SRCDIR="' + meson.current_source_dir() + '"',
|
||||||
'-DGUILE_LOAD_PATH="' + guile_load_path + '"'
|
'-DGUILE_LOAD_PATH="' + guile_load_path + '"',
|
||||||
|
'-DGUILE_EXTENSIONS_PATH="' + guile_load_path + '"'
|
||||||
],
|
],
|
||||||
dependencies: [glib_dep, lib_mu_dep, lib_test_mu_common_dep]))
|
dependencies: [glib_dep, lib_mu_dep, lib_test_mu_common_dep]))
|
||||||
|
|
|
@ -29,64 +29,66 @@
|
||||||
|
|
||||||
#include "test-mu-common.hh"
|
#include "test-mu-common.hh"
|
||||||
#include <lib/mu-store.hh>
|
#include <lib/mu-store.hh>
|
||||||
|
#include <utils/mu-utils.hh>
|
||||||
|
|
||||||
/* Tests For The command line interface, uses testdir2 */
|
using namespace Mu;
|
||||||
|
|
||||||
static gchar*
|
static std::string test_dir;
|
||||||
|
|
||||||
|
static std::string
|
||||||
fill_database(void)
|
fill_database(void)
|
||||||
{
|
{
|
||||||
gchar * cmdline, *tmpdir;
|
const auto cmdline = format(
|
||||||
GError* err;
|
"/bin/sh -c '"
|
||||||
|
"%s init --muhome=%s --maildir=%s --quiet; "
|
||||||
tmpdir = test_mu_common_get_random_tmpdir();
|
"%s index --muhome=%s --quiet'",
|
||||||
cmdline = g_strdup_printf("/bin/sh -c '"
|
MU_PROGRAM,
|
||||||
"%s init --muhome=%s --maildir=%s --quiet; "
|
test_dir.c_str(),
|
||||||
"%s index --muhome=%s --quiet'",
|
MU_TESTMAILDIR2,
|
||||||
MU_PROGRAM,
|
MU_PROGRAM,
|
||||||
tmpdir,
|
test_dir.c_str());
|
||||||
MU_TESTMAILDIR2,
|
|
||||||
MU_PROGRAM,
|
|
||||||
tmpdir);
|
|
||||||
|
|
||||||
if (g_test_verbose())
|
if (g_test_verbose())
|
||||||
g_print("%s\n", cmdline);
|
g_print("%s\n", cmdline.c_str());
|
||||||
|
|
||||||
err = NULL;
|
GError *err{};
|
||||||
if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &err)) {
|
if (!g_spawn_command_line_sync(cmdline.c_str(), NULL, NULL, NULL, &err)) {
|
||||||
g_printerr("Error: %s\n", err ? err->message : "?");
|
g_printerr("Error: %s\n", err ? err->message : "?");
|
||||||
|
g_clear_error(&err);
|
||||||
g_assert(0);
|
g_assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free(cmdline);
|
return test_dir;
|
||||||
return tmpdir;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_something(const char* what)
|
test_something(const char* what)
|
||||||
{
|
{
|
||||||
char *dir, *cmdline;
|
|
||||||
gint result;
|
|
||||||
|
|
||||||
|
|
||||||
g_setenv("GUILE_AUTO_COMPILE", "0", TRUE);
|
g_setenv("GUILE_AUTO_COMPILE", "0", TRUE);
|
||||||
g_setenv("GUILE_LOAD_PATH", GUILE_LOAD_PATH, TRUE);
|
g_setenv("GUILE_LOAD_PATH", GUILE_LOAD_PATH, TRUE);
|
||||||
|
g_setenv("GUILE_EXTENSIONS_PATH",GUILE_EXTENSIONS_PATH, TRUE);
|
||||||
dir = fill_database();
|
|
||||||
cmdline = g_strdup_printf("%s -q -e main %s/test-mu-guile.scm "
|
|
||||||
"--muhome=%s --test=%s",
|
|
||||||
GUILE_BINARY,
|
|
||||||
ABS_SRCDIR,
|
|
||||||
dir,
|
|
||||||
what);
|
|
||||||
|
|
||||||
if (g_test_verbose())
|
if (g_test_verbose())
|
||||||
g_print("cmdline: %s\n", cmdline);
|
g_print("GUILE_LOAD_PATH: %s\n", GUILE_LOAD_PATH);
|
||||||
|
|
||||||
result = system(cmdline);
|
const auto dir = fill_database();
|
||||||
g_assert(result == 0);
|
const auto cmdline = format("%s -q -e main %s/test-mu-guile.scm "
|
||||||
|
"--muhome=%s --test=%s",
|
||||||
|
GUILE_BINARY,
|
||||||
|
ABS_SRCDIR,
|
||||||
|
dir.c_str(), what);
|
||||||
|
|
||||||
g_free(dir);
|
if (g_test_verbose())
|
||||||
g_free(cmdline);
|
g_print("cmdline: %s\n", cmdline.c_str());
|
||||||
|
|
||||||
|
GError *err{};
|
||||||
|
int status{};
|
||||||
|
if (!g_spawn_command_line_sync(cmdline.c_str(), NULL, NULL, &status, &err) ||
|
||||||
|
status != 0) {
|
||||||
|
g_printerr("Error: %s\n", err ? err->message : "something went wrong");
|
||||||
|
g_clear_error(&err);
|
||||||
|
g_assert(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -111,6 +113,9 @@ int
|
||||||
main(int argc, char* argv[])
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
TempDir tempdir;
|
||||||
|
test_dir = tempdir.path();
|
||||||
|
|
||||||
g_test_init(&argc, &argv, NULL);
|
g_test_init(&argc, &argv, NULL);
|
||||||
|
|
||||||
if (!set_en_us_utf8_locale())
|
if (!set_en_us_utf8_locale())
|
||||||
|
|
|
@ -23,7 +23,9 @@
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
||||||
|
extern "C" {
|
||||||
#include <libguile.h>
|
#include <libguile.h>
|
||||||
|
}
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif /*BUILD_GUILE*/
|
#endif /*BUILD_GUILE*/
|
||||||
|
|
||||||
|
|
|
@ -179,9 +179,10 @@ endif
|
||||||
|
|
||||||
if not get_option('guile').disabled() and guile_dep.found()
|
if not get_option('guile').disabled() and guile_dep.found()
|
||||||
config_h_data.set('BUILD_GUILE', 1)
|
config_h_data.set('BUILD_GUILE', 1)
|
||||||
config_h_data.set_quoted('GUILE_BINARY', 'guile')
|
config_h_data.set_quoted('GUILE_BINARY',
|
||||||
message('guile is disabled for now')
|
guile_dep.get_pkgconfig_variable('guile'))
|
||||||
#subdir('guile')
|
#message('guile is disabled for now')
|
||||||
|
subdir('guile')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
config_h_data.set_quoted('MU_PROGRAM', mu.full_path())
|
config_h_data.set_quoted('MU_PROGRAM', mu.full_path())
|
||||||
|
|
Loading…
Reference in New Issue