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
extern "C" {
@ -1390,44 +1391,4 @@ mu_store_get_dirstamp (const MuStore *store, const char *dirpath, GError **err)
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;
}
case Type::String:
//sstrm << quote(value());
sstrm << "\"";
for (auto&& k: value()) {
switch (k) {
case '"' : sstrm << "\\\""; break;
case '\\': sstrm << "\\\\"; break;
default: sstrm << k;
}
}
sstrm << "\"";
sstrm << quote(value());
break;
case Type::Number:
case Type::Symbol:
default:

View File

@ -309,7 +309,7 @@ typedef gpointer XapianEnquire;
} 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 {

View File

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

View File

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

View File

@ -21,21 +21,14 @@ AM_CPPFLAGS= \
$(GLIB_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= \
$(JSON_GLIB_CFLAGS) \
-DMU_SCRIPTS_DIR="\"$(pkgdatadir)/scripts/\""
$(ASAN_CXXCFLAGS) \
$(WARN_CXXFLAGS) \
$(CODE_COVERAGE_CFLAGS)
$(CODE_COVERAGE_CFLAGS) \
-Wno-switch-enum
AM_LDFLAGS= \
$(ASAN_LDFLAGS)
@ -47,16 +40,16 @@ bin_PROGRAMS= \
# be linked as c++, not c.
mu_SOURCES= \
mu.cc \
mu-cmd-cfind.c \
mu-config.c \
mu-config.h \
mu-cmd-extract.c \
mu-cmd-find.c \
mu-cmd-index.c \
mu-cmd-cfind.cc \
mu-config.cc \
mu-config.hh \
mu-cmd-extract.cc \
mu-cmd-find.cc \
mu-cmd-index.cc \
mu-cmd-server.cc \
mu-cmd-script.c \
mu-cmd.c \
mu-cmd.h
mu-cmd-script.cc \
mu-cmd.cc \
mu-cmd.hh
BUILT_SOURCES= \
mu-help-strings.h
@ -77,8 +70,8 @@ EXTRA_DIST= \
noinst_PROGRAMS= $(TEST_PROGS)
test_cflags= \
${AM_CFLAGS} \
test_cxxflags= \
${AM_CXXFLAGS} \
-DMU_TESTMAILDIR=\"${abs_top_srcdir}/lib/testdir\" \
-DMU_TESTMAILDIR2=\"${abs_top_srcdir}/lib/testdir2\" \
-DMU_TESTMAILDIR3=\"${abs_top_srcdir}/lib/testdir3\" \
@ -88,31 +81,25 @@ test_cflags= \
-DABS_SRCDIR=\"${abs_srcdir}\"
TEST_PROGS += test-mu-query
test_mu_query_SOURCES= test-mu-query.c dummy.cc
test_mu_query_CFLAGS=$(test_cflags)
test_mu_query_SOURCES= test-mu-query.cc
test_mu_query_CXXFLAGS=$(test_cxxflags)
test_mu_query_LDADD=${top_builddir}/lib/libtestmucommon.la $(CODE_COVERAGE_LIBS)
TEST_PROGS += test-mu-cmd
test_mu_cmd_SOURCES= test-mu-cmd.c dummy.cc
test_mu_cmd_CFLAGS=$(test_cflags)
test_mu_cmd_SOURCES= test-mu-cmd.cc
test_mu_cmd_CXXFLAGS=$(test_cxxflags)
test_mu_cmd_LDADD=${top_builddir}/lib/libtestmucommon.la $(CODE_COVERAGE_LIBS)
TEST_PROGS += test-mu-cmd-cfind
test_mu_cmd_cfind_SOURCES= test-mu-cmd-cfind.c dummy.cc
test_mu_cmd_cfind_CFLAGS=$(test_cflags)
test_mu_cmd_cfind_SOURCES= test-mu-cmd-cfind.cc
test_mu_cmd_cfind_CXXFLAGS=$(test_cxxflags)
test_mu_cmd_cfind_LDADD=${top_builddir}/lib/libtestmucommon.la $(CODE_COVERAGE_LIBS)
TEST_PROGS += test-mu-threads
test_mu_threads_SOURCES= test-mu-threads.c dummy.cc
test_mu_threads_CFLAGS=$(test_cflags)
test_mu_threads_SOURCES= test-mu-threads.cc
test_mu_threads_CXXFLAGS=$(test_cxxflags)
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)
include $(top_srcdir)/aminclude_static.am

View File

@ -18,16 +18,20 @@
#include "config.h"
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "mu-cmd.h"
#include "mu-cmd.hh"
#include "mu-contacts.hh"
#include "mu-runtime.h"
#include "utils/mu-util.h"
#include "utils/mu-utils.hh"
#include "utils/mu-error.hh"
#include "utils/mu-str.h"
#include "utils/mu-date.h"
@ -174,10 +178,8 @@ leave:
return nick;
}
static void
print_header (MuConfigFormat format)
print_header (const MuConfigFormat format)
{
switch (format) {
case MU_CONFIG_FORMAT_BBDB:
@ -193,18 +195,18 @@ print_header (MuConfigFormat format)
}
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;
fname = guess_first_name (name);
lname = guess_last_name (name);
fname = guess_first_name (name.c_str());
lname = guess_last_name (name.c_str());
now = mu_date_str ("%Y-%m-%d", time(NULL));
timestamp = mu_date_str ("%Y-%m-%d", tstamp);
g_print ("[\"%s\" \"%s\" nil nil nil nil (\"%s\") "
"((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 (timestamp);
@ -214,89 +216,44 @@ each_contact_bbdb (const char *email, const char *name, time_t tstamp)
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)
{
gchar *nick;
if (!name)
if (name.empty())
return;
nick = guess_nick (name, nicks);
char *nick = guess_nick (name.c_str(), nicks);
mu_util_print_encoded ("alias %s %s <%s>\n",
nick, name, email);
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);
nick, name.c_str(), email.c_str());
g_free (nick);
}
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)
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)
if (name.empty())
return;
s = mu_str_replace (str, "\"", "\"\"");
if (strchr (s, ','))
mu_util_print_encoded ("\"%s\"", s);
else
mu_util_print_encoded ("%s", s);
g_free (s);
char *nick = guess_nick (name.c_str(), nicks);
mu_util_print_encoded ("%s \"%s\" \"%s\"\n", email.c_str(), nick, name.c_str());
g_free (nick);
}
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);
mu_util_print_encoded (",");
print_csv_field (email);
mu_util_print_encoded ("\n");
}
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 (!name.empty()) {
if (color)
::fputs (MU_COLOR_MAGENTA, stdout);
mu_util_fputs_encoded (name.c_str(), stdout);
::fputs (" ", stdout);
}
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)
fputs (MU_COLOR_DEFAULT, stdout);
@ -304,92 +261,91 @@ print_plain (const char *email, const char *name, gboolean color)
fputs ("\n", stdout);
}
typedef struct {
MuConfigFormat format;
gboolean color, personal;
time_t after;
struct ECData {
MuConfigFormat format;
gboolean color, personal;
time_t after;
GRegex *rx;
GHashTable *nicks;
size_t n;
} ECData;
};
static void
each_contact (const char *full_address,
const char *email, const char *name, gboolean personal,
time_t last_seen, size_t freq, gint64 tstamp,
ECData *ecdata)
each_contact (const Mu::ContactInfo& ci, ECData& ecdata)
{
if (ecdata->personal && !personal)
if (ecdata.personal && ci.personal)
return;
if (tstamp < ecdata->after)
if (ci.tstamp < ecdata.after)
return;
if (ecdata->rx &&
!g_regex_match (ecdata->rx, email, 0, NULL) &&
!g_regex_match (ecdata->rx, name ? name : "", 0, NULL))
if (ecdata.rx &&
!g_regex_match (ecdata.rx, ci.email.c_str(), (GRegexMatchFlags)0, NULL) &&
!g_regex_match (ecdata.rx, ci.name.empty() ? "" : ci.name.c_str(), (GRegexMatchFlags)0, NULL))
return;
++ecdata->n;
++ecdata.n;
switch (ecdata->format) {
switch (ecdata.format) {
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;
case MU_CONFIG_FORMAT_MUTT_AB:
mu_util_print_encoded ("%s\t%s\t\n",
email, name ? name : "");
ci.email.c_str(), ci.name.c_str());
break;
case MU_CONFIG_FORMAT_WL:
each_contact_wl (email, name, ecdata->nicks);
each_contact_wl (ci.email, ci.name, ecdata.nicks);
break;
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;
case MU_CONFIG_FORMAT_BBDB:
each_contact_bbdb (email, name, last_seen);
each_contact_bbdb (ci.email, ci.name, ci.last_seen);
break;
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;
case MU_CONFIG_FORMAT_DEBUG: {
char datebuf[32];
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"
"\tlast-seen: %s\n",
email,
name ? name : "<none>",
full_address,
personal ? "yes" : "no",
freq,
ci.email.c_str(),
ci.name.empty() ? "<none>" : ci.name.c_str(),
ci.full_address.c_str(),
ci.personal ? "yes" : "no",
ci.freq,
datebuf);
} break;
default:
print_plain (email, name, ecdata->color);
print_plain (ci.email, ci.name, ecdata.color);
}
}
static MuError
run_cmd_cfind (MuStore *store,
const char* pattern,
gboolean personal,
time_t after,
MuConfigFormat format,
gboolean color,
GError **err)
run_cmd_cfind (const Mu::Store& store,
const char* pattern,
gboolean personal,
time_t after,
const MuConfigFormat format,
gboolean color,
GError **err)
{
gboolean rv;
ECData ecdata;
ECData ecdata{};
memset(&ecdata, 0, sizeof(ecdata));
if (pattern) {
ecdata.rx = g_regex_new (pattern,
G_REGEX_CASELESS|G_REGEX_OPTIMIZE,
0, err);
(GRegexCompileFlags)(G_REGEX_CASELESS|G_REGEX_OPTIMIZE),
(GRegexMatchFlags)0, err);
if (!ecdata.rx)
return MU_ERROR_CONTACTS;
}
@ -403,8 +359,9 @@ run_cmd_cfind (MuStore *store,
g_free, NULL);
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);
if (ecdata.rx)
@ -415,11 +372,11 @@ run_cmd_cfind (MuStore *store,
return MU_ERROR_NO_MATCHES;
}
return rv ? MU_OK : MU_ERROR_CONTACTS;
return MU_OK;
}
static gboolean
cfind_params_valid (MuConfig *opts)
cfind_params_valid (const MuConfig *opts)
{
switch (opts->format) {
case MU_CONFIG_FORMAT_PLAIN:
@ -447,24 +404,25 @@ cfind_params_valid (MuConfig *opts)
}
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->cmd == MU_CONFIG_CMD_CFIND,
MU_ERROR_INTERNAL);
if (!cfind_params_valid (opts)) {
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_IN_PARAMETERS,
"invalid parameters");
return MU_ERROR_IN_PARAMETERS;
}
if (!cfind_params_valid (opts))
throw Mu::Error(Mu::Error::Code::InvalidArgument,
"invalid parameters");
return run_cmd_cfind (store,
opts->params[1],
opts->personal,
opts->after,
opts->format,
!opts->nocolor,
err);
auto res = run_cmd_cfind (store,
opts->params[1],
opts->personal,
opts->after,
opts->format,
!opts->nocolor,
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
** under the terms of the GNU General Public License as published by the
@ -19,22 +17,20 @@
**
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif /*HAVE_CONFIG_H*/
#include <stdlib.h>
#include <string.h>
#include "mu-msg.h"
#include "mu-msg-part.h"
#include "mu-cmd.h"
#include "mu-cmd.hh"
#include "utils/mu-util.h"
#include "utils/mu-str.h"
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;
gchar *filepath;
@ -70,7 +66,7 @@ exit:
static gboolean
save_numbered_parts (MuMsg *msg, MuConfig *opts)
save_numbered_parts (MuMsg *msg, const MuConfig *opts)
{
gboolean rv;
char **parts, **cur;
@ -116,8 +112,9 @@ anchored_regex (const char* pattern)
pattern[strlen(pattern)-1] == '$' ? "" : "$");
err = NULL;
rx = g_regex_new (anchored, G_REGEX_CASELESS|G_REGEX_OPTIMIZE, 0,
&err);
rx = g_regex_new (anchored,
(GRegexCompileFlags)(G_REGEX_CASELESS|G_REGEX_OPTIMIZE),
(GRegexMatchFlags)0, &err);
g_free (anchored);
if (!rx) {
@ -132,7 +129,7 @@ anchored_regex (const char* pattern)
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;
GRegex *rx;
@ -164,7 +161,7 @@ save_part_with_filename (MuMsg *msg, const char *pattern, MuConfig *opts)
struct _SaveData {
gboolean result;
guint saved_num;
MuConfig *opts;
const MuConfig *opts;
};
typedef struct _SaveData SaveData;
@ -232,7 +229,7 @@ exit:
}
static gboolean
save_certain_parts (MuMsg *msg, MuConfig *opts)
save_certain_parts (MuMsg *msg, const MuConfig *opts)
{
SaveData sd;
MuMsgOptions msgopts;
@ -256,7 +253,7 @@ save_certain_parts (MuMsg *msg, MuConfig *opts)
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;
gboolean rv;
@ -336,7 +333,7 @@ each_part_show (MuMsg *msg, MuMsgPart *part, gboolean color)
static gboolean
show_parts (const char* path, MuConfig *opts, GError **err)
show_parts (const char* path, const MuConfig *opts, GError **err)
{
MuMsg *msg;
MuMsgOptions msgopts;
@ -362,7 +359,7 @@ show_parts (const char* path, MuConfig *opts, GError **err)
static gboolean
check_params (MuConfig *opts, GError **err)
check_params (const MuConfig *opts, GError **err)
{
size_t param_num;
@ -396,7 +393,7 @@ check_params (MuConfig *opts, GError **err)
}
MuError
mu_cmd_extract (MuConfig *opts, GError **err)
mu_cmd_extract (const MuConfig *opts, GError **err)
{
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
** under the terms of the GNU General Public License as published by the
@ -17,9 +17,7 @@
**
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif /*HAVE_CONFIG_H*/
#include <unistd.h>
#include <stdio.h>
@ -40,7 +38,7 @@
#include "utils/mu-str.h"
#include "utils/mu-date.h"
#include "mu-cmd.h"
#include "mu-cmd.hh"
#include "mu-threader.h"
#ifdef HAVE_JSON_GLIB
@ -48,7 +46,7 @@
#endif /*HAVE_JSON_GLIB*/
typedef gboolean (OutputFunc) (MuMsg *msg, MuMsgIter *iter,
MuConfig *opts, GError **err);
const MuConfig *opts, GError **err);
static gboolean
print_internal (MuQuery *query, const gchar *expr, gboolean xapian,
@ -115,11 +113,11 @@ get_message (MuMsgIter *iter, time_t after)
}
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;
MuMsgFieldId sortid;
MuQueryFlags qflags;
MuMsgIter *iter;
MuMsgFieldId sortid;
int qflags;
sortid = MU_MSG_FIELD_ID_NONE;
if (opts->sortfield) {
@ -138,12 +136,13 @@ run_query (MuQuery *xapian, const gchar *query, MuConfig *opts, GError **err)
if (opts->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;
}
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;
char *cmdline, *escpath;
@ -161,7 +160,7 @@ exec_cmd (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err)
}
static gchar*
resolve_bookmark (MuConfig *opts, GError **err)
resolve_bookmark (const MuConfig *opts, GError **err)
{
MuBookmarks *bm;
char* val;
@ -187,7 +186,7 @@ resolve_bookmark (MuConfig *opts, GError **err)
}
static gchar*
get_query (MuConfig *opts, GError **err)
get_query (const MuConfig *opts, GError **err)
{
gchar *query, *bookmarkval;
@ -243,7 +242,7 @@ get_query_obj (MuStore *store, GError **err)
}
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
* mail dir already exists */
@ -266,7 +265,7 @@ prepare_links (MuConfig *opts, GError **err)
}
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))
return FALSE;
@ -381,7 +380,7 @@ display_field (MuMsg *msg, MuMsgFieldId mfid)
}
static void
print_summary (MuMsg *msg, MuConfig *opts)
print_summary (MuMsg *msg, const MuConfig *opts)
{
const char* body;
char *summ;
@ -472,7 +471,7 @@ output_plain_fields (MuMsg *msg, const char *fields,
}
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)
* for message-priority for threads, too */
@ -489,7 +488,7 @@ output_plain (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err)
}
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;
const MuMsgIterThreadInfo *ti;
@ -504,7 +503,7 @@ output_sexp (MuMsg *msg, MuMsgIter *iter, MuConfig *opts, GError **err)
}
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
JsonNode *node;
@ -552,7 +551,7 @@ print_attr_xml (const char* elm, const char *str)
}
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)) {
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*
get_output_func (MuConfig *opts, GError **err)
get_output_func (const MuConfig *opts, GError **err)
{
switch (opts->format) {
case MU_CONFIG_FORMAT_LINKS: return output_link;
@ -596,7 +595,7 @@ get_output_func (MuConfig *opts, GError **err)
}
static gboolean
output_query_results (MuMsgIter *iter, MuConfig *opts, GError **err)
output_query_results (MuMsgIter *iter, const MuConfig *opts, GError **err)
{
int count;
gboolean rv;
@ -639,7 +638,7 @@ output_query_results (MuMsgIter *iter, MuConfig *opts, GError **err)
}
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;
gboolean rv;
@ -655,7 +654,7 @@ process_query (MuQuery *xapian, const gchar *query, MuConfig *opts, GError **err
}
static gboolean
execute_find (MuStore *store, MuConfig *opts, GError **err)
execute_find (MuStore *store, const MuConfig *opts, GError **err)
{
char *query_str;
MuQuery *oracle;
@ -686,7 +685,7 @@ execute_find (MuStore *store, MuConfig *opts, GError **err)
}
static gboolean
format_params_valid (MuConfig *opts, GError **err)
format_params_valid (const MuConfig *opts, GError **err)
{
switch (opts->format) {
case MU_CONFIG_FORMAT_EXEC:
@ -727,7 +726,7 @@ format_params_valid (MuConfig *opts, GError **err)
}
static gboolean
query_params_valid (MuConfig *opts, GError **err)
query_params_valid (const MuConfig *opts, GError **err)
{
const gchar *xpath;
@ -748,20 +747,22 @@ query_params_valid (MuConfig *opts, GError **err)
}
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->cmd == MU_CONFIG_CMD_FIND,
MU_ERROR_INTERNAL);
if (opts->exec)
opts->format = MU_CONFIG_FORMAT_EXEC; /* pseudo format */
MuConfig myopts{*opts};
if (!query_params_valid (opts, err) ||
!format_params_valid(opts, err))
if (myopts.exec)
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);
if (!execute_find (store, opts, err))
if (!execute_find (store, &myopts, err))
return MU_G_ERROR_CODE(err);
else
return MU_OK;

View File

@ -17,11 +17,8 @@
**
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif /*HAVE_CONFIG_H*/
#include "mu-cmd.h"
#include "mu-cmd.hh"
#include <errno.h>
#include <string.h>
@ -70,7 +67,7 @@ install_sig_handler (void)
static gboolean
check_params (MuConfig *opts, GError **err)
check_params (const MuConfig *opts, GError **err)
{
/* param[0] == 'index' there should be no param[1] */
if (opts->params[1]) {
@ -178,7 +175,7 @@ show_time (unsigned t, unsigned processed, gboolean color)
}
static MuError
cleanup_missing (MuIndex *midx, MuConfig *opts, MuIndexStats *stats,
cleanup_missing (MuIndex *midx, const MuConfig *opts, MuIndexStats *stats,
GError **err)
{
MuError rv;
@ -213,7 +210,7 @@ cleanup_missing (MuIndex *midx, MuConfig *opts, MuIndexStats *stats,
}
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;
MuError rv;
@ -240,7 +237,7 @@ cmd_index (MuIndex *midx, MuConfig *opts, MuIndexStats *stats, GError **err)
static MuIndex*
init_mu_index (MuStore *store, MuConfig *opts, GError **err)
init_mu_index (MuStore *store, const MuConfig *opts, GError **err)
{
MuIndex *midx;
@ -257,28 +254,26 @@ init_mu_index (MuStore *store, MuConfig *opts, GError **err)
}
MuError
mu_cmd_index (MuStore *store, MuConfig *opts, GError **err)
mu_cmd_index (Mu::Store& store, const MuConfig *opts, GError **err)
{
MuIndex *midx;
MuIndexStats stats;
gboolean rv;
time_t t;
g_return_val_if_fail (opts, FALSE);
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_INDEX,
FALSE);
g_return_val_if_fail (opts, MU_ERROR);
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_INDEX, MU_ERROR);
/* 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)
return MU_G_ERROR_CODE(err);
throw Mu::Error(Mu::Error::Code::Internal, err/*consumes*/,
"error in index");
mu_index_stats_clear (&stats);
install_sig_handler ();
if (!opts->quiet)
mu_store_print_info (store, opts->nocolor);
t = time (NULL);
rv = cmd_index (midx, opts, &stats, err);
@ -297,5 +292,9 @@ mu_cmd_index (MuStore *store, MuConfig *opts, GError **err)
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 <errno.h>
#include "mu-cmd.h"
#include "mu-cmd.hh"
#include "mu-script.h"
#include "mu-runtime.h"
@ -151,7 +151,7 @@ get_script_info_list (const char *muhome, GError **err)
static gboolean
check_params (MuConfig *opts, GError **err)
check_params (const MuConfig *opts, GError **err)
{
if (!mu_util_supports (MU_FEATURE_GUILE)) {
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
@ -165,7 +165,7 @@ check_params (MuConfig *opts, GError **err)
MuError
mu_cmd_script (MuConfig *opts, GError **err)
mu_cmd_script (const MuConfig *opts, GError **err)
{
MuScriptInfo *msi;
GSList *scripts;

View File

@ -18,7 +18,7 @@
*/
#include "config.h"
#include "mu-cmd.h"
#include "mu-cmd.hh"
#include <iostream>
#include <string>
@ -29,7 +29,7 @@
#include <glib/gprintf.h>
#include "mu-runtime.h"
#include "mu-cmd.h"
#include "mu-cmd.hh"
#include "mu-maildir.h"
#include "mu-query.h"
#include "mu-index.h"
@ -211,7 +211,7 @@ print_sexps (MuMsgIter *iter, unsigned maxnum)
struct Context {
Context(){}
Context (MuConfig *opts) {
Context (const MuConfig *opts) {
const auto dbpath{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB)};
GError *gerr{};
store = mu_store_new_writable (dbpath, NULL);
@ -314,86 +314,33 @@ add_handler (Context& context, const Parameters& params)
}
struct _PartInfo {
GSList *attlist;
MuMsgOptions opts;
struct PartInfo {
Node::Seq attseq;
MuMsgOptions opts;
};
typedef struct _PartInfo PartInfo;
static void
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))
return;
GError *gerr{};
cachefile = mu_msg_part_save_temp (msg,
(MuMsgOptions)(pinfo->opts|MU_MSG_OPTION_OVERWRITE),
part->index, &gerr);
char *cachefile = mu_msg_part_save_temp (
msg, (MuMsgOptions)(pinfo->opts|MU_MSG_OPTION_OVERWRITE),
part->index, &gerr);
if (!cachefile)
throw Error (Error::Code::File, &gerr, "failed to save part");
att = g_strdup_printf ("(:file-name %s :mime-type \"%s/%s\")",
quote(cachefile).c_str(), part->type, part->subtype);
pinfo->attlist = g_slist_append (pinfo->attlist, att);
Node::Seq seq;
seq.add_prop(":file-name", cachefile);
seq.add_prop(":mime-type", format("%s/%s", part->type, part->subtype));
pinfo->attseq.add(std::move(seq));
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
* 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
@ -408,15 +355,15 @@ compose_type (const char *typestr)
static void
compose_handler (Context& context, const Parameters& params)
{
const auto typestr{get_symbol_or(params, "type")};
const auto ctype{compose_type(typestr.c_str())};
if (ctype == INVALID_TYPE)
throw Error(Error::Code::InvalidArgument, "invalid compose type");
auto ctype{get_symbol_or(params, "type")};
Node::Seq compose_seq;
compose_seq.add_prop(":compose", ctype);
// 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{};
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};
const auto opts{message_options(params)};
sexp = mu_msg_to_sexp (msg, docid, NULL, opts);
atts = (ctype == FORWARD) ? include_attachments (msg, opts) : NULL;
compose_seq.add_prop(":original", Mu::msg_to_sexp(msg, docid, {}, opts));
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);
}
print_expr ("(:compose %s :original %s :include %s)",
typestr.c_str(), sexp ? sexp : "nil", atts ? atts : "nil");
} else if (ctype != "new")
throw Error(Error::Code::InvalidArgument, "invalid compose type");
g_free (sexp);
g_free (atts);
print_expr (std::move(compose_seq));
}
@ -1318,7 +1271,7 @@ make_command_map (Context& context)
}
MuError
mu_cmd_server (MuConfig *opts, GError **err) try
mu_cmd_server (const MuConfig *opts, GError **err) try
{
if (opts->commands) {
Context ctx{};
@ -1336,7 +1289,6 @@ mu_cmd_server (MuConfig *opts, GError **err) try
return MU_OK;
}
const auto histpath{std::string{mu_runtime_path(MU_RUNTIME_PATH_CACHE)} + "/history"};
setup_readline(histpath, 50);

View File

@ -19,6 +19,8 @@
#include "config.h"
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -27,7 +29,7 @@
#include "mu-msg.h"
#include "mu-msg-part.h"
#include "mu-cmd.h"
#include "mu-cmd.hh"
#include "mu-maildir.h"
#include "mu-contacts.hh"
#include "mu-runtime.h"
@ -37,10 +39,12 @@
#include "utils/mu-str.h"
#include "utils/mu-date.h"
#include "utils/mu-error.hh"
#define VIEW_TERMINATOR '\f' /* form-feed */
static gboolean
view_msg_sexp (MuMsg *msg, MuConfig *opts)
view_msg_sexp (MuMsg *msg, const MuConfig *opts)
{
char *sexp;
@ -74,13 +78,12 @@ each_part (MuMsg *msg, MuMsgPart *part, gchar **attach)
/* return comma-sep'd list of attachments */
static gchar *
get_attach_str (MuMsg *msg, MuConfig *opts)
get_attach_str (MuMsg *msg, const MuConfig *opts)
{
gchar *attach;
MuMsgOptions msgopts;
msgopts = mu_config_get_msg_options(opts) |
MU_MSG_OPTION_CONSOLE_PASSWORD;
const auto msgopts = (MuMsgOptions)
(mu_config_get_msg_options(opts) | MU_MSG_OPTION_CONSOLE_PASSWORD);
attach = NULL;
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 */
static void
body_or_summary (MuMsg *msg, MuConfig *opts)
body_or_summary (MuMsg *msg, const MuConfig *opts)
{
const char *body;
gboolean color;
gboolean color;
int my_opts = mu_config_get_msg_options(opts) |
MU_MSG_OPTION_CONSOLE_PASSWORD;
color = !opts->nocolor;
body = mu_msg_get_body_text (msg,
mu_config_get_msg_options(opts) |
MU_MSG_OPTION_CONSOLE_PASSWORD);
body = mu_msg_get_body_text (msg, (MuMsgOptions)my_opts);
if (!body) {
if (mu_msg_get_flags (msg) & MU_FLAG_ENCRYPTED) {
color_maybe (MU_COLOR_CYAN);
@ -151,7 +154,7 @@ body_or_summary (MuMsg *msg, MuConfig *opts)
/* we ignore fields for now */
/* summary_len == 0 means "no summary */
static gboolean
view_msg_plain (MuMsg *msg, MuConfig *opts)
view_msg_plain (MuMsg *msg, const MuConfig *opts)
{
gchar *attachs;
time_t date;
@ -189,7 +192,7 @@ view_msg_plain (MuMsg *msg, MuConfig *opts)
static gboolean
handle_msg (const char *fname, MuConfig *opts, GError **err)
handle_msg (const char *fname, const MuConfig *opts, GError **err)
{
MuMsg *msg;
gboolean rv;
@ -216,7 +219,7 @@ handle_msg (const char *fname, MuConfig *opts, GError **err)
}
static gboolean
view_params_valid (MuConfig *opts, GError **err)
view_params_valid (const MuConfig *opts, GError **err)
{
/* note: params[0] will be 'view' */
if (!opts->params[0] || !opts->params[1]) {
@ -240,7 +243,7 @@ view_params_valid (MuConfig *opts, GError **err)
static MuError
cmd_view (MuConfig *opts, GError **err)
cmd_view (const MuConfig *opts, GError **err)
{
int i;
gboolean rv;
@ -266,13 +269,13 @@ cmd_view (MuConfig *opts, GError **err)
leave:
if (!rv)
return err && *err ? (*err)->code : MU_ERROR;
return err && *err ? (MuError)(*err)->code : MU_ERROR;
return MU_OK;
}
static MuError
cmd_mkdir (MuConfig *opts, GError **err)
cmd_mkdir (const MuConfig *opts, GError **err)
{
int i;
@ -289,7 +292,7 @@ cmd_mkdir (MuConfig *opts, GError **err)
for (i = 1; opts->params[i]; ++i)
if (!mu_maildir_mkdir (opts->params[i], opts->dirmode,
FALSE, err))
return err && *err ? (*err)->code :
return err && *err ? (MuError)(*err)->code :
MU_ERROR_FILE_CANNOT_MKDIR;
return MU_OK;
}
@ -312,13 +315,10 @@ check_file_okay (const char *path, gboolean cmd_add)
return TRUE;
}
typedef gboolean (*ForeachMsgFunc) (MuStore *store, const char *path,
GError **err);
typedef bool (*ForeachMsgFunc) (Mu::Store& store, const char *path, GError **err);
static MuError
foreach_msg_file (MuStore *store, MuConfig *opts,
foreach_msg_file (Mu::Store& store, const MuConfig *opts,
ForeachMsgFunc foreach_func, GError **err)
{
unsigned u;
@ -366,17 +366,19 @@ foreach_msg_file (MuStore *store, MuConfig *opts,
}
static gboolean
add_path_func (MuStore *store, const char *path, GError **err)
static bool
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
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->cmd == MU_CONFIG_CMD_ADD,
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);
}
static gboolean
remove_path_func (MuStore *store, const char *path, GError **err)
static bool
remove_path_func (Mu::Store& store, const char *path, GError **err)
{
if (!mu_store_remove_path (store, path)) {
mu_util_g_set_error (err, MU_ERROR_XAPIAN_REMOVE_FAILED,
"failed to remove %s", path);
return FALSE;
}
const auto res = store.remove_message (path);
g_debug ("removed %s (%s)", path, res ? "yes" : "no");
return TRUE;
return true;
}
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->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);
}
static gboolean
tickle_func (MuStore *store, const char *path, GError **err)
static bool
tickle_func (Mu::Store& store, const char *path, GError **err)
{
MuMsg *msg;
gboolean rv;
msg = mu_msg_new_from_file (path, NULL, err);
MuMsg *msg{mu_msg_new_from_file (path, NULL, err)};
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);
return rv;
return res == TRUE;
}
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->cmd == MU_CONFIG_CMD_TICKLE,
@ -509,11 +506,11 @@ print_verdict (VData *vdata, gboolean color, gboolean verbose)
static MuError
cmd_verify (MuConfig *opts, GError **err)
cmd_verify (const MuConfig *opts, GError **err)
{
MuMsg *msg;
MuMsgOptions msgopts;
VData vdata;
int msgopts;
VData vdata;
g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
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.oneline = FALSE;
mu_msg_part_foreach (msg, msgopts,
mu_msg_part_foreach (msg, (MuMsgOptions)msgopts,
(MuMsgPartForeachFunc)each_sig, &vdata);
if (!opts->quiet)
@ -551,20 +548,51 @@ cmd_verify (MuConfig *opts, GError **err)
}
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;
}
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 */
if (!opts->maildir) {
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;
}
path = mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB);
store = mu_store_new_create (path,
opts->maildir,
(const char**)opts->my_addresses,
err);
if (!store)
return MU_G_ERROR_CODE(err);
Mu::StringVec my_addrs;
auto addrs = opts->my_addresses;
while (addrs && *addrs) {
my_addrs.emplace_back (*addrs);
++addrs;
}
Mu::Store store(mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), opts->maildir, my_addrs);
if (!opts->quiet) {
mu_store_print_info (store, opts->nocolor);
cmd_info (store, opts, NULL);
g_print ("\nstore created.\n"
"use 'mu index' to fill the database "
"with your messages.\n"
"see mu-index(1) for details\n");
}
mu_store_unref (store);
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
show_usage (void)
@ -604,46 +649,27 @@ show_usage (void)
"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
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;
MuStore *store;
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;
const Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), true/*readonly*/};
return func (store, opts, err);
}
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
check_params (MuConfig *opts, GError **err)
check_params (const MuConfig *opts, GError **err)
{
if (!opts->params||!opts->params[0]) {/* no command? */
show_usage ();
@ -656,7 +682,7 @@ check_params (MuConfig *opts, GError **err)
}
MuError
mu_cmd_execute (MuConfig *opts, GError **err)
mu_cmd_execute (const MuConfig *opts, GError **err) try
{
MuError merr;
@ -683,9 +709,9 @@ mu_cmd_execute (MuConfig *opts, GError **err)
case MU_CONFIG_CMD_CFIND:
merr = with_readonly_store (mu_cmd_cfind, opts, err); break;
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:
merr = with_readonly_store (cmd_info, opts, err); break;
merr = with_readonly_store (cmd_info, opts, err); break;
/* writable store */
@ -696,7 +722,7 @@ mu_cmd_execute (MuConfig *opts, GError **err)
case MU_CONFIG_CMD_TICKLE:
merr = with_writable_store (cmd_tickle, opts, err); break;
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 */
case MU_CONFIG_CMD_INIT:
@ -709,4 +735,11 @@ mu_cmd_execute (MuConfig *opts, GError **err)
}
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__
#include <glib.h>
#include <mu-config.h>
#include <mu-config.hh>
#include <mu-store.hh>
G_BEGIN_DECLS
@ -37,8 +37,8 @@ G_BEGIN_DECLS
* >MU_OK (0) results, MU_EXITCODE_NO_MATCHES if the command
* 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
@ -49,7 +49,7 @@ MuError mu_cmd_find (MuStore *store, MuConfig *opts, GError **err);
* @return MU_OK (0) if the command succeeds,
* 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,
* 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
@ -73,7 +73,8 @@ MuError mu_cmd_script (MuConfig *opts, GError **err);
* @return MU_OK (0) if the command succeeds,
* 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'
@ -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
*/
MuError mu_cmd_execute (MuConfig *opts, GError **err);
MuError mu_cmd_execute (const MuConfig *opts, GError **err);
/**
* execute the 'index' command
@ -95,7 +96,7 @@ MuError mu_cmd_execute (MuConfig *opts, GError **err);
* @return MU_OK (0) if the command succeeded,
* 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
@ -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
*/
MuError mu_cmd_server (MuConfig *opts, GError **err);
MuError mu_cmd_server (const MuConfig *opts, GError **err);
G_END_DECLS

View File

@ -24,8 +24,9 @@
#include <unistd.h>
#include <stdio.h>
#include "mu-config.h"
#include "mu-cmd.h"
#include "mu-config.hh"
#include "mu-cmd.hh"
#include "mu-msg.h"
static MuConfig MU_CONFIG;
@ -115,7 +116,7 @@ config_options_group_mu (void)
{G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY,
&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);
@ -143,7 +144,7 @@ config_options_group_init (void)
{"my-address", 0, 0, G_OPTION_ARG_STRING_ARRAY,
&MU_CONFIG.my_addresses, "my e-mail address; can be used multiple times",
"<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",
@ -186,7 +187,7 @@ config_options_group_index (void)
"only check dir-timestamps (false)", NULL},
{"nocleanup", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.nocleanup,
"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",
@ -257,7 +258,7 @@ config_options_group_find (void)
{"after", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.after,
"only show messages whose m_time > T (t_time)",
"<timestamp>"},
{NULL, 0, 0, 0, NULL, NULL, NULL}
{NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}
};
og = g_option_group_new("find",
@ -275,7 +276,7 @@ config_options_group_mkdir (void)
GOptionEntry entries[] = {
{"mode", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.dirmode,
"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 */
@ -309,7 +310,7 @@ config_options_group_cfind (void)
"whether to only get 'personal' contacts", NULL},
{"after", 0, 0, G_OPTION_ARG_INT, &MU_CONFIG.after,
"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",
@ -326,7 +327,7 @@ config_options_group_script (void)
GOptionEntry entries[] = {
{G_OPTION_REMAINING, 0,0, G_OPTION_ARG_STRING_ARRAY,
&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",
@ -359,7 +360,7 @@ crypto_option_entries (void)
"attempt to use the GPG agent (false)", NULL},
{"decrypt", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.decrypt,
"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;
@ -378,7 +379,7 @@ config_options_group_view (void)
"<term>"},
{"format", 'o', 0, G_OPTION_ARG_STRING, &MU_CONFIG.formatstr,
"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",
@ -419,7 +420,7 @@ config_options_group_extract (void)
"overwrite existing files (false)", NULL},
{"play", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.play,
"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",
"Options for the 'extract' command",
@ -453,7 +454,7 @@ config_options_group_server (void)
"list the available command and their parameters, then exit", NULL},
{"eval", 'e', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING,
&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",
@ -587,7 +588,7 @@ massage_help (const char *help)
char *str;
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,
-1, 0, "",
G_REGEX_MATCH_NEWLINE_ANY, NULL);
@ -774,7 +775,7 @@ mu_config_uninit (MuConfig *opts)
}
size_t
mu_config_param_num (MuConfig *opts)
mu_config_param_num (const MuConfig *opts)
{
size_t n;
@ -786,9 +787,9 @@ mu_config_param_num (MuConfig *opts)
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;
@ -803,5 +804,5 @@ mu_config_get_msg_options (MuConfig *muopts)
if (muopts->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
*
*/
MuError mu_config_execute (MuConfig *conf);
MuError mu_config_execute (const MuConfig *conf);
/**
* 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
*/
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
*/
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
*/
void mu_config_show_help (MuConfigCmd cmd);
void mu_config_show_help (const MuConfigCmd cmd);
G_END_DECLS

View File

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

View File

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

View File

@ -754,8 +754,8 @@ main (int argc, char *argv[])
if (!g_test_verbose())
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);
rv = g_test_run ();

View File

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