mu: convert command-line tools to c++

This commit is contained in:
Dirk-Jan C. Binnema 2020-06-08 23:04:05 +03:00
parent dd0cb3112a
commit a9fab4abcc
22 changed files with 425 additions and 529 deletions

View File

@ -447,6 +447,7 @@ Store::in_transaction () const
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// C compat // C compat
extern "C" { extern "C" {
@ -1390,44 +1391,4 @@ mu_store_get_dirstamp (const MuStore *store, const char *dirpath, GError **err)
return self(store)->dirstamp(dirpath); return self(store)->dirstamp(dirpath);
} }
void
mu_store_print_info (const MuStore *store, gboolean nocolor)
{
const auto green{nocolor ? "" : MU_COLOR_GREEN};
const auto def{nocolor ? "" : MU_COLOR_DEFAULT};
std::cout << "database-path : "
<< green << self(store)->database_path() << def << "\n"
<< "messages in store : "
<< green << self(store)->size() << def << "\n"
<< "schema-version : "
<< green << self(store)->schema_version() << def << "\n";
const auto created{mu_store_created (store)};
const auto tstamp{localtime (&created)};
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-y2k"
char tbuf[64];
strftime (tbuf, sizeof(tbuf), "%c", tstamp);
#pragma GCC diagnostic pop
std::cout << "created : " << green << tbuf << def << "\n"
<< "maildir : "
<< green << self(store)->root_maildir() << def << "\n";
std::cout << ("personal-addresses : ");
auto addrs{mu_store_personal_addresses (store)};
if (!addrs || g_strv_length(addrs) == 0)
std::cout << green << "<none>" << def << "\n";
else {
for (auto i = 0U; addrs[i]; ++i) {
std::cout << (i != 0 ? " " : "")
<< green << addrs[i] << def << "\n";
}
}
g_strfreev(addrs);
}
} }

View File

@ -195,18 +195,8 @@ Sexp::Node::to_string () const
break; break;
} }
case Type::String: case Type::String:
//sstrm << quote(value()); sstrm << quote(value());
sstrm << "\"";
for (auto&& k: value()) {
switch (k) {
case '"' : sstrm << "\\\""; break;
case '\\': sstrm << "\\\\"; break;
default: sstrm << k;
}
}
sstrm << "\"";
break; break;
case Type::Number: case Type::Number:
case Type::Symbol: case Type::Symbol:
default: default:

View File

@ -309,7 +309,7 @@ typedef gpointer XapianEnquire;
} while (0) } while (0)
#define MU_G_ERROR_CODE(GE) ((GE)&&(*(GE))?(*(GE))->code:MU_ERROR) #define MU_G_ERROR_CODE(GE) ((GE)&&(*(GE))?(MuError)(*(GE))->code:MU_ERROR)
enum _MuError { enum _MuError {

View File

@ -165,14 +165,17 @@ Mu::split (const std::string& str, const std::string& sepa)
std::string std::string
Mu::quote (const std::string& str) Mu::quote (const std::string& str)
{ {
char *s = g_strescape (str.c_str(), NULL); std::string res{"\""};
if (!s)
return {};
std::string res (s); for (auto&& k: str) {
g_free (s); switch (k) {
case '"' : res += "\\\""; break;
case '\\': res += "\\\\"; break;
default: res += k;
}
}
return "\"" + res + "\""; return res + "\"";
} }
std::string std::string

View File

@ -65,7 +65,7 @@ std::vector<std::string> split (const std::string& str,
const std::string& sepa); const std::string& sepa);
/** /**
* Quote & escape a string * Quote & escape a string for " and \
* *
* @param str a string * @param str a string
* *

View File

@ -21,21 +21,14 @@ AM_CPPFLAGS= \
$(GLIB_CFLAGS) \ $(GLIB_CFLAGS) \
$(CODE_COVERAGE_CFLAGS) $(CODE_COVERAGE_CFLAGS)
# don't use -Werror, as it might break on other compilers
# use -Wno-unused-parameters, because some callbacks may not
# really need all the params they get
AM_CFLAGS= \
$(JSON_GLIB_CFLAGS) \
$(ASAN_CFLAGS) \
$(WARN_CFLAGS) \
$(CODE_COVERAGE_CFLAGS) \
-Wno-switch-enum \
-DMU_SCRIPTS_DIR="\"$(pkgdatadir)/scripts/\""
AM_CXXFLAGS= \ AM_CXXFLAGS= \
$(JSON_GLIB_CFLAGS) \
-DMU_SCRIPTS_DIR="\"$(pkgdatadir)/scripts/\""
$(ASAN_CXXCFLAGS) \ $(ASAN_CXXCFLAGS) \
$(WARN_CXXFLAGS) \ $(WARN_CXXFLAGS) \
$(CODE_COVERAGE_CFLAGS) $(CODE_COVERAGE_CFLAGS) \
-Wno-switch-enum
AM_LDFLAGS= \ AM_LDFLAGS= \
$(ASAN_LDFLAGS) $(ASAN_LDFLAGS)
@ -47,16 +40,16 @@ bin_PROGRAMS= \
# be linked as c++, not c. # be linked as c++, not c.
mu_SOURCES= \ mu_SOURCES= \
mu.cc \ mu.cc \
mu-cmd-cfind.c \ mu-cmd-cfind.cc \
mu-config.c \ mu-config.cc \
mu-config.h \ mu-config.hh \
mu-cmd-extract.c \ mu-cmd-extract.cc \
mu-cmd-find.c \ mu-cmd-find.cc \
mu-cmd-index.c \ mu-cmd-index.cc \
mu-cmd-server.cc \ mu-cmd-server.cc \
mu-cmd-script.c \ mu-cmd-script.cc \
mu-cmd.c \ mu-cmd.cc \
mu-cmd.h mu-cmd.hh
BUILT_SOURCES= \ BUILT_SOURCES= \
mu-help-strings.h mu-help-strings.h
@ -77,8 +70,8 @@ EXTRA_DIST= \
noinst_PROGRAMS= $(TEST_PROGS) noinst_PROGRAMS= $(TEST_PROGS)
test_cflags= \ test_cxxflags= \
${AM_CFLAGS} \ ${AM_CXXFLAGS} \
-DMU_TESTMAILDIR=\"${abs_top_srcdir}/lib/testdir\" \ -DMU_TESTMAILDIR=\"${abs_top_srcdir}/lib/testdir\" \
-DMU_TESTMAILDIR2=\"${abs_top_srcdir}/lib/testdir2\" \ -DMU_TESTMAILDIR2=\"${abs_top_srcdir}/lib/testdir2\" \
-DMU_TESTMAILDIR3=\"${abs_top_srcdir}/lib/testdir3\" \ -DMU_TESTMAILDIR3=\"${abs_top_srcdir}/lib/testdir3\" \
@ -88,31 +81,25 @@ test_cflags= \
-DABS_SRCDIR=\"${abs_srcdir}\" -DABS_SRCDIR=\"${abs_srcdir}\"
TEST_PROGS += test-mu-query TEST_PROGS += test-mu-query
test_mu_query_SOURCES= test-mu-query.c dummy.cc test_mu_query_SOURCES= test-mu-query.cc
test_mu_query_CFLAGS=$(test_cflags) test_mu_query_CXXFLAGS=$(test_cxxflags)
test_mu_query_LDADD=${top_builddir}/lib/libtestmucommon.la $(CODE_COVERAGE_LIBS) test_mu_query_LDADD=${top_builddir}/lib/libtestmucommon.la $(CODE_COVERAGE_LIBS)
TEST_PROGS += test-mu-cmd TEST_PROGS += test-mu-cmd
test_mu_cmd_SOURCES= test-mu-cmd.c dummy.cc test_mu_cmd_SOURCES= test-mu-cmd.cc
test_mu_cmd_CFLAGS=$(test_cflags) test_mu_cmd_CXXFLAGS=$(test_cxxflags)
test_mu_cmd_LDADD=${top_builddir}/lib/libtestmucommon.la $(CODE_COVERAGE_LIBS) test_mu_cmd_LDADD=${top_builddir}/lib/libtestmucommon.la $(CODE_COVERAGE_LIBS)
TEST_PROGS += test-mu-cmd-cfind TEST_PROGS += test-mu-cmd-cfind
test_mu_cmd_cfind_SOURCES= test-mu-cmd-cfind.c dummy.cc test_mu_cmd_cfind_SOURCES= test-mu-cmd-cfind.cc
test_mu_cmd_cfind_CFLAGS=$(test_cflags) test_mu_cmd_cfind_CXXFLAGS=$(test_cxxflags)
test_mu_cmd_cfind_LDADD=${top_builddir}/lib/libtestmucommon.la $(CODE_COVERAGE_LIBS) test_mu_cmd_cfind_LDADD=${top_builddir}/lib/libtestmucommon.la $(CODE_COVERAGE_LIBS)
TEST_PROGS += test-mu-threads TEST_PROGS += test-mu-threads
test_mu_threads_SOURCES= test-mu-threads.c dummy.cc test_mu_threads_SOURCES= test-mu-threads.cc
test_mu_threads_CFLAGS=$(test_cflags) test_mu_threads_CXXFLAGS=$(test_cxxflags)
test_mu_threads_LDADD=${top_builddir}/lib/libtestmucommon.la $(CODE_COVERAGE_LIBS) test_mu_threads_LDADD=${top_builddir}/lib/libtestmucommon.la $(CODE_COVERAGE_LIBS)
# we need to use dummy.cc to enforce c++ linking...
BUILT_SOURCES+= \
dummy.cc
dummy.cc:
touch dummy.cc
TESTS=$(TEST_PROGS) TESTS=$(TEST_PROGS)
include $(top_srcdir)/aminclude_static.am include $(top_srcdir)/aminclude_static.am

View File

@ -18,16 +18,20 @@
#include "config.h" #include "config.h"
#include <string>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include "mu-cmd.h" #include "mu-cmd.hh"
#include "mu-contacts.hh" #include "mu-contacts.hh"
#include "mu-runtime.h" #include "mu-runtime.h"
#include "utils/mu-util.h" #include "utils/mu-util.h"
#include "utils/mu-utils.hh"
#include "utils/mu-error.hh"
#include "utils/mu-str.h" #include "utils/mu-str.h"
#include "utils/mu-date.h" #include "utils/mu-date.h"
@ -174,10 +178,8 @@ leave:
return nick; return nick;
} }
static void static void
print_header (MuConfigFormat format) print_header (const MuConfigFormat format)
{ {
switch (format) { switch (format) {
case MU_CONFIG_FORMAT_BBDB: case MU_CONFIG_FORMAT_BBDB:
@ -193,18 +195,18 @@ print_header (MuConfigFormat format)
} }
static void static void
each_contact_bbdb (const char *email, const char *name, time_t tstamp) each_contact_bbdb (const std::string& email, const std::string& name, time_t tstamp)
{ {
char *fname, *lname, *now, *timestamp; char *fname, *lname, *now, *timestamp;
fname = guess_first_name (name); fname = guess_first_name (name.c_str());
lname = guess_last_name (name); lname = guess_last_name (name.c_str());
now = mu_date_str ("%Y-%m-%d", time(NULL)); now = mu_date_str ("%Y-%m-%d", time(NULL));
timestamp = mu_date_str ("%Y-%m-%d", tstamp); timestamp = mu_date_str ("%Y-%m-%d", tstamp);
g_print ("[\"%s\" \"%s\" nil nil nil nil (\"%s\") " g_print ("[\"%s\" \"%s\" nil nil nil nil (\"%s\") "
"((creation-date . \"%s\") (time-stamp . \"%s\")) nil]\n", "((creation-date . \"%s\") (time-stamp . \"%s\")) nil]\n",
fname, lname, email, now, timestamp); fname, lname, email.c_str(), now, timestamp);
g_free (now); g_free (now);
g_free (timestamp); g_free (timestamp);
@ -214,89 +216,44 @@ each_contact_bbdb (const char *email, const char *name, time_t tstamp)
static void static void
each_contact_mutt_alias (const char *email, const char *name, each_contact_mutt_alias (const std::string& email, const std::string& name,
GHashTable *nicks) GHashTable *nicks)
{ {
if (name.empty())
gchar *nick;
if (!name)
return; return;
nick = guess_nick (name, nicks); char *nick = guess_nick (name.c_str(), nicks);
mu_util_print_encoded ("alias %s %s <%s>\n", mu_util_print_encoded ("alias %s %s <%s>\n",
nick, name, email); nick, name.c_str(), email.c_str());
g_free (nick);
}
static void
each_contact_wl (const char *email, const char *name, GHashTable *nicks)
{
gchar *nick;
if (!name)
return;
nick = guess_nick (name, nicks);
mu_util_print_encoded ("%s \"%s\" \"%s\"\n",
email, nick, name);
g_free (nick); g_free (nick);
} }
static void static void
each_contact_org_contact (const char *email, const char *name) each_contact_wl (const std::string& email, const std::string& name, GHashTable *nicks)
{ {
if (name) if (name.empty())
mu_util_print_encoded (
"* %s\n:PROPERTIES:\n:EMAIL: %s\n:END:\n\n",
name, email);
}
static void
print_csv_field (const char *str)
{
char *s;
if (!str)
return; return;
s = mu_str_replace (str, "\"", "\"\""); char *nick = guess_nick (name.c_str(), nicks);
if (strchr (s, ',')) mu_util_print_encoded ("%s \"%s\" \"%s\"\n", email.c_str(), nick, name.c_str());
mu_util_print_encoded ("\"%s\"", s); g_free (nick);
else
mu_util_print_encoded ("%s", s);
g_free (s);
} }
static void static void
each_contact_csv (const char *email, const char *name) print_plain (const std::string& email, const std::string& name, bool color)
{ {
print_csv_field (name); if (!name.empty()) {
mu_util_print_encoded (","); if (color)
print_csv_field (email); ::fputs (MU_COLOR_MAGENTA, stdout);
mu_util_print_encoded ("\n"); mu_util_fputs_encoded (name.c_str(), stdout);
} ::fputs (" ", stdout);
static void
print_plain (const char *email, const char *name, gboolean color)
{
if (name) {
if (color) fputs (MU_COLOR_MAGENTA, stdout);
mu_util_fputs_encoded (name, stdout);
fputs (" ", stdout);
} }
if (color) if (color)
fputs (MU_COLOR_GREEN, stdout); ::fputs (MU_COLOR_GREEN, stdout);
mu_util_fputs_encoded (email, stdout); mu_util_fputs_encoded (email.c_str(), stdout);
if (color) if (color)
fputs (MU_COLOR_DEFAULT, stdout); fputs (MU_COLOR_DEFAULT, stdout);
@ -304,92 +261,91 @@ print_plain (const char *email, const char *name, gboolean color)
fputs ("\n", stdout); fputs ("\n", stdout);
} }
typedef struct { struct ECData {
MuConfigFormat format; MuConfigFormat format;
gboolean color, personal; gboolean color, personal;
time_t after; time_t after;
GRegex *rx; GRegex *rx;
GHashTable *nicks; GHashTable *nicks;
size_t n; size_t n;
} ECData; };
static void static void
each_contact (const char *full_address, each_contact (const Mu::ContactInfo& ci, ECData& ecdata)
const char *email, const char *name, gboolean personal,
time_t last_seen, size_t freq, gint64 tstamp,
ECData *ecdata)
{ {
if (ecdata->personal && !personal) if (ecdata.personal && ci.personal)
return; return;
if (tstamp < ecdata->after) if (ci.tstamp < ecdata.after)
return; return;
if (ecdata->rx && if (ecdata.rx &&
!g_regex_match (ecdata->rx, email, 0, NULL) && !g_regex_match (ecdata.rx, ci.email.c_str(), (GRegexMatchFlags)0, NULL) &&
!g_regex_match (ecdata->rx, name ? name : "", 0, NULL)) !g_regex_match (ecdata.rx, ci.name.empty() ? "" : ci.name.c_str(), (GRegexMatchFlags)0, NULL))
return; return;
++ecdata->n; ++ecdata.n;
switch (ecdata->format) { switch (ecdata.format) {
case MU_CONFIG_FORMAT_MUTT_ALIAS: case MU_CONFIG_FORMAT_MUTT_ALIAS:
each_contact_mutt_alias (email, name, ecdata->nicks); each_contact_mutt_alias (ci.email, ci.name, ecdata.nicks);
break; break;
case MU_CONFIG_FORMAT_MUTT_AB: case MU_CONFIG_FORMAT_MUTT_AB:
mu_util_print_encoded ("%s\t%s\t\n", mu_util_print_encoded ("%s\t%s\t\n",
email, name ? name : ""); ci.email.c_str(), ci.name.c_str());
break; break;
case MU_CONFIG_FORMAT_WL: case MU_CONFIG_FORMAT_WL:
each_contact_wl (email, name, ecdata->nicks); each_contact_wl (ci.email, ci.name, ecdata.nicks);
break; break;
case MU_CONFIG_FORMAT_ORG_CONTACT: case MU_CONFIG_FORMAT_ORG_CONTACT:
each_contact_org_contact (email, name); if (!ci.name.empty())
mu_util_print_encoded("* %s\n:PROPERTIES:\n:EMAIL: %s\n:END:\n\n",
ci.name.c_str(), ci.email.c_str());
break; break;
case MU_CONFIG_FORMAT_BBDB: case MU_CONFIG_FORMAT_BBDB:
each_contact_bbdb (email, name, last_seen); each_contact_bbdb (ci.email, ci.name, ci.last_seen);
break; break;
case MU_CONFIG_FORMAT_CSV: case MU_CONFIG_FORMAT_CSV:
each_contact_csv (email, name); mu_util_print_encoded("%s,%s\n",
ci.name.empty() ? "" : Mu::quote(ci.name).c_str(),
Mu::quote(ci.email).c_str());
break; break;
case MU_CONFIG_FORMAT_DEBUG: { case MU_CONFIG_FORMAT_DEBUG: {
char datebuf[32]; char datebuf[32];
strftime(datebuf, sizeof(datebuf), "%F %T", strftime(datebuf, sizeof(datebuf), "%F %T",
gmtime(&last_seen)); gmtime(&ci.last_seen));
g_print ("%s\n\tname: %s\n\t%s\n\tpersonal: %s\n\tfreq: %zu\n" g_print ("%s\n\tname: %s\n\t%s\n\tpersonal: %s\n\tfreq: %zu\n"
"\tlast-seen: %s\n", "\tlast-seen: %s\n",
email, ci.email.c_str(),
name ? name : "<none>", ci.name.empty() ? "<none>" : ci.name.c_str(),
full_address, ci.full_address.c_str(),
personal ? "yes" : "no", ci.personal ? "yes" : "no",
freq, ci.freq,
datebuf); datebuf);
} break; } break;
default: default:
print_plain (email, name, ecdata->color); print_plain (ci.email, ci.name, ecdata.color);
} }
} }
static MuError static MuError
run_cmd_cfind (MuStore *store, run_cmd_cfind (const Mu::Store& store,
const char* pattern, const char* pattern,
gboolean personal, gboolean personal,
time_t after, time_t after,
MuConfigFormat format, const MuConfigFormat format,
gboolean color, gboolean color,
GError **err) GError **err)
{ {
gboolean rv; ECData ecdata{};
ECData ecdata;
memset(&ecdata, 0, sizeof(ecdata)); memset(&ecdata, 0, sizeof(ecdata));
if (pattern) { if (pattern) {
ecdata.rx = g_regex_new (pattern, ecdata.rx = g_regex_new (pattern,
G_REGEX_CASELESS|G_REGEX_OPTIMIZE, (GRegexCompileFlags)(G_REGEX_CASELESS|G_REGEX_OPTIMIZE),
0, err); (GRegexMatchFlags)0, err);
if (!ecdata.rx) if (!ecdata.rx)
return MU_ERROR_CONTACTS; return MU_ERROR_CONTACTS;
} }
@ -403,8 +359,9 @@ run_cmd_cfind (MuStore *store,
g_free, NULL); g_free, NULL);
print_header (format); print_header (format);
rv = mu_contacts_foreach (mu_store_contacts(store),
(MuContactsForeachFunc)each_contact, &ecdata); store.contacts().for_each([&](const auto& ci) { each_contact(ci, ecdata); });
g_hash_table_unref (ecdata.nicks); g_hash_table_unref (ecdata.nicks);
if (ecdata.rx) if (ecdata.rx)
@ -415,11 +372,11 @@ run_cmd_cfind (MuStore *store,
return MU_ERROR_NO_MATCHES; return MU_ERROR_NO_MATCHES;
} }
return rv ? MU_OK : MU_ERROR_CONTACTS; return MU_OK;
} }
static gboolean static gboolean
cfind_params_valid (MuConfig *opts) cfind_params_valid (const MuConfig *opts)
{ {
switch (opts->format) { switch (opts->format) {
case MU_CONFIG_FORMAT_PLAIN: case MU_CONFIG_FORMAT_PLAIN:
@ -447,24 +404,25 @@ cfind_params_valid (MuConfig *opts)
} }
MuError MuError
mu_cmd_cfind (MuStore *store, MuConfig *opts, GError **err) mu_cmd_cfind (const Mu::Store& store, const MuConfig *opts, GError **err)
{ {
g_return_val_if_fail (store, MU_ERROR_INTERNAL);
g_return_val_if_fail (opts, MU_ERROR_INTERNAL); g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_CFIND, g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_CFIND,
MU_ERROR_INTERNAL); MU_ERROR_INTERNAL);
if (!cfind_params_valid (opts)) { if (!cfind_params_valid (opts))
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_IN_PARAMETERS, throw Mu::Error(Mu::Error::Code::InvalidArgument,
"invalid parameters"); "invalid parameters");
return MU_ERROR_IN_PARAMETERS;
}
return run_cmd_cfind (store, auto res = run_cmd_cfind (store,
opts->params[1], opts->params[1],
opts->personal, opts->personal,
opts->after, opts->after,
opts->format, opts->format,
!opts->nocolor, !opts->nocolor,
err); err);
if (res != MU_OK)
throw Mu::Error(Mu::Error::Code::Internal, err/*consumes*/,
"error in cfind");
return MU_OK;
} }

View File

@ -1,7 +1,5 @@
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/
/* /*
** Copyright (C) 2010-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ** Copyright (C) 2010-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** **
** This program is free software; you can redistribute it and/or modify it ** 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 ** under the terms of the GNU General Public License as published by the
@ -19,22 +17,20 @@
** **
*/ */
#if HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif /*HAVE_CONFIG_H*/
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "mu-msg.h" #include "mu-msg.h"
#include "mu-msg-part.h" #include "mu-msg-part.h"
#include "mu-cmd.h" #include "mu-cmd.hh"
#include "utils/mu-util.h" #include "utils/mu-util.h"
#include "utils/mu-str.h" #include "utils/mu-str.h"
static gboolean static gboolean
save_part (MuMsg *msg, const char *targetdir, guint partidx, MuConfig *opts) save_part (MuMsg *msg, const char *targetdir, guint partidx, const MuConfig *opts)
{ {
GError *err; GError *err;
gchar *filepath; gchar *filepath;
@ -70,7 +66,7 @@ exit:
static gboolean static gboolean
save_numbered_parts (MuMsg *msg, MuConfig *opts) save_numbered_parts (MuMsg *msg, const MuConfig *opts)
{ {
gboolean rv; gboolean rv;
char **parts, **cur; char **parts, **cur;
@ -116,8 +112,9 @@ anchored_regex (const char* pattern)
pattern[strlen(pattern)-1] == '$' ? "" : "$"); pattern[strlen(pattern)-1] == '$' ? "" : "$");
err = NULL; err = NULL;
rx = g_regex_new (anchored, G_REGEX_CASELESS|G_REGEX_OPTIMIZE, 0, rx = g_regex_new (anchored,
&err); (GRegexCompileFlags)(G_REGEX_CASELESS|G_REGEX_OPTIMIZE),
(GRegexMatchFlags)0, &err);
g_free (anchored); g_free (anchored);
if (!rx) { if (!rx) {
@ -132,7 +129,7 @@ anchored_regex (const char* pattern)
static gboolean static gboolean
save_part_with_filename (MuMsg *msg, const char *pattern, MuConfig *opts) save_part_with_filename (MuMsg *msg, const char *pattern, const MuConfig *opts)
{ {
GSList *lst, *cur; GSList *lst, *cur;
GRegex *rx; GRegex *rx;
@ -164,7 +161,7 @@ save_part_with_filename (MuMsg *msg, const char *pattern, MuConfig *opts)
struct _SaveData { struct _SaveData {
gboolean result; gboolean result;
guint saved_num; guint saved_num;
MuConfig *opts; const MuConfig *opts;
}; };
typedef struct _SaveData SaveData; typedef struct _SaveData SaveData;
@ -232,7 +229,7 @@ exit:
} }
static gboolean static gboolean
save_certain_parts (MuMsg *msg, MuConfig *opts) save_certain_parts (MuMsg *msg, const MuConfig *opts)
{ {
SaveData sd; SaveData sd;
MuMsgOptions msgopts; MuMsgOptions msgopts;
@ -256,7 +253,7 @@ save_certain_parts (MuMsg *msg, MuConfig *opts)
static gboolean static gboolean
save_parts (const char *path, const char *filename, MuConfig *opts) save_parts (const char *path, const char *filename, const MuConfig *opts)
{ {
MuMsg* msg; MuMsg* msg;
gboolean rv; gboolean rv;
@ -336,7 +333,7 @@ each_part_show (MuMsg *msg, MuMsgPart *part, gboolean color)
static gboolean static gboolean
show_parts (const char* path, MuConfig *opts, GError **err) show_parts (const char* path, const MuConfig *opts, GError **err)
{ {
MuMsg *msg; MuMsg *msg;
MuMsgOptions msgopts; MuMsgOptions msgopts;
@ -362,7 +359,7 @@ show_parts (const char* path, MuConfig *opts, GError **err)
static gboolean static gboolean
check_params (MuConfig *opts, GError **err) check_params (const MuConfig *opts, GError **err)
{ {
size_t param_num; size_t param_num;
@ -396,7 +393,7 @@ check_params (MuConfig *opts, GError **err)
} }
MuError MuError
mu_cmd_extract (MuConfig *opts, GError **err) mu_cmd_extract (const MuConfig *opts, GError **err)
{ {
int rv; int rv;

View File

@ -1,5 +1,5 @@
/* /*
** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ** Copyright (C) 2008-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** **
** This program is free software; you can redistribute it and/or modify it ** 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 ** under the terms of the GNU General Public License as published by the
@ -17,9 +17,7 @@
** **
*/ */
#if HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif /*HAVE_CONFIG_H*/
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
@ -40,7 +38,7 @@
#include "utils/mu-str.h" #include "utils/mu-str.h"
#include "utils/mu-date.h" #include "utils/mu-date.h"
#include "mu-cmd.h" #include "mu-cmd.hh"
#include "mu-threader.h" #include "mu-threader.h"
#ifdef HAVE_JSON_GLIB #ifdef HAVE_JSON_GLIB
@ -48,7 +46,7 @@
#endif /*HAVE_JSON_GLIB*/ #endif /*HAVE_JSON_GLIB*/
typedef gboolean (OutputFunc) (MuMsg *msg, MuMsgIter *iter, typedef gboolean (OutputFunc) (MuMsg *msg, MuMsgIter *iter,
MuConfig *opts, GError **err); const MuConfig *opts, GError **err);
static gboolean static gboolean
print_internal (MuQuery *query, const gchar *expr, gboolean xapian, print_internal (MuQuery *query, const gchar *expr, gboolean xapian,
@ -115,11 +113,11 @@ get_message (MuMsgIter *iter, time_t after)
} }
static MuMsgIter* static MuMsgIter*
run_query (MuQuery *xapian, const gchar *query, MuConfig *opts, GError **err) run_query (MuQuery *xapian, const gchar *query, const MuConfig *opts, GError **err)
{ {
MuMsgIter *iter; MuMsgIter *iter;
MuMsgFieldId sortid; MuMsgFieldId sortid;
MuQueryFlags qflags; int qflags;
sortid = MU_MSG_FIELD_ID_NONE; sortid = MU_MSG_FIELD_ID_NONE;
if (opts->sortfield) { if (opts->sortfield) {
@ -138,12 +136,13 @@ run_query (MuQuery *xapian, const gchar *query, MuConfig *opts, GError **err)
if (opts->threads) if (opts->threads)
qflags |= MU_QUERY_FLAG_THREADS; qflags |= MU_QUERY_FLAG_THREADS;
iter = mu_query_run (xapian, query, sortid, opts->maxnum, qflags, err); iter = mu_query_run (xapian, query, sortid, opts->maxnum,
(MuQueryFlags)qflags, err);
return iter; return iter;
} }
static gboolean static gboolean
exec_cmd (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err) exec_cmd (MuMsg *msg, MuMsgIter *iter, const MuConfig *opts, GError **err)
{ {
gint status; gint status;
char *cmdline, *escpath; char *cmdline, *escpath;
@ -161,7 +160,7 @@ exec_cmd (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err)
} }
static gchar* static gchar*
resolve_bookmark (MuConfig *opts, GError **err) resolve_bookmark (const MuConfig *opts, GError **err)
{ {
MuBookmarks *bm; MuBookmarks *bm;
char* val; char* val;
@ -187,7 +186,7 @@ resolve_bookmark (MuConfig *opts, GError **err)
} }
static gchar* static gchar*
get_query (MuConfig *opts, GError **err) get_query (const MuConfig *opts, GError **err)
{ {
gchar *query, *bookmarkval; gchar *query, *bookmarkval;
@ -243,7 +242,7 @@ get_query_obj (MuStore *store, GError **err)
} }
static gboolean static gboolean
prepare_links (MuConfig *opts, GError **err) prepare_links (const MuConfig *opts, GError **err)
{ {
/* note, mu_maildir_mkdir simply ignores whatever part of the /* note, mu_maildir_mkdir simply ignores whatever part of the
* mail dir already exists */ * mail dir already exists */
@ -266,7 +265,7 @@ prepare_links (MuConfig *opts, GError **err)
} }
static gboolean static gboolean
output_link (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err) output_link (MuMsg *msg, MuMsgIter *iter, const MuConfig *opts, GError **err)
{ {
if (mu_msg_iter_is_first (iter) && !prepare_links (opts, err)) if (mu_msg_iter_is_first (iter) && !prepare_links (opts, err))
return FALSE; return FALSE;
@ -381,7 +380,7 @@ display_field (MuMsg *msg, MuMsgFieldId mfid)
} }
static void static void
print_summary (MuMsg *msg, MuConfig *opts) print_summary (MuMsg *msg, const MuConfig *opts)
{ {
const char* body; const char* body;
char *summ; char *summ;
@ -472,7 +471,7 @@ output_plain_fields (MuMsg *msg, const char *fields,
} }
static gboolean static gboolean
output_plain (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err) output_plain (MuMsg *msg, MuMsgIter *iter, const MuConfig *opts, GError **err)
{ {
/* we reuse the color (whatever that may be) /* we reuse the color (whatever that may be)
* for message-priority for threads, too */ * for message-priority for threads, too */
@ -489,7 +488,7 @@ output_plain (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err)
} }
static gboolean static gboolean
output_sexp (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err) output_sexp (MuMsg *msg, MuMsgIter *iter, const MuConfig *opts, GError **err)
{ {
char *sexp; char *sexp;
const MuMsgIterThreadInfo *ti; const MuMsgIterThreadInfo *ti;
@ -504,7 +503,7 @@ output_sexp (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err)
} }
static gboolean static gboolean
output_json (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err) output_json (MuMsg *msg, MuMsgIter *iter, const MuConfig *opts, GError **err)
{ {
#ifdef HAVE_JSON_GLIB #ifdef HAVE_JSON_GLIB
JsonNode *node; JsonNode *node;
@ -552,7 +551,7 @@ print_attr_xml (const char* elm, const char *str)
} }
static gboolean static gboolean
output_xml (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err) output_xml (MuMsg *msg, MuMsgIter *iter, const MuConfig *opts, GError **err)
{ {
if (mu_msg_iter_is_first(iter)) { if (mu_msg_iter_is_first(iter)) {
g_print ("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); g_print ("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
@ -579,7 +578,7 @@ output_xml (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err)
} }
static OutputFunc* static OutputFunc*
get_output_func (MuConfig *opts, GError **err) get_output_func (const MuConfig *opts, GError **err)
{ {
switch (opts->format) { switch (opts->format) {
case MU_CONFIG_FORMAT_LINKS: return output_link; case MU_CONFIG_FORMAT_LINKS: return output_link;
@ -596,7 +595,7 @@ get_output_func (MuConfig *opts, GError **err)
} }
static gboolean static gboolean
output_query_results (MuMsgIter *iter, MuConfig *opts, GError **err) output_query_results (MuMsgIter *iter, const MuConfig *opts, GError **err)
{ {
int count; int count;
gboolean rv; gboolean rv;
@ -639,7 +638,7 @@ output_query_results (MuMsgIter *iter, MuConfig *opts, GError **err)
} }
static gboolean static gboolean
process_query (MuQuery *xapian, const gchar *query, MuConfig *opts, GError **err) process_query (MuQuery *xapian, const gchar *query, const MuConfig *opts, GError **err)
{ {
MuMsgIter *iter; MuMsgIter *iter;
gboolean rv; gboolean rv;
@ -655,7 +654,7 @@ process_query (MuQuery *xapian, const gchar *query, MuConfig *opts, GError **err
} }
static gboolean static gboolean
execute_find (MuStore *store, MuConfig *opts, GError **err) execute_find (MuStore *store, const MuConfig *opts, GError **err)
{ {
char *query_str; char *query_str;
MuQuery *oracle; MuQuery *oracle;
@ -686,7 +685,7 @@ execute_find (MuStore *store, MuConfig *opts, GError **err)
} }
static gboolean static gboolean
format_params_valid (MuConfig *opts, GError **err) format_params_valid (const MuConfig *opts, GError **err)
{ {
switch (opts->format) { switch (opts->format) {
case MU_CONFIG_FORMAT_EXEC: case MU_CONFIG_FORMAT_EXEC:
@ -727,7 +726,7 @@ format_params_valid (MuConfig *opts, GError **err)
} }
static gboolean static gboolean
query_params_valid (MuConfig *opts, GError **err) query_params_valid (const MuConfig *opts, GError **err)
{ {
const gchar *xpath; const gchar *xpath;
@ -748,20 +747,22 @@ query_params_valid (MuConfig *opts, GError **err)
} }
MuError MuError
mu_cmd_find (MuStore *store, MuConfig *opts, GError **err) mu_cmd_find (MuStore *store, const MuConfig *opts, GError **err)
{ {
g_return_val_if_fail (opts, MU_ERROR_INTERNAL); g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_FIND, g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_FIND,
MU_ERROR_INTERNAL); MU_ERROR_INTERNAL);
if (opts->exec) MuConfig myopts{*opts};
opts->format = MU_CONFIG_FORMAT_EXEC; /* pseudo format */
if (!query_params_valid (opts, err) || if (myopts.exec)
!format_params_valid(opts, err)) myopts.format = MU_CONFIG_FORMAT_EXEC; /* pseudo format */
if (!query_params_valid (&myopts, err) ||
!format_params_valid(&myopts, err))
return MU_G_ERROR_CODE (err); return MU_G_ERROR_CODE (err);
if (!execute_find (store, opts, err)) if (!execute_find (store, &myopts, err))
return MU_G_ERROR_CODE(err); return MU_G_ERROR_CODE(err);
else else
return MU_OK; return MU_OK;

View File

@ -17,11 +17,8 @@
** **
*/ */
#if HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif /*HAVE_CONFIG_H*/ #include "mu-cmd.hh"
#include "mu-cmd.h"
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
@ -70,7 +67,7 @@ install_sig_handler (void)
static gboolean static gboolean
check_params (MuConfig *opts, GError **err) check_params (const MuConfig *opts, GError **err)
{ {
/* param[0] == 'index' there should be no param[1] */ /* param[0] == 'index' there should be no param[1] */
if (opts->params[1]) { if (opts->params[1]) {
@ -178,7 +175,7 @@ show_time (unsigned t, unsigned processed, gboolean color)
} }
static MuError static MuError
cleanup_missing (MuIndex *midx, MuConfig *opts, MuIndexStats *stats, cleanup_missing (MuIndex *midx, const MuConfig *opts, MuIndexStats *stats,
GError **err) GError **err)
{ {
MuError rv; MuError rv;
@ -213,7 +210,7 @@ cleanup_missing (MuIndex *midx, MuConfig *opts, MuIndexStats *stats,
} }
static MuError static MuError
cmd_index (MuIndex *midx, MuConfig *opts, MuIndexStats *stats, GError **err) cmd_index (MuIndex *midx, const MuConfig *opts, MuIndexStats *stats, GError **err)
{ {
IndexData idata; IndexData idata;
MuError rv; MuError rv;
@ -240,7 +237,7 @@ cmd_index (MuIndex *midx, MuConfig *opts, MuIndexStats *stats, GError **err)
static MuIndex* static MuIndex*
init_mu_index (MuStore *store, MuConfig *opts, GError **err) init_mu_index (MuStore *store, const MuConfig *opts, GError **err)
{ {
MuIndex *midx; MuIndex *midx;
@ -257,28 +254,26 @@ init_mu_index (MuStore *store, MuConfig *opts, GError **err)
} }
MuError MuError
mu_cmd_index (MuStore *store, MuConfig *opts, GError **err) mu_cmd_index (Mu::Store& store, const MuConfig *opts, GError **err)
{ {
MuIndex *midx; MuIndex *midx;
MuIndexStats stats; MuIndexStats stats;
gboolean rv; gboolean rv;
time_t t; time_t t;
g_return_val_if_fail (opts, FALSE); g_return_val_if_fail (opts, MU_ERROR);
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_INDEX, g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_INDEX, MU_ERROR);
FALSE);
/* create, and do error handling if needed */ /* create, and do error handling if needed */
midx = init_mu_index (store, opts, err); midx = init_mu_index (reinterpret_cast<MuStore*>(&store), // ugh.
opts, err);
if (!midx) if (!midx)
return MU_G_ERROR_CODE(err); throw Mu::Error(Mu::Error::Code::Internal, err/*consumes*/,
"error in index");
mu_index_stats_clear (&stats); mu_index_stats_clear (&stats);
install_sig_handler (); install_sig_handler ();
if (!opts->quiet)
mu_store_print_info (store, opts->nocolor);
t = time (NULL); t = time (NULL);
rv = cmd_index (midx, opts, &stats, err); rv = cmd_index (midx, opts, &stats, err);
@ -297,5 +292,9 @@ mu_cmd_index (MuStore *store, MuConfig *opts, GError **err)
mu_index_destroy (midx); mu_index_destroy (midx);
return rv; if (rv != MU_OK)
throw Mu::Error(Mu::Error::Code::Internal, err/*consumes*/,
"error in index");
return rv ? MU_OK : MU_ERROR;
} }

View File

@ -29,7 +29,7 @@
#include <dirent.h> #include <dirent.h>
#include <errno.h> #include <errno.h>
#include "mu-cmd.h" #include "mu-cmd.hh"
#include "mu-script.h" #include "mu-script.h"
#include "mu-runtime.h" #include "mu-runtime.h"
@ -151,7 +151,7 @@ get_script_info_list (const char *muhome, GError **err)
static gboolean static gboolean
check_params (MuConfig *opts, GError **err) check_params (const MuConfig *opts, GError **err)
{ {
if (!mu_util_supports (MU_FEATURE_GUILE)) { if (!mu_util_supports (MU_FEATURE_GUILE)) {
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
@ -165,7 +165,7 @@ check_params (MuConfig *opts, GError **err)
MuError MuError
mu_cmd_script (MuConfig *opts, GError **err) mu_cmd_script (const MuConfig *opts, GError **err)
{ {
MuScriptInfo *msi; MuScriptInfo *msi;
GSList *scripts; GSList *scripts;

View File

@ -18,7 +18,7 @@
*/ */
#include "config.h" #include "config.h"
#include "mu-cmd.h" #include "mu-cmd.hh"
#include <iostream> #include <iostream>
#include <string> #include <string>
@ -29,7 +29,7 @@
#include <glib/gprintf.h> #include <glib/gprintf.h>
#include "mu-runtime.h" #include "mu-runtime.h"
#include "mu-cmd.h" #include "mu-cmd.hh"
#include "mu-maildir.h" #include "mu-maildir.h"
#include "mu-query.h" #include "mu-query.h"
#include "mu-index.h" #include "mu-index.h"
@ -211,7 +211,7 @@ print_sexps (MuMsgIter *iter, unsigned maxnum)
struct Context { struct Context {
Context(){} Context(){}
Context (MuConfig *opts) { Context (const MuConfig *opts) {
const auto dbpath{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB)}; const auto dbpath{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB)};
GError *gerr{}; GError *gerr{};
store = mu_store_new_writable (dbpath, NULL); store = mu_store_new_writable (dbpath, NULL);
@ -314,86 +314,33 @@ add_handler (Context& context, const Parameters& params)
} }
struct _PartInfo { struct PartInfo {
GSList *attlist; Node::Seq attseq;
MuMsgOptions opts; MuMsgOptions opts;
}; };
typedef struct _PartInfo PartInfo;
static void static void
each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo) each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo)
{ {
char *att, *cachefile; /* exclude things that don't look like proper attachments, unless they're images */
/* exclude things that don't look like proper attachments,
* unless they're images */
if (!mu_msg_part_maybe_attachment(part)) if (!mu_msg_part_maybe_attachment(part))
return; return;
GError *gerr{}; GError *gerr{};
cachefile = mu_msg_part_save_temp (msg, char *cachefile = mu_msg_part_save_temp (
(MuMsgOptions)(pinfo->opts|MU_MSG_OPTION_OVERWRITE), msg, (MuMsgOptions)(pinfo->opts|MU_MSG_OPTION_OVERWRITE),
part->index, &gerr); part->index, &gerr);
if (!cachefile) if (!cachefile)
throw Error (Error::Code::File, &gerr, "failed to save part"); throw Error (Error::Code::File, &gerr, "failed to save part");
att = g_strdup_printf ("(:file-name %s :mime-type \"%s/%s\")", Node::Seq seq;
quote(cachefile).c_str(), part->type, part->subtype); seq.add_prop(":file-name", cachefile);
pinfo->attlist = g_slist_append (pinfo->attlist, att); seq.add_prop(":mime-type", format("%s/%s", part->type, part->subtype));
pinfo->attseq.add(std::move(seq));
g_free (cachefile); g_free (cachefile);
} }
/* take the attachments of msg, save them as tmp files, and return
* as sexp (as a string) describing them
*
* ((:name <filename> :mime-type <mime-type> :disposition
* <attachment|inline>) ... )
*
*/
static gchar*
include_attachments (MuMsg *msg, MuMsgOptions opts)
{
GSList *cur;
GString *gstr;
PartInfo pinfo;
pinfo.attlist = NULL;
pinfo.opts = opts;
mu_msg_part_foreach (msg, opts,
(MuMsgPartForeachFunc)each_part,
&pinfo);
gstr = g_string_sized_new (512);
gstr = g_string_append_c (gstr, '(');
for (cur = pinfo.attlist; cur; cur = g_slist_next (cur))
g_string_append (gstr, (gchar*)cur->data);
gstr = g_string_append_c (gstr, ')');
mu_str_free_list (pinfo.attlist);
return g_string_free (gstr, FALSE);
}
enum { NEW, REPLY, FORWARD, EDIT, RESEND, INVALID_TYPE };
static unsigned
compose_type (const char *typestr)
{
if (g_str_equal (typestr, "reply"))
return REPLY;
else if (g_str_equal (typestr, "forward"))
return FORWARD;
else if (g_str_equal (typestr, "edit"))
return EDIT;
else if (g_str_equal (typestr, "resend"))
return RESEND;
else if (g_str_equal (typestr, "new"))
return NEW;
else
return INVALID_TYPE;
}
/* 'compose' produces the un-changed *original* message sexp (ie., the message /* 'compose' produces the un-changed *original* message sexp (ie., the message
* to reply to, forward or edit) for a new message to compose). It takes two * to reply to, forward or edit) for a new message to compose). It takes two
* parameters: 'type' with the compose type (either reply, forward or * parameters: 'type' with the compose type (either reply, forward or
@ -408,15 +355,15 @@ compose_type (const char *typestr)
static void static void
compose_handler (Context& context, const Parameters& params) compose_handler (Context& context, const Parameters& params)
{ {
const auto typestr{get_symbol_or(params, "type")}; auto ctype{get_symbol_or(params, "type")};
const auto ctype{compose_type(typestr.c_str())};
if (ctype == INVALID_TYPE) Node::Seq compose_seq;
throw Error(Error::Code::InvalidArgument, "invalid compose type"); compose_seq.add_prop(":compose", ctype);
// message optioss below checks extract-images / extract-encrypted // message optioss below checks extract-images / extract-encrypted
char *sexp{}, *atts{};
if (ctype == REPLY || ctype == FORWARD || ctype == EDIT || ctype == RESEND) { if (ctype == "reply" || ctype == "forward" || ctype == "edit" || ctype == "resend") {
GError *gerr{}; GError *gerr{};
const unsigned docid{(unsigned)get_int_or(params, "docid")}; const unsigned docid{(unsigned)get_int_or(params, "docid")};
@ -425,16 +372,22 @@ compose_handler (Context& context, const Parameters& params)
throw Error{Error::Code::Store, &gerr, "failed to get message %u", docid}; throw Error{Error::Code::Store, &gerr, "failed to get message %u", docid};
const auto opts{message_options(params)}; const auto opts{message_options(params)};
sexp = mu_msg_to_sexp (msg, docid, NULL, opts); compose_seq.add_prop(":original", Mu::msg_to_sexp(msg, docid, {}, opts));
atts = (ctype == FORWARD) ? include_attachments (msg, opts) : NULL;
if (ctype == "forward") {
PartInfo pinfo{};
pinfo.opts = opts;
mu_msg_part_foreach (msg, opts,
(MuMsgPartForeachFunc)each_part, &pinfo);
if (!pinfo.attseq.empty())
compose_seq.add_prop (":include", std::move(pinfo.attseq));
}
mu_msg_unref (msg); mu_msg_unref (msg);
}
print_expr ("(:compose %s :original %s :include %s)", } else if (ctype != "new")
typestr.c_str(), sexp ? sexp : "nil", atts ? atts : "nil"); throw Error(Error::Code::InvalidArgument, "invalid compose type");
g_free (sexp); print_expr (std::move(compose_seq));
g_free (atts);
} }
@ -1318,7 +1271,7 @@ make_command_map (Context& context)
} }
MuError MuError
mu_cmd_server (MuConfig *opts, GError **err) try mu_cmd_server (const MuConfig *opts, GError **err) try
{ {
if (opts->commands) { if (opts->commands) {
Context ctx{}; Context ctx{};
@ -1336,7 +1289,6 @@ mu_cmd_server (MuConfig *opts, GError **err) try
return MU_OK; return MU_OK;
} }
const auto histpath{std::string{mu_runtime_path(MU_RUNTIME_PATH_CACHE)} + "/history"}; const auto histpath{std::string{mu_runtime_path(MU_RUNTIME_PATH_CACHE)} + "/history"};
setup_readline(histpath, 50); setup_readline(histpath, 50);

View File

@ -19,6 +19,8 @@
#include "config.h" #include "config.h"
#include <iostream>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -27,7 +29,7 @@
#include "mu-msg.h" #include "mu-msg.h"
#include "mu-msg-part.h" #include "mu-msg-part.h"
#include "mu-cmd.h" #include "mu-cmd.hh"
#include "mu-maildir.h" #include "mu-maildir.h"
#include "mu-contacts.hh" #include "mu-contacts.hh"
#include "mu-runtime.h" #include "mu-runtime.h"
@ -37,10 +39,12 @@
#include "utils/mu-str.h" #include "utils/mu-str.h"
#include "utils/mu-date.h" #include "utils/mu-date.h"
#include "utils/mu-error.hh"
#define VIEW_TERMINATOR '\f' /* form-feed */ #define VIEW_TERMINATOR '\f' /* form-feed */
static gboolean static gboolean
view_msg_sexp (MuMsg *msg, MuConfig *opts) view_msg_sexp (MuMsg *msg, const MuConfig *opts)
{ {
char *sexp; char *sexp;
@ -74,13 +78,12 @@ each_part (MuMsg *msg, MuMsgPart *part, gchar **attach)
/* return comma-sep'd list of attachments */ /* return comma-sep'd list of attachments */
static gchar * static gchar *
get_attach_str (MuMsg *msg, MuConfig *opts) get_attach_str (MuMsg *msg, const MuConfig *opts)
{ {
gchar *attach; gchar *attach;
MuMsgOptions msgopts;
msgopts = mu_config_get_msg_options(opts) | const auto msgopts = (MuMsgOptions)
MU_MSG_OPTION_CONSOLE_PASSWORD; (mu_config_get_msg_options(opts) | MU_MSG_OPTION_CONSOLE_PASSWORD);
attach = NULL; attach = NULL;
mu_msg_part_foreach (msg, msgopts, mu_msg_part_foreach (msg, msgopts,
@ -113,15 +116,15 @@ print_field (const char* field, const char *val, gboolean color)
/* a summary_len of 0 mean 'don't show summary, show body */ /* a summary_len of 0 mean 'don't show summary, show body */
static void static void
body_or_summary (MuMsg *msg, MuConfig *opts) body_or_summary (MuMsg *msg, const MuConfig *opts)
{ {
const char *body; const char *body;
gboolean color; gboolean color;
int my_opts = mu_config_get_msg_options(opts) |
MU_MSG_OPTION_CONSOLE_PASSWORD;
color = !opts->nocolor; color = !opts->nocolor;
body = mu_msg_get_body_text (msg, body = mu_msg_get_body_text (msg, (MuMsgOptions)my_opts);
mu_config_get_msg_options(opts) |
MU_MSG_OPTION_CONSOLE_PASSWORD);
if (!body) { if (!body) {
if (mu_msg_get_flags (msg) & MU_FLAG_ENCRYPTED) { if (mu_msg_get_flags (msg) & MU_FLAG_ENCRYPTED) {
color_maybe (MU_COLOR_CYAN); color_maybe (MU_COLOR_CYAN);
@ -151,7 +154,7 @@ body_or_summary (MuMsg *msg, MuConfig *opts)
/* we ignore fields for now */ /* we ignore fields for now */
/* summary_len == 0 means "no summary */ /* summary_len == 0 means "no summary */
static gboolean static gboolean
view_msg_plain (MuMsg *msg, MuConfig *opts) view_msg_plain (MuMsg *msg, const MuConfig *opts)
{ {
gchar *attachs; gchar *attachs;
time_t date; time_t date;
@ -189,7 +192,7 @@ view_msg_plain (MuMsg *msg, MuConfig *opts)
static gboolean static gboolean
handle_msg (const char *fname, MuConfig *opts, GError **err) handle_msg (const char *fname, const MuConfig *opts, GError **err)
{ {
MuMsg *msg; MuMsg *msg;
gboolean rv; gboolean rv;
@ -216,7 +219,7 @@ handle_msg (const char *fname, MuConfig *opts, GError **err)
} }
static gboolean static gboolean
view_params_valid (MuConfig *opts, GError **err) view_params_valid (const MuConfig *opts, GError **err)
{ {
/* note: params[0] will be 'view' */ /* note: params[0] will be 'view' */
if (!opts->params[0] || !opts->params[1]) { if (!opts->params[0] || !opts->params[1]) {
@ -240,7 +243,7 @@ view_params_valid (MuConfig *opts, GError **err)
static MuError static MuError
cmd_view (MuConfig *opts, GError **err) cmd_view (const MuConfig *opts, GError **err)
{ {
int i; int i;
gboolean rv; gboolean rv;
@ -266,13 +269,13 @@ cmd_view (MuConfig *opts, GError **err)
leave: leave:
if (!rv) if (!rv)
return err && *err ? (*err)->code : MU_ERROR; return err && *err ? (MuError)(*err)->code : MU_ERROR;
return MU_OK; return MU_OK;
} }
static MuError static MuError
cmd_mkdir (MuConfig *opts, GError **err) cmd_mkdir (const MuConfig *opts, GError **err)
{ {
int i; int i;
@ -289,7 +292,7 @@ cmd_mkdir (MuConfig *opts, GError **err)
for (i = 1; opts->params[i]; ++i) for (i = 1; opts->params[i]; ++i)
if (!mu_maildir_mkdir (opts->params[i], opts->dirmode, if (!mu_maildir_mkdir (opts->params[i], opts->dirmode,
FALSE, err)) FALSE, err))
return err && *err ? (*err)->code : return err && *err ? (MuError)(*err)->code :
MU_ERROR_FILE_CANNOT_MKDIR; MU_ERROR_FILE_CANNOT_MKDIR;
return MU_OK; return MU_OK;
} }
@ -312,13 +315,10 @@ check_file_okay (const char *path, gboolean cmd_add)
return TRUE; return TRUE;
} }
typedef bool (*ForeachMsgFunc) (Mu::Store& store, const char *path, GError **err);
typedef gboolean (*ForeachMsgFunc) (MuStore *store, const char *path,
GError **err);
static MuError static MuError
foreach_msg_file (MuStore *store, MuConfig *opts, foreach_msg_file (Mu::Store& store, const MuConfig *opts,
ForeachMsgFunc foreach_func, GError **err) ForeachMsgFunc foreach_func, GError **err)
{ {
unsigned u; unsigned u;
@ -366,17 +366,19 @@ foreach_msg_file (MuStore *store, MuConfig *opts,
} }
static gboolean static bool
add_path_func (MuStore *store, const char *path, GError **err) add_path_func (Mu::Store& store, const char *path, GError **err)
{ {
return mu_store_add_path (store, path, err); const auto docid = store.add_message (path);
g_debug ("added message @ %s, docid=%u", docid);
return true;
} }
static MuError static MuError
cmd_add (MuStore *store, MuConfig *opts, GError **err) cmd_add (Mu::Store& store, const MuConfig *opts, GError **err)
{ {
g_return_val_if_fail (store, MU_ERROR_INTERNAL);
g_return_val_if_fail (opts, MU_ERROR_INTERNAL); g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_ADD, g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_ADD,
MU_ERROR_INTERNAL); MU_ERROR_INTERNAL);
@ -384,20 +386,17 @@ cmd_add (MuStore *store, MuConfig *opts, GError **err)
return foreach_msg_file (store, opts, add_path_func, err); return foreach_msg_file (store, opts, add_path_func, err);
} }
static gboolean static bool
remove_path_func (MuStore *store, const char *path, GError **err) remove_path_func (Mu::Store& store, const char *path, GError **err)
{ {
if (!mu_store_remove_path (store, path)) { const auto res = store.remove_message (path);
mu_util_g_set_error (err, MU_ERROR_XAPIAN_REMOVE_FAILED, g_debug ("removed %s (%s)", path, res ? "yes" : "no");
"failed to remove %s", path);
return FALSE;
}
return TRUE; return true;
} }
static MuError static MuError
cmd_remove (MuStore *store, MuConfig *opts, GError **err) cmd_remove (Mu::Store& store, const MuConfig *opts, GError **err)
{ {
g_return_val_if_fail (opts, MU_ERROR_INTERNAL); g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_REMOVE, g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_REMOVE,
@ -406,25 +405,23 @@ cmd_remove (MuStore *store, MuConfig *opts, GError **err)
return foreach_msg_file (store, opts, remove_path_func, err); return foreach_msg_file (store, opts, remove_path_func, err);
} }
static gboolean static bool
tickle_func (MuStore *store, const char *path, GError **err) tickle_func (Mu::Store& store, const char *path, GError **err)
{ {
MuMsg *msg; MuMsg *msg{mu_msg_new_from_file (path, NULL, err)};
gboolean rv;
msg = mu_msg_new_from_file (path, NULL, err);
if (!msg) if (!msg)
return FALSE; return false;
rv = mu_msg_tickle (msg, err); const auto res = mu_msg_tickle (msg, err);
g_debug ("tickled %s (%s)", res ? "ok" : "failed");
mu_msg_unref (msg); mu_msg_unref (msg);
return rv; return res == TRUE;
} }
static MuError static MuError
cmd_tickle (MuStore *store, MuConfig *opts, GError **err) cmd_tickle (Mu::Store& store, const MuConfig *opts, GError **err)
{ {
g_return_val_if_fail (opts, MU_ERROR_INTERNAL); g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_TICKLE, g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_TICKLE,
@ -509,11 +506,11 @@ print_verdict (VData *vdata, gboolean color, gboolean verbose)
static MuError static MuError
cmd_verify (MuConfig *opts, GError **err) cmd_verify (const MuConfig *opts, GError **err)
{ {
MuMsg *msg; MuMsg *msg;
MuMsgOptions msgopts; int msgopts;
VData vdata; VData vdata;
g_return_val_if_fail (opts, MU_ERROR_INTERNAL); g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_VERIFY, g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_VERIFY,
@ -537,7 +534,7 @@ cmd_verify (MuConfig *opts, GError **err)
vdata.combined_status = MU_MSG_PART_SIG_STATUS_UNSIGNED; vdata.combined_status = MU_MSG_PART_SIG_STATUS_UNSIGNED;
vdata.oneline = FALSE; vdata.oneline = FALSE;
mu_msg_part_foreach (msg, msgopts, mu_msg_part_foreach (msg, (MuMsgOptions)msgopts,
(MuMsgPartForeachFunc)each_sig, &vdata); (MuMsgPartForeachFunc)each_sig, &vdata);
if (!opts->quiet) if (!opts->quiet)
@ -551,20 +548,51 @@ cmd_verify (MuConfig *opts, GError **err)
} }
static MuError static MuError
cmd_info (MuStore *store, MuConfig *opts, GError **err) cmd_info (const Mu::Store& store, const MuConfig *opts, GError **err)
{ {
mu_store_print_info (store, opts->nocolor); const auto green{opts->nocolor ? "" : MU_COLOR_GREEN};
const auto def{opts->nocolor ? "" : MU_COLOR_DEFAULT};
std::cout << "database-path : "
<< green << store.database_path() << def << "\n"
<< "messages in store : "
<< green << store.size() << def << "\n"
<< "schema-version : "
<< green << store.schema_version() << def << "\n";
const auto created{store.created()};
const auto tstamp{::localtime (&created)};
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-y2k"
char tbuf[64];
strftime (tbuf, sizeof(tbuf), "%c", tstamp);
#pragma GCC diagnostic pop
std::cout << "created : " << green << tbuf << def << "\n"
<< "maildir : "
<< green << store.root_maildir() << def << "\n";
std::cout << ("personal-addresses : ");
const auto addrs{store.personal_addresses()};
if (addrs.empty())
std::cout << green << "<none>" << def << "\n";
else {
bool first{true};
for (auto&& c: addrs) {
std::cout << (!first ? " " : "")
<< green << c << def << "\n";
first = false;
}
}
return MU_OK; return MU_OK;
} }
static MuError static MuError
cmd_init (MuConfig *opts, GError **err) cmd_init (const MuConfig *opts, GError **err)
{ {
MuStore *store;
const char *path;
/* not provided, nor could we find a good default */ /* not provided, nor could we find a good default */
if (!opts->maildir) { if (!opts->maildir) {
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
@ -573,26 +601,43 @@ cmd_init (MuConfig *opts, GError **err)
return MU_ERROR_IN_PARAMETERS; return MU_ERROR_IN_PARAMETERS;
} }
path = mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB); Mu::StringVec my_addrs;
store = mu_store_new_create (path, auto addrs = opts->my_addresses;
opts->maildir, while (addrs && *addrs) {
(const char**)opts->my_addresses, my_addrs.emplace_back (*addrs);
err); ++addrs;
if (!store) }
return MU_G_ERROR_CODE(err);
Mu::Store store(mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), opts->maildir, my_addrs);
if (!opts->quiet) { if (!opts->quiet) {
mu_store_print_info (store, opts->nocolor); cmd_info (store, opts, NULL);
g_print ("\nstore created.\n" g_print ("\nstore created.\n"
"use 'mu index' to fill the database " "use 'mu index' to fill the database "
"with your messages.\n" "with your messages.\n"
"see mu-index(1) for details\n"); "see mu-index(1) for details\n");
} }
mu_store_unref (store);
return MU_OK; return MU_OK;
} }
static MuError
cmd_index (Mu::Store& store, const MuConfig *opts, GError **err)
{
const auto res = mu_cmd_index(store, opts, err);
if (res == MU_OK && !opts->quiet)
cmd_info(store, opts, err);
return res;
}
static MuError
cmd_find (const MuConfig *opts, GError **err)
{
Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), true/*readonly*/};
return mu_cmd_find(reinterpret_cast<MuStore*>(&store), opts, err);
}
static void static void
show_usage (void) show_usage (void)
@ -604,46 +649,27 @@ show_usage (void)
"more information\n"); "more information\n");
} }
typedef MuError (*store_func) (MuStore *, MuConfig *, GError **err); typedef MuError (*readonly_store_func) (const Mu::Store&, const MuConfig *, GError **err);
typedef MuError (*writable_store_func) (Mu::Store&, const MuConfig *, GError **err);
static MuError static MuError
with_store (store_func func, MuConfig *opts, gboolean read_only, GError **err) with_readonly_store (readonly_store_func func, const MuConfig *opts, GError **err)
{ {
MuError merr; const Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), true/*readonly*/};
MuStore *store; return func (store, opts, err);
const char *path;
path = mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB);
if (read_only)
store = mu_store_new_readable (path, err);
else
store = mu_store_new_writable (path, err);
if (!store)
return MU_G_ERROR_CODE(err);
merr = func (store, opts, err);
mu_store_unref (store);
return merr;
} }
static MuError static MuError
with_readonly_store (store_func func, MuConfig *opts, GError **err) with_writable_store (writable_store_func func, const MuConfig *opts, GError **err)
{ {
return with_store (func, opts, TRUE, err); Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), false/*!readonly*/};
return func (store, opts, err);
} }
static MuError
with_writable_store (store_func func, MuConfig *opts, GError **err)
{
return with_store (func, opts, FALSE, err);
}
static gboolean static gboolean
check_params (MuConfig *opts, GError **err) check_params (const MuConfig *opts, GError **err)
{ {
if (!opts->params||!opts->params[0]) {/* no command? */ if (!opts->params||!opts->params[0]) {/* no command? */
show_usage (); show_usage ();
@ -656,7 +682,7 @@ check_params (MuConfig *opts, GError **err)
} }
MuError MuError
mu_cmd_execute (MuConfig *opts, GError **err) mu_cmd_execute (const MuConfig *opts, GError **err) try
{ {
MuError merr; MuError merr;
@ -683,9 +709,9 @@ mu_cmd_execute (MuConfig *opts, GError **err)
case MU_CONFIG_CMD_CFIND: case MU_CONFIG_CMD_CFIND:
merr = with_readonly_store (mu_cmd_cfind, opts, err); break; merr = with_readonly_store (mu_cmd_cfind, opts, err); break;
case MU_CONFIG_CMD_FIND: case MU_CONFIG_CMD_FIND:
merr = with_readonly_store (mu_cmd_find, opts, err); break; merr = cmd_find(opts, err); break;
case MU_CONFIG_CMD_INFO: case MU_CONFIG_CMD_INFO:
merr = with_readonly_store (cmd_info, opts, err); break; merr = with_readonly_store (cmd_info, opts, err); break;
/* writable store */ /* writable store */
@ -696,7 +722,7 @@ mu_cmd_execute (MuConfig *opts, GError **err)
case MU_CONFIG_CMD_TICKLE: case MU_CONFIG_CMD_TICKLE:
merr = with_writable_store (cmd_tickle, opts, err); break; merr = with_writable_store (cmd_tickle, opts, err); break;
case MU_CONFIG_CMD_INDEX: case MU_CONFIG_CMD_INDEX:
merr = with_writable_store (mu_cmd_index, opts, err); break; merr = with_writable_store (cmd_index, opts, err); break;
/* commands instantiate store themselves */ /* commands instantiate store themselves */
case MU_CONFIG_CMD_INIT: case MU_CONFIG_CMD_INIT:
@ -709,4 +735,11 @@ mu_cmd_execute (MuConfig *opts, GError **err)
} }
return merr; return merr;
} catch (const Mu::Error& er) {
g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", er.what());
return MU_ERROR;
} catch (...) {
g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", "caught exception");
return MU_ERROR;
} }

View File

@ -21,7 +21,7 @@
#define __MU_CMD_H__ #define __MU_CMD_H__
#include <glib.h> #include <glib.h>
#include <mu-config.h> #include <mu-config.hh>
#include <mu-store.hh> #include <mu-store.hh>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -37,8 +37,8 @@ G_BEGIN_DECLS
* >MU_OK (0) results, MU_EXITCODE_NO_MATCHES if the command * >MU_OK (0) results, MU_EXITCODE_NO_MATCHES if the command
* succeeds but there no matches, some error code for all other errors * succeeds but there no matches, some error code for all other errors
*/ */
MuError mu_cmd_find (MuStore *store, MuConfig *opts, GError **err); MuError mu_cmd_find (MuStore* store, const MuConfig *opts,
GError **err);
/** /**
* execute the 'extract' command * execute the 'extract' command
@ -49,7 +49,7 @@ MuError mu_cmd_find (MuStore *store, MuConfig *opts, GError **err);
* @return MU_OK (0) if the command succeeds, * @return MU_OK (0) if the command succeeds,
* some error code otherwise * some error code otherwise
*/ */
MuError mu_cmd_extract (MuConfig *opts, GError **err); MuError mu_cmd_extract (const MuConfig *opts, GError **err);
/** /**
@ -61,7 +61,7 @@ MuError mu_cmd_extract (MuConfig *opts, GError **err);
* @return MU_OK (0) if the command succeeds, * @return MU_OK (0) if the command succeeds,
* some error code otherwise * some error code otherwise
*/ */
MuError mu_cmd_script (MuConfig *opts, GError **err); MuError mu_cmd_script (const MuConfig *opts, GError **err);
/** /**
* execute the cfind command * execute the cfind command
@ -73,7 +73,8 @@ MuError mu_cmd_script (MuConfig *opts, GError **err);
* @return MU_OK (0) if the command succeeds, * @return MU_OK (0) if the command succeeds,
* some error code otherwise * some error code otherwise
*/ */
MuError mu_cmd_cfind (MuStore *store, MuConfig *opts, GError **err); MuError mu_cmd_cfind (const Mu::Store& store, const MuConfig *opts,
GError **err);
/** /**
* execute some mu command, based on 'opts' * execute some mu command, based on 'opts'
@ -83,7 +84,7 @@ MuError mu_cmd_cfind (MuStore *store, MuConfig *opts, GError **err);
* *
* @return MU_OK if all went wall, some error code otherwise * @return MU_OK if all went wall, some error code otherwise
*/ */
MuError mu_cmd_execute (MuConfig *opts, GError **err); MuError mu_cmd_execute (const MuConfig *opts, GError **err);
/** /**
* execute the 'index' command * execute the 'index' command
@ -95,7 +96,7 @@ MuError mu_cmd_execute (MuConfig *opts, GError **err);
* @return MU_OK (0) if the command succeeded, * @return MU_OK (0) if the command succeeded,
* some error code otherwise * some error code otherwise
*/ */
MuError mu_cmd_index (MuStore *store, MuConfig *opt, GError **err); MuError mu_cmd_index (Mu::Store& store, const MuConfig *opt, GError **err);
/** /**
* execute the server command * execute the server command
@ -104,7 +105,7 @@ MuError mu_cmd_index (MuStore *store, MuConfig *opt, GError **err);
* *
* @return MU_OK (0) if the command succeeds, some error code otherwise * @return MU_OK (0) if the command succeeds, some error code otherwise
*/ */
MuError mu_cmd_server (MuConfig *opts, GError **err); MuError mu_cmd_server (const MuConfig *opts, GError **err);
G_END_DECLS G_END_DECLS

View File

@ -24,8 +24,9 @@
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include "mu-config.h" #include "mu-config.hh"
#include "mu-cmd.h" #include "mu-cmd.hh"
#include "mu-msg.h"
static MuConfig MU_CONFIG; static MuConfig MU_CONFIG;
@ -115,7 +116,7 @@ config_options_group_mu (void)
{G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY,
&MU_CONFIG.params, "parameters", NULL}, &MU_CONFIG.params, "parameters", NULL},
{NULL, 0, 0, 0, NULL, NULL, NULL} {NULL, 0, 0, (GOptionArg)0, NULL, NULL, NULL}
}; };
og = g_option_group_new("mu", "general mu options", "", NULL, NULL); og = g_option_group_new("mu", "general mu options", "", NULL, NULL);
@ -143,7 +144,7 @@ config_options_group_init (void)
{"my-address", 0, 0, G_OPTION_ARG_STRING_ARRAY, {"my-address", 0, 0, G_OPTION_ARG_STRING_ARRAY,
&MU_CONFIG.my_addresses, "my e-mail address; can be used multiple times", &MU_CONFIG.my_addresses, "my e-mail address; can be used multiple times",
"<address>"}, "<address>"},
{NULL, 0, 0, 0, NULL, NULL, NULL} {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}
}; };
og = g_option_group_new("init", "Options for the 'index' command", og = g_option_group_new("init", "Options for the 'index' command",
@ -186,7 +187,7 @@ config_options_group_index (void)
"only check dir-timestamps (false)", NULL}, "only check dir-timestamps (false)", NULL},
{"nocleanup", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.nocleanup, {"nocleanup", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.nocleanup,
"don't clean up the database after indexing (false)", NULL}, "don't clean up the database after indexing (false)", NULL},
{NULL, 0, 0, 0, NULL, NULL, NULL} {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}
}; };
og = g_option_group_new("index", "Options for the 'index' command", og = g_option_group_new("index", "Options for the 'index' command",
@ -257,7 +258,7 @@ config_options_group_find (void)
{"after", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.after, {"after", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.after,
"only show messages whose m_time > T (t_time)", "only show messages whose m_time > T (t_time)",
"<timestamp>"}, "<timestamp>"},
{NULL, 0, 0, 0, NULL, NULL, NULL} {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}
}; };
og = g_option_group_new("find", og = g_option_group_new("find",
@ -275,7 +276,7 @@ config_options_group_mkdir (void)
GOptionEntry entries[] = { GOptionEntry entries[] = {
{"mode", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.dirmode, {"mode", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.dirmode,
"set the mode (as in chmod), in octal notation", "<mode>"}, "set the mode (as in chmod), in octal notation", "<mode>"},
{NULL, 0, 0, 0, NULL, NULL, NULL} {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}
}; };
/* set dirmode before, because '0000' is a valid mode */ /* set dirmode before, because '0000' is a valid mode */
@ -309,7 +310,7 @@ config_options_group_cfind (void)
"whether to only get 'personal' contacts", NULL}, "whether to only get 'personal' contacts", NULL},
{"after", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.after, {"after", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.after,
"only get addresses last seen after T", "<timestamp>"}, "only get addresses last seen after T", "<timestamp>"},
{NULL, 0, 0, 0, NULL, NULL, NULL} {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}
}; };
og = g_option_group_new("cfind", "Options for the 'cfind' command", og = g_option_group_new("cfind", "Options for the 'cfind' command",
@ -326,7 +327,7 @@ config_options_group_script (void)
GOptionEntry entries[] = { GOptionEntry entries[] = {
{G_OPTION_REMAINING, 0,0, G_OPTION_ARG_STRING_ARRAY, {G_OPTION_REMAINING, 0,0, G_OPTION_ARG_STRING_ARRAY,
&MU_CONFIG.params, "script parameters", NULL}, &MU_CONFIG.params, "script parameters", NULL},
{NULL, 0, 0, 0, NULL, NULL, NULL} {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}
}; };
og = g_option_group_new("script", "Options for the 'script' command", og = g_option_group_new("script", "Options for the 'script' command",
@ -359,7 +360,7 @@ crypto_option_entries (void)
"attempt to use the GPG agent (false)", NULL}, "attempt to use the GPG agent (false)", NULL},
{"decrypt", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.decrypt, {"decrypt", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.decrypt,
"attempt to decrypt the message", NULL}, "attempt to decrypt the message", NULL},
{NULL, 0, 0, 0, NULL, NULL, NULL} {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}
}; };
return entries; return entries;
@ -378,7 +379,7 @@ config_options_group_view (void)
"<term>"}, "<term>"},
{"format", 'o', 0, G_OPTION_ARG_STRING, &MU_CONFIG.formatstr, {"format", 'o', 0, G_OPTION_ARG_STRING, &MU_CONFIG.formatstr,
"output format ('plain'(*), 'sexp')", "<format>"}, "output format ('plain'(*), 'sexp')", "<format>"},
{NULL, 0, 0, 0, NULL, NULL, NULL} {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}
}; };
og = g_option_group_new("view", "Options for the 'view' command", og = g_option_group_new("view", "Options for the 'view' command",
@ -419,7 +420,7 @@ config_options_group_extract (void)
"overwrite existing files (false)", NULL}, "overwrite existing files (false)", NULL},
{"play", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.play, {"play", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.play,
"try to 'play' (open) the extracted parts", NULL}, "try to 'play' (open) the extracted parts", NULL},
{NULL, 0, 0, 0, NULL, NULL, NULL} {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}
}; };
og = g_option_group_new("extract", og = g_option_group_new("extract",
"Options for the 'extract' command", "Options for the 'extract' command",
@ -453,7 +454,7 @@ config_options_group_server (void)
"list the available command and their parameters, then exit", NULL}, "list the available command and their parameters, then exit", NULL},
{"eval", 'e', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, {"eval", 'e', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING,
&MU_CONFIG.eval, "expression to evaluate", "<expr>"}, &MU_CONFIG.eval, "expression to evaluate", "<expr>"},
{NULL, 0, 0, 0, NULL, NULL, NULL} {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}
}; };
og = g_option_group_new("server", og = g_option_group_new("server",
@ -587,7 +588,7 @@ massage_help (const char *help)
char *str; char *str;
rx = g_regex_new ("^Usage:.*\n.*\n", rx = g_regex_new ("^Usage:.*\n.*\n",
0, G_REGEX_MATCH_NEWLINE_ANY, NULL); (GRegexCompileFlags)0, G_REGEX_MATCH_NEWLINE_ANY, NULL);
str = g_regex_replace (rx, help, str = g_regex_replace (rx, help,
-1, 0, "", -1, 0, "",
G_REGEX_MATCH_NEWLINE_ANY, NULL); G_REGEX_MATCH_NEWLINE_ANY, NULL);
@ -774,7 +775,7 @@ mu_config_uninit (MuConfig *opts)
} }
size_t size_t
mu_config_param_num (MuConfig *opts) mu_config_param_num (const MuConfig *opts)
{ {
size_t n; size_t n;
@ -786,9 +787,9 @@ mu_config_param_num (MuConfig *opts)
MuMsgOptions MuMsgOptions
mu_config_get_msg_options (MuConfig *muopts) mu_config_get_msg_options (const MuConfig *muopts)
{ {
MuMsgOptions opts; int opts;
opts = MU_MSG_OPTION_NONE; opts = MU_MSG_OPTION_NONE;
@ -803,5 +804,5 @@ mu_config_get_msg_options (MuConfig *muopts)
if (muopts->overwrite) if (muopts->overwrite)
opts |= MU_MSG_OPTION_OVERWRITE; opts |= MU_MSG_OPTION_OVERWRITE;
return opts; return (MuMsgOptions)opts;
} }

View File

@ -226,7 +226,7 @@ void mu_config_uninit (MuConfig *conf);
* the exit code of the process * the exit code of the process
* *
*/ */
MuError mu_config_execute (MuConfig *conf); MuError mu_config_execute (const MuConfig *conf);
/** /**
* count the number of non-option parameters * count the number of non-option parameters
@ -235,7 +235,7 @@ MuError mu_config_execute (MuConfig *conf);
* *
* @return the number of non-option parameters, or 0 in case of error * @return the number of non-option parameters, or 0 in case of error
*/ */
size_t mu_config_param_num (MuConfig *conf); size_t mu_config_param_num (const MuConfig *conf);
/** /**
@ -245,7 +245,7 @@ size_t mu_config_param_num (MuConfig *conf);
* *
* @return the corresponding MuMsgOptions * @return the corresponding MuMsgOptions
*/ */
MuMsgOptions mu_config_get_msg_options (MuConfig *opts); MuMsgOptions mu_config_get_msg_options (const MuConfig *opts);
/** /**
@ -253,7 +253,7 @@ MuMsgOptions mu_config_get_msg_options (MuConfig *opts);
* *
* @param cmd the command to show help for * @param cmd the command to show help for
*/ */
void mu_config_show_help (MuConfigCmd cmd); void mu_config_show_help (const MuConfigCmd cmd);
G_END_DECLS G_END_DECLS

View File

@ -17,16 +17,14 @@
** **
*/ */
#ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <glib.h> #include <glib.h>
#include <glib-object.h> #include <glib-object.h>
#include <locale.h> #include <locale.h>
#include "mu-config.h" #include "mu-config.hh"
#include "mu-cmd.h" #include "mu-cmd.hh"
#include "mu-runtime.h" #include "mu-runtime.h"

View File

@ -226,11 +226,14 @@ test_mu_cfind_mutt_ab (void)
"'testmu\\.xxx?'", "'testmu\\.xxx?'",
MU_PROGRAM, CONTACTS_CACHE); MU_PROGRAM, CONTACTS_CACHE);
if (g_test_verbose())
g_print("%s\n", cmdline);
output = erroutput = NULL; output = erroutput = NULL;
g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput,
NULL, NULL)); NULL, NULL));
g_assert (output); g_assert (output);
if (output[39] == 'h') if (output[39] == 'h')
g_assert_cmpstr (output, g_assert_cmpstr (output,
==, ==,
@ -305,20 +308,26 @@ test_mu_cfind_csv (void)
"'testmu\\.xxx?'", "'testmu\\.xxx?'",
MU_PROGRAM, CONTACTS_CACHE); MU_PROGRAM, CONTACTS_CACHE);
if (g_test_verbose())
g_print("%s\n", cmdline);
output = erroutput = NULL; output = erroutput = NULL;
g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput, g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput,
NULL, NULL)); NULL, NULL));
g_print ("\n\n%s\n\n", output);
g_assert (output); g_assert (output);
if (output[0] == 'H') if (output[1] == 'H')
g_assert_cmpstr (output, g_assert_cmpstr (output,
==, ==,
"Helmut Kröger,hk@testmu.xxx\n" "\"Helmut Kröger\",\"hk@testmu.xxx\"\n"
",testmu@testmu.xx\n"); "\"\",\"testmu@testmu.xx\"\n");
else else
g_assert_cmpstr (output, g_assert_cmpstr (output,
==, ==,
",testmu@testmu.xx\n" "\"\",\"testmu@testmu.xx\"\n"
"Helmut Kröger,hk@testmu.xxx\n"); "\"Helmut Kröger\",\"hk@testmu.xxx\"\n");
g_free (cmdline); g_free (cmdline);
g_free (output); g_free (output);
g_free (erroutput); g_free (erroutput);
@ -349,8 +358,9 @@ main (int argc, char *argv[])
test_mu_cfind_csv); test_mu_cfind_csv);
g_log_set_handler (NULL, g_log_set_handler (NULL,
(GLogLevelFlags)(
G_LOG_LEVEL_MASK | G_LOG_LEVEL_WARNING| G_LOG_LEVEL_MASK | G_LOG_LEVEL_WARNING|
G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION, G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION),
(GLogFunc)black_hole, NULL); (GLogFunc)black_hole, NULL);
rv = g_test_run (); rv = g_test_run ();

View File

@ -900,8 +900,9 @@ main (int argc, char *argv[])
g_test_add_func ("/mu-cmd/test-mu-verify-bad", test_mu_verify_bad); g_test_add_func ("/mu-cmd/test-mu-verify-bad", test_mu_verify_bad);
g_log_set_handler (NULL, g_log_set_handler (NULL,
(GLogLevelFlags)(
G_LOG_LEVEL_MASK | G_LOG_LEVEL_WARNING| G_LOG_LEVEL_MASK | G_LOG_LEVEL_WARNING|
G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION, G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION),
(GLogFunc)black_hole, NULL); (GLogFunc)black_hole, NULL);
DBPATH = fill_database (); DBPATH = fill_database ();

View File

@ -754,8 +754,8 @@ main (int argc, char *argv[])
if (!g_test_verbose()) if (!g_test_verbose())
g_log_set_handler (NULL, g_log_set_handler (NULL,
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL|
G_LOG_FLAG_RECURSION, G_LOG_FLAG_RECURSION),
(GLogFunc)black_hole, NULL); (GLogFunc)black_hole, NULL);
rv = g_test_run (); rv = g_test_run ();

View File

@ -124,9 +124,10 @@ static MuMsgIter*
run_and_get_iter_full (const char *xpath, const char *query, run_and_get_iter_full (const char *xpath, const char *query,
MuMsgFieldId sort_field, MuQueryFlags flags) MuMsgFieldId sort_field, MuQueryFlags flags)
{ {
MuQuery *mquery; MuQuery *mquery;
MuStore *store; MuStore *store;
MuMsgIter *iter; MuMsgIter *iter;
int myflags;
store = mu_store_new_readable (xpath, NULL); store = mu_store_new_readable (xpath, NULL);
g_assert (store); g_assert (store);
@ -135,8 +136,10 @@ run_and_get_iter_full (const char *xpath, const char *query,
mu_store_unref (store); mu_store_unref (store);
g_assert (query); g_assert (query);
flags |= MU_QUERY_FLAG_THREADS; myflags = flags;
iter = mu_query_run (mquery, query, sort_field, -1, flags, NULL); myflags |= MU_QUERY_FLAG_THREADS;
iter = mu_query_run (mquery, query, sort_field, -1,
(MuQueryFlags)myflags, NULL);
mu_query_destroy (mquery); mu_query_destroy (mquery);
g_assert (iter); g_assert (iter);
@ -233,7 +236,7 @@ query_testdir (const char *query, MuMsgFieldId sort_field, gboolean descending)
{ {
MuMsgIter *iter; MuMsgIter *iter;
gchar *xpath; gchar *xpath;
MuQueryFlags flags; int flags;
flags = MU_QUERY_FLAG_NONE; flags = MU_QUERY_FLAG_NONE;
if (descending) if (descending)
@ -242,7 +245,7 @@ query_testdir (const char *query, MuMsgFieldId sort_field, gboolean descending)
xpath = fill_database (MU_TESTMAILDIR3); xpath = fill_database (MU_TESTMAILDIR3);
g_assert (xpath != NULL); g_assert (xpath != NULL);
iter = run_and_get_iter_full (xpath, query, sort_field, flags); iter = run_and_get_iter_full (xpath, query, sort_field, (MuQueryFlags)flags);
g_assert (iter != NULL); g_assert (iter != NULL);
g_assert (!mu_msg_iter_is_done (iter)); g_assert (!mu_msg_iter_is_done (iter));
@ -453,7 +456,8 @@ main (int argc, char *argv[])
test_mu_threads_sort_granchild_promotes_only_subthread); test_mu_threads_sort_granchild_promotes_only_subthread);
g_log_set_handler (NULL, g_log_set_handler (NULL,
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION, (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL|
G_LOG_FLAG_RECURSION),
(GLogFunc)black_hole, NULL); (GLogFunc)black_hole, NULL);
rv = g_test_run (); rv = g_test_run ();