clang-format: update c/cc coding style
Update all cc code using .clang-format; please do so as well for future PRs etc.; emacs has a handy 'clang-format' mode to make this automatic. For comparing old changes with git blame, we can disregard this one using --ignore-rev (see https://www.moxio.com/blog/43/ignoring-bulk-change-commits-with-git-blame )
This commit is contained in:
@ -47,16 +47,16 @@ using namespace Mu;
|
||||
* g_free)
|
||||
*/
|
||||
static gchar*
|
||||
guess_last_name (const char *name)
|
||||
guess_last_name(const char* name)
|
||||
{
|
||||
const gchar *lastsp;
|
||||
const gchar* lastsp;
|
||||
|
||||
if (!name)
|
||||
return g_strdup ("");
|
||||
if (!name)
|
||||
return g_strdup("");
|
||||
|
||||
lastsp = g_strrstr (name, " ");
|
||||
lastsp = g_strrstr(name, " ");
|
||||
|
||||
return g_strdup (lastsp ? lastsp + 1 : "");
|
||||
return g_strdup(lastsp ? lastsp + 1 : "");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,19 +69,19 @@ guess_last_name (const char *name)
|
||||
* g_free)
|
||||
*/
|
||||
static gchar*
|
||||
guess_first_name (const char *name)
|
||||
guess_first_name(const char* name)
|
||||
{
|
||||
const gchar *lastsp;
|
||||
const gchar* lastsp;
|
||||
|
||||
if (!name)
|
||||
return g_strdup ("");
|
||||
if (!name)
|
||||
return g_strdup("");
|
||||
|
||||
lastsp = g_strrstr (name, " ");
|
||||
lastsp = g_strrstr(name, " ");
|
||||
|
||||
if (lastsp)
|
||||
return g_strndup (name, lastsp - name);
|
||||
else
|
||||
return g_strdup (name);
|
||||
if (lastsp)
|
||||
return g_strndup(name, lastsp - name);
|
||||
else
|
||||
return g_strdup(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -95,336 +95,322 @@ guess_first_name (const char *name)
|
||||
* @return the guessed nick, as a newly allocated string (free with g_free)
|
||||
*/
|
||||
static gchar*
|
||||
cleanup_str (const char* str)
|
||||
cleanup_str(const char* str)
|
||||
{
|
||||
gchar *s;
|
||||
const gchar *cur;
|
||||
unsigned i;
|
||||
gchar* s;
|
||||
const gchar* cur;
|
||||
unsigned i;
|
||||
|
||||
if (mu_str_is_empty(str))
|
||||
return g_strdup ("");
|
||||
if (mu_str_is_empty(str))
|
||||
return g_strdup("");
|
||||
|
||||
s = g_new0 (char, strlen(str) + 1);
|
||||
s = g_new0(char, strlen(str) + 1);
|
||||
|
||||
for (cur = str, i = 0; *cur; ++cur) {
|
||||
if (ispunct(*cur) || isspace(*cur))
|
||||
continue;
|
||||
else
|
||||
s[i++] = *cur;
|
||||
}
|
||||
for (cur = str, i = 0; *cur; ++cur) {
|
||||
if (ispunct(*cur) || isspace(*cur))
|
||||
continue;
|
||||
else
|
||||
s[i++] = *cur;
|
||||
}
|
||||
|
||||
return s;
|
||||
return s;
|
||||
}
|
||||
|
||||
static char*
|
||||
uniquify_nick (const char *nick, GHashTable *nicks)
|
||||
uniquify_nick(const char* nick, GHashTable* nicks)
|
||||
{
|
||||
guint u;
|
||||
guint u;
|
||||
|
||||
for (u = 2; u != 1000; ++u) {
|
||||
char *cand;
|
||||
cand = g_strdup_printf ("%s%u", nick, u);
|
||||
if (!g_hash_table_contains (nicks, cand))
|
||||
return cand;
|
||||
}
|
||||
for (u = 2; u != 1000; ++u) {
|
||||
char* cand;
|
||||
cand = g_strdup_printf("%s%u", nick, u);
|
||||
if (!g_hash_table_contains(nicks, cand))
|
||||
return cand;
|
||||
}
|
||||
|
||||
return g_strdup (nick); /* if all else fails */
|
||||
return g_strdup(nick); /* if all else fails */
|
||||
}
|
||||
|
||||
|
||||
static gchar*
|
||||
guess_nick (const char* name, GHashTable *nicks)
|
||||
guess_nick(const char* name, GHashTable* nicks)
|
||||
{
|
||||
gchar *fname, *lname, *nick;
|
||||
gchar initial[7];
|
||||
gchar *fname, *lname, *nick;
|
||||
gchar initial[7];
|
||||
|
||||
fname = guess_first_name (name);
|
||||
lname = guess_last_name (name);
|
||||
fname = guess_first_name(name);
|
||||
lname = guess_last_name(name);
|
||||
|
||||
/* if there's no last name, use first name as the nick */
|
||||
if (mu_str_is_empty(fname) || mu_str_is_empty(lname)) {
|
||||
g_free (lname);
|
||||
nick = fname;
|
||||
goto leave;
|
||||
}
|
||||
/* if there's no last name, use first name as the nick */
|
||||
if (mu_str_is_empty(fname) || mu_str_is_empty(lname)) {
|
||||
g_free(lname);
|
||||
nick = fname;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
memset (initial, 0, sizeof(initial));
|
||||
/* couldn't we get an initial for the last name? */
|
||||
if (g_unichar_to_utf8 (g_utf8_get_char (lname), initial) == 0) {
|
||||
g_free (lname);
|
||||
nick = fname;
|
||||
goto leave;
|
||||
}
|
||||
memset(initial, 0, sizeof(initial));
|
||||
/* couldn't we get an initial for the last name? */
|
||||
if (g_unichar_to_utf8(g_utf8_get_char(lname), initial) == 0) {
|
||||
g_free(lname);
|
||||
nick = fname;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
nick = g_strdup_printf ("%s%s", fname, initial);
|
||||
g_free (fname);
|
||||
g_free (lname);
|
||||
nick = g_strdup_printf("%s%s", fname, initial);
|
||||
g_free(fname);
|
||||
g_free(lname);
|
||||
|
||||
leave:
|
||||
{
|
||||
gchar *tmp;
|
||||
tmp = cleanup_str (nick);
|
||||
g_free (nick);
|
||||
nick = tmp;
|
||||
}
|
||||
leave : {
|
||||
gchar* tmp;
|
||||
tmp = cleanup_str(nick);
|
||||
g_free(nick);
|
||||
nick = tmp;
|
||||
}
|
||||
|
||||
if (g_hash_table_contains (nicks, nick)) {
|
||||
char *tmp;
|
||||
tmp = uniquify_nick (nick, nicks);
|
||||
g_free (nick);
|
||||
nick = tmp;
|
||||
}
|
||||
if (g_hash_table_contains(nicks, nick)) {
|
||||
char* tmp;
|
||||
tmp = uniquify_nick(nick, nicks);
|
||||
g_free(nick);
|
||||
nick = tmp;
|
||||
}
|
||||
|
||||
g_hash_table_add (nicks, g_strdup(nick));
|
||||
g_hash_table_add(nicks, g_strdup(nick));
|
||||
|
||||
return nick;
|
||||
return nick;
|
||||
}
|
||||
|
||||
static void
|
||||
print_header (const MuConfigFormat format)
|
||||
print_header(const MuConfigFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case MU_CONFIG_FORMAT_BBDB:
|
||||
g_print (";; -*-coding: utf-8-emacs;-*-\n"
|
||||
";;; file-version: 6\n");
|
||||
break;
|
||||
case MU_CONFIG_FORMAT_MUTT_AB:
|
||||
g_print ("Matching addresses in the mu database:\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (format) {
|
||||
case MU_CONFIG_FORMAT_BBDB:
|
||||
g_print(";; -*-coding: utf-8-emacs;-*-\n"
|
||||
";;; file-version: 6\n");
|
||||
break;
|
||||
case MU_CONFIG_FORMAT_MUTT_AB: g_print("Matching addresses in the mu database:\n"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
each_contact_bbdb (const std::string& email, const std::string& 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.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);
|
||||
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.c_str(), now, timestamp);
|
||||
g_print("[\"%s\" \"%s\" nil nil nil nil (\"%s\") "
|
||||
"((creation-date . \"%s\") (time-stamp . \"%s\")) nil]\n",
|
||||
fname,
|
||||
lname,
|
||||
email.c_str(),
|
||||
now,
|
||||
timestamp);
|
||||
|
||||
g_free (now);
|
||||
g_free (timestamp);
|
||||
g_free (fname);
|
||||
g_free (lname);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
each_contact_mutt_alias (const std::string& email, const std::string& name,
|
||||
GHashTable *nicks)
|
||||
{
|
||||
if (name.empty())
|
||||
return;
|
||||
|
||||
char *nick = guess_nick (name.c_str(), nicks);
|
||||
mu_util_print_encoded ("alias %s %s <%s>\n",
|
||||
nick, name.c_str(), email.c_str());
|
||||
g_free (nick);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
each_contact_wl (const std::string& email, const std::string& name, GHashTable *nicks)
|
||||
{
|
||||
if (name.empty())
|
||||
return;
|
||||
|
||||
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);
|
||||
g_free(now);
|
||||
g_free(timestamp);
|
||||
g_free(fname);
|
||||
g_free(lname);
|
||||
}
|
||||
|
||||
static void
|
||||
print_plain (const std::string& email, const std::string& name, bool color)
|
||||
each_contact_mutt_alias(const std::string& email, const std::string& name, GHashTable* nicks)
|
||||
{
|
||||
if (!name.empty()) {
|
||||
if (color)
|
||||
::fputs (MU_COLOR_MAGENTA, stdout);
|
||||
mu_util_fputs_encoded (name.c_str(), stdout);
|
||||
::fputs (" ", stdout);
|
||||
}
|
||||
if (name.empty())
|
||||
return;
|
||||
|
||||
if (color)
|
||||
::fputs (MU_COLOR_GREEN, stdout);
|
||||
char* nick = guess_nick(name.c_str(), nicks);
|
||||
mu_util_print_encoded("alias %s %s <%s>\n", nick, name.c_str(), email.c_str());
|
||||
g_free(nick);
|
||||
}
|
||||
|
||||
mu_util_fputs_encoded (email.c_str(), stdout);
|
||||
static void
|
||||
each_contact_wl(const std::string& email, const std::string& name, GHashTable* nicks)
|
||||
{
|
||||
if (name.empty())
|
||||
return;
|
||||
|
||||
if (color)
|
||||
fputs (MU_COLOR_DEFAULT, stdout);
|
||||
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);
|
||||
}
|
||||
|
||||
fputs ("\n", stdout);
|
||||
static void
|
||||
print_plain(const std::string& email, const std::string& name, bool color)
|
||||
{
|
||||
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);
|
||||
|
||||
mu_util_fputs_encoded(email.c_str(), stdout);
|
||||
|
||||
if (color)
|
||||
fputs(MU_COLOR_DEFAULT, stdout);
|
||||
|
||||
fputs("\n", stdout);
|
||||
}
|
||||
|
||||
struct ECData {
|
||||
MuConfigFormat format;
|
||||
gboolean color, personal;
|
||||
time_t after;
|
||||
GRegex *rx;
|
||||
GHashTable *nicks;
|
||||
size_t n;
|
||||
MuConfigFormat format;
|
||||
gboolean color, personal;
|
||||
time_t after;
|
||||
GRegex* rx;
|
||||
GHashTable* nicks;
|
||||
size_t n;
|
||||
};
|
||||
|
||||
static void
|
||||
each_contact (const Mu::ContactInfo& ci, ECData& ecdata)
|
||||
each_contact(const Mu::ContactInfo& ci, ECData& ecdata)
|
||||
{
|
||||
if (ecdata.personal && ci.personal)
|
||||
return;
|
||||
if (ecdata.personal && ci.personal)
|
||||
return;
|
||||
|
||||
if (ci.tstamp < ecdata.after)
|
||||
return;
|
||||
if (ci.tstamp < ecdata.after)
|
||||
return;
|
||||
|
||||
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;
|
||||
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) {
|
||||
case MU_CONFIG_FORMAT_MUTT_ALIAS:
|
||||
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",
|
||||
ci.email.c_str(), ci.name.c_str());
|
||||
break;
|
||||
case MU_CONFIG_FORMAT_WL:
|
||||
each_contact_wl (ci.email, ci.name, ecdata.nicks);
|
||||
break;
|
||||
case MU_CONFIG_FORMAT_ORG_CONTACT:
|
||||
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 (ci.email, ci.name, ci.last_seen);
|
||||
break;
|
||||
case MU_CONFIG_FORMAT_CSV:
|
||||
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(&ci.last_seen));
|
||||
g_print ("%s\n\tname: %s\n\t%s\n\tpersonal: %s\n\tfreq: %zu\n"
|
||||
"\tlast-seen: %s\n",
|
||||
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 (ci.email, ci.name, ecdata.color);
|
||||
}
|
||||
switch (ecdata.format) {
|
||||
case MU_CONFIG_FORMAT_MUTT_ALIAS:
|
||||
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", ci.email.c_str(), ci.name.c_str());
|
||||
break;
|
||||
case MU_CONFIG_FORMAT_WL: each_contact_wl(ci.email, ci.name, ecdata.nicks); break;
|
||||
case MU_CONFIG_FORMAT_ORG_CONTACT:
|
||||
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(ci.email, ci.name, ci.last_seen); break;
|
||||
case MU_CONFIG_FORMAT_CSV:
|
||||
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(&ci.last_seen));
|
||||
g_print("%s\n\tname: %s\n\t%s\n\tpersonal: %s\n\tfreq: %zu\n"
|
||||
"\tlast-seen: %s\n",
|
||||
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(ci.email, ci.name, ecdata.color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static MuError
|
||||
run_cmd_cfind (const Mu::Store& store,
|
||||
const char* pattern,
|
||||
gboolean personal,
|
||||
time_t after,
|
||||
const 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)
|
||||
{
|
||||
ECData ecdata{};
|
||||
ECData ecdata{};
|
||||
|
||||
memset(&ecdata, 0, sizeof(ecdata));
|
||||
memset(&ecdata, 0, sizeof(ecdata));
|
||||
|
||||
if (pattern) {
|
||||
ecdata.rx = g_regex_new (pattern,
|
||||
(GRegexCompileFlags)(G_REGEX_CASELESS|G_REGEX_OPTIMIZE),
|
||||
(GRegexMatchFlags)0, err);
|
||||
if (!ecdata.rx)
|
||||
return MU_ERROR_CONTACTS;
|
||||
}
|
||||
if (pattern) {
|
||||
ecdata.rx = g_regex_new(pattern,
|
||||
(GRegexCompileFlags)(G_REGEX_CASELESS | G_REGEX_OPTIMIZE),
|
||||
(GRegexMatchFlags)0,
|
||||
err);
|
||||
if (!ecdata.rx)
|
||||
return MU_ERROR_CONTACTS;
|
||||
}
|
||||
|
||||
ecdata.personal = personal;
|
||||
ecdata.n = 0;
|
||||
ecdata.after = after;
|
||||
ecdata.format = format;
|
||||
ecdata.color = color;
|
||||
ecdata.nicks = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, NULL);
|
||||
ecdata.personal = personal;
|
||||
ecdata.n = 0;
|
||||
ecdata.after = after;
|
||||
ecdata.format = format;
|
||||
ecdata.color = color;
|
||||
ecdata.nicks = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
|
||||
|
||||
print_header (format);
|
||||
print_header(format);
|
||||
|
||||
store.contacts().for_each([&](const auto& ci) { each_contact(ci, 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)
|
||||
g_regex_unref (ecdata.rx);
|
||||
if (ecdata.rx)
|
||||
g_regex_unref(ecdata.rx);
|
||||
|
||||
if (ecdata.n == 0) {
|
||||
g_printerr ("no matching contacts found\n");
|
||||
return MU_ERROR_NO_MATCHES;
|
||||
}
|
||||
if (ecdata.n == 0) {
|
||||
g_printerr("no matching contacts found\n");
|
||||
return MU_ERROR_NO_MATCHES;
|
||||
}
|
||||
|
||||
return MU_OK;
|
||||
return MU_OK;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cfind_params_valid (const MuConfig *opts)
|
||||
cfind_params_valid(const MuConfig* opts)
|
||||
{
|
||||
switch (opts->format) {
|
||||
case MU_CONFIG_FORMAT_PLAIN:
|
||||
case MU_CONFIG_FORMAT_MUTT_ALIAS:
|
||||
case MU_CONFIG_FORMAT_MUTT_AB:
|
||||
case MU_CONFIG_FORMAT_WL:
|
||||
case MU_CONFIG_FORMAT_BBDB:
|
||||
case MU_CONFIG_FORMAT_CSV:
|
||||
case MU_CONFIG_FORMAT_ORG_CONTACT:
|
||||
case MU_CONFIG_FORMAT_DEBUG:
|
||||
break;
|
||||
default:
|
||||
g_printerr ("invalid output format %s\n",
|
||||
opts->formatstr ? opts->formatstr : "<none>");
|
||||
return FALSE;
|
||||
}
|
||||
switch (opts->format) {
|
||||
case MU_CONFIG_FORMAT_PLAIN:
|
||||
case MU_CONFIG_FORMAT_MUTT_ALIAS:
|
||||
case MU_CONFIG_FORMAT_MUTT_AB:
|
||||
case MU_CONFIG_FORMAT_WL:
|
||||
case MU_CONFIG_FORMAT_BBDB:
|
||||
case MU_CONFIG_FORMAT_CSV:
|
||||
case MU_CONFIG_FORMAT_ORG_CONTACT:
|
||||
case MU_CONFIG_FORMAT_DEBUG: break;
|
||||
default:
|
||||
g_printerr("invalid output format %s\n",
|
||||
opts->formatstr ? opts->formatstr : "<none>");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* only one pattern allowed */
|
||||
if (opts->params[1] && opts->params[2]) {
|
||||
g_printerr ("usage: mu cfind [options] [<ptrn>]\n");
|
||||
return FALSE;
|
||||
}
|
||||
/* only one pattern allowed */
|
||||
if (opts->params[1] && opts->params[2]) {
|
||||
g_printerr("usage: mu cfind [options] [<ptrn>]\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
MuError
|
||||
Mu::mu_cmd_cfind (const Mu::Store& store, const MuConfig *opts, GError **err)
|
||||
Mu::mu_cmd_cfind(const 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_CFIND,
|
||||
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))
|
||||
throw Mu::Error(Mu::Error::Code::InvalidArgument,
|
||||
"invalid parameters");
|
||||
if (!cfind_params_valid(opts))
|
||||
throw Mu::Error(Mu::Error::Code::InvalidArgument, "invalid parameters");
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -32,144 +32,138 @@
|
||||
using namespace Mu;
|
||||
|
||||
static gboolean
|
||||
save_part (MuMsg *msg, const char *targetdir, guint partidx, const MuConfig *opts)
|
||||
save_part(MuMsg* msg, const char* targetdir, guint partidx, const MuConfig* opts)
|
||||
{
|
||||
GError *err;
|
||||
gchar *filepath;
|
||||
gboolean rv;
|
||||
GError* err;
|
||||
gchar* filepath;
|
||||
gboolean rv;
|
||||
MuMsgOptions msgopts;
|
||||
|
||||
err = NULL;
|
||||
rv = FALSE;
|
||||
rv = FALSE;
|
||||
|
||||
msgopts = mu_config_get_msg_options (opts);
|
||||
msgopts = mu_config_get_msg_options(opts);
|
||||
|
||||
filepath = mu_msg_part_get_path (msg, msgopts, targetdir, partidx, &err);
|
||||
filepath = mu_msg_part_get_path(msg, msgopts, targetdir, partidx, &err);
|
||||
if (!filepath)
|
||||
goto exit;
|
||||
|
||||
if (!mu_msg_part_save (msg, msgopts, filepath, partidx, &err))
|
||||
if (!mu_msg_part_save(msg, msgopts, filepath, partidx, &err))
|
||||
goto exit;
|
||||
|
||||
if (opts->play)
|
||||
rv = mu_util_play (filepath, TRUE, FALSE, &err);
|
||||
rv = mu_util_play(filepath, TRUE, FALSE, &err);
|
||||
else
|
||||
rv = TRUE;
|
||||
exit:
|
||||
if (err) {
|
||||
g_printerr ("error with MIME-part: %s\n", err->message);
|
||||
g_clear_error (&err);
|
||||
g_printerr("error with MIME-part: %s\n", err->message);
|
||||
g_clear_error(&err);
|
||||
}
|
||||
|
||||
g_free (filepath);
|
||||
g_free(filepath);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static gboolean
|
||||
save_numbered_parts (MuMsg *msg, const MuConfig *opts)
|
||||
save_numbered_parts(MuMsg* msg, const MuConfig* opts)
|
||||
{
|
||||
gboolean rv;
|
||||
char **parts, **cur;
|
||||
char ** parts, **cur;
|
||||
|
||||
parts = g_strsplit (opts->parts, ",", 0);
|
||||
parts = g_strsplit(opts->parts, ",", 0);
|
||||
|
||||
for (rv = TRUE, cur = parts; cur && *cur; ++cur) {
|
||||
|
||||
unsigned idx;
|
||||
int i;
|
||||
char *endptr;
|
||||
int i;
|
||||
char* endptr;
|
||||
|
||||
idx = (unsigned)(i = strtol (*cur, &endptr, 10));
|
||||
idx = (unsigned)(i = strtol(*cur, &endptr, 10));
|
||||
if (i < 0 || *cur == endptr) {
|
||||
g_printerr ("invalid MIME-part index '%s'\n", *cur);
|
||||
g_printerr("invalid MIME-part index '%s'\n", *cur);
|
||||
rv = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!save_part (msg, opts->targetdir, idx, opts)) {
|
||||
g_printerr ("failed to save MIME-part %d\n", idx);
|
||||
if (!save_part(msg, opts->targetdir, idx, opts)) {
|
||||
g_printerr("failed to save MIME-part %d\n", idx);
|
||||
rv = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev (parts);
|
||||
g_strfreev(parts);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static GRegex*
|
||||
anchored_regex (const char* pattern)
|
||||
anchored_regex(const char* pattern)
|
||||
{
|
||||
GRegex *rx;
|
||||
GError *err;
|
||||
gchar *anchored;
|
||||
GRegex* rx;
|
||||
GError* err;
|
||||
gchar* anchored;
|
||||
|
||||
|
||||
anchored = g_strdup_printf
|
||||
("%s%s%s",
|
||||
pattern[0] == '^' ? "" : "^",
|
||||
pattern,
|
||||
pattern[strlen(pattern)-1] == '$' ? "" : "$");
|
||||
anchored = g_strdup_printf("%s%s%s",
|
||||
pattern[0] == '^' ? "" : "^",
|
||||
pattern,
|
||||
pattern[strlen(pattern) - 1] == '$' ? "" : "$");
|
||||
|
||||
err = NULL;
|
||||
rx = g_regex_new (anchored,
|
||||
(GRegexCompileFlags)(G_REGEX_CASELESS|G_REGEX_OPTIMIZE),
|
||||
(GRegexMatchFlags)0, &err);
|
||||
g_free (anchored);
|
||||
rx = g_regex_new(anchored,
|
||||
(GRegexCompileFlags)(G_REGEX_CASELESS | G_REGEX_OPTIMIZE),
|
||||
(GRegexMatchFlags)0,
|
||||
&err);
|
||||
g_free(anchored);
|
||||
|
||||
if (!rx) {
|
||||
g_printerr ("error in regular expression '%s': %s\n",
|
||||
pattern, err->message ? err->message : "error");
|
||||
g_error_free (err);
|
||||
g_printerr("error in regular expression '%s': %s\n",
|
||||
pattern,
|
||||
err->message ? err->message : "error");
|
||||
g_error_free(err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rx;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
save_part_with_filename (MuMsg *msg, const char *pattern, const MuConfig *opts)
|
||||
save_part_with_filename(MuMsg* msg, const char* pattern, const MuConfig* opts)
|
||||
{
|
||||
GSList *lst, *cur;
|
||||
GRegex *rx;
|
||||
gboolean rv;
|
||||
GSList * lst, *cur;
|
||||
GRegex* rx;
|
||||
gboolean rv;
|
||||
MuMsgOptions msgopts;
|
||||
|
||||
msgopts = mu_config_get_msg_options (opts);
|
||||
msgopts = mu_config_get_msg_options(opts);
|
||||
|
||||
/* 'anchor' the pattern with '^...$' if not already */
|
||||
rx = anchored_regex (pattern);
|
||||
rx = anchored_regex(pattern);
|
||||
if (!rx)
|
||||
return FALSE;
|
||||
|
||||
lst = mu_msg_find_files (msg, msgopts, rx);
|
||||
g_regex_unref (rx);
|
||||
lst = mu_msg_find_files(msg, msgopts, rx);
|
||||
g_regex_unref(rx);
|
||||
if (!lst) {
|
||||
g_printerr ("no matching attachments found");
|
||||
g_printerr("no matching attachments found");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (cur = lst, rv = TRUE; cur; cur = g_slist_next (cur))
|
||||
rv = rv && save_part (msg, opts->targetdir,
|
||||
GPOINTER_TO_UINT(cur->data), opts);
|
||||
g_slist_free (lst);
|
||||
for (cur = lst, rv = TRUE; cur; cur = g_slist_next(cur))
|
||||
rv = rv && save_part(msg, opts->targetdir, GPOINTER_TO_UINT(cur->data), opts);
|
||||
g_slist_free(lst);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
struct _SaveData {
|
||||
gboolean result;
|
||||
guint saved_num;
|
||||
const MuConfig *opts;
|
||||
gboolean result;
|
||||
guint saved_num;
|
||||
const MuConfig* opts;
|
||||
};
|
||||
typedef struct _SaveData SaveData;
|
||||
|
||||
typedef struct _SaveData SaveData;
|
||||
|
||||
static gboolean
|
||||
ignore_part (MuMsg *msg, MuMsgPart *part, SaveData *sd)
|
||||
ignore_part(MuMsg* msg, MuMsgPart* part, SaveData* sd)
|
||||
{
|
||||
/* something went wrong somewhere; stop */
|
||||
if (!sd->result)
|
||||
@ -180,93 +174,86 @@ ignore_part (MuMsg *msg, MuMsgPart *part, SaveData *sd)
|
||||
return TRUE;
|
||||
|
||||
/* filter out non-attachments? */
|
||||
if (!sd->opts->save_all &&
|
||||
!(mu_msg_part_maybe_attachment (part)))
|
||||
if (!sd->opts->save_all && !(mu_msg_part_maybe_attachment(part)))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
save_part_if (MuMsg *msg, MuMsgPart *part, SaveData *sd)
|
||||
save_part_if(MuMsg* msg, MuMsgPart* part, SaveData* sd)
|
||||
{
|
||||
gchar *filepath;
|
||||
gboolean rv;
|
||||
GError *err;
|
||||
gchar* filepath;
|
||||
gboolean rv;
|
||||
GError* err;
|
||||
MuMsgOptions msgopts;
|
||||
|
||||
if (ignore_part (msg, part, sd))
|
||||
if (ignore_part(msg, part, sd))
|
||||
return;
|
||||
|
||||
rv = FALSE;
|
||||
rv = FALSE;
|
||||
filepath = NULL;
|
||||
err = NULL;
|
||||
|
||||
msgopts = mu_config_get_msg_options (sd->opts);
|
||||
filepath = mu_msg_part_get_path (msg, msgopts,
|
||||
sd->opts->targetdir,
|
||||
part->index, &err);
|
||||
msgopts = mu_config_get_msg_options(sd->opts);
|
||||
filepath = mu_msg_part_get_path(msg, msgopts, sd->opts->targetdir, part->index, &err);
|
||||
if (!filepath)
|
||||
goto exit;
|
||||
|
||||
if (!mu_msg_part_save (msg, msgopts, filepath, part->index, &err))
|
||||
if (!mu_msg_part_save(msg, msgopts, filepath, part->index, &err))
|
||||
goto exit;
|
||||
|
||||
if (sd->opts->play)
|
||||
rv = mu_util_play (filepath, TRUE, FALSE, &err);
|
||||
rv = mu_util_play(filepath, TRUE, FALSE, &err);
|
||||
else
|
||||
rv = TRUE;
|
||||
|
||||
++sd->saved_num;
|
||||
exit:
|
||||
if (err)
|
||||
g_printerr ("error saving MIME part: %s", err->message);
|
||||
g_printerr("error saving MIME part: %s", err->message);
|
||||
|
||||
g_free (filepath);
|
||||
g_clear_error (&err);
|
||||
g_free(filepath);
|
||||
g_clear_error(&err);
|
||||
|
||||
sd->result = rv;
|
||||
|
||||
}
|
||||
|
||||
static gboolean
|
||||
save_certain_parts (MuMsg *msg, const MuConfig *opts)
|
||||
save_certain_parts(MuMsg* msg, const MuConfig* opts)
|
||||
{
|
||||
SaveData sd;
|
||||
SaveData sd;
|
||||
MuMsgOptions msgopts;
|
||||
|
||||
sd.result = TRUE;
|
||||
sd.saved_num = 0;
|
||||
sd.opts = opts;
|
||||
sd.result = TRUE;
|
||||
sd.saved_num = 0;
|
||||
sd.opts = opts;
|
||||
|
||||
msgopts = mu_config_get_msg_options (opts);
|
||||
mu_msg_part_foreach (msg, msgopts,
|
||||
(MuMsgPartForeachFunc)save_part_if, &sd);
|
||||
msgopts = mu_config_get_msg_options(opts);
|
||||
mu_msg_part_foreach(msg, msgopts, (MuMsgPartForeachFunc)save_part_if, &sd);
|
||||
|
||||
if (sd.saved_num == 0) {
|
||||
g_printerr ("no %s extracted from this message",
|
||||
opts->save_attachments ? "attachments" : "parts");
|
||||
g_printerr("no %s extracted from this message",
|
||||
opts->save_attachments ? "attachments" : "parts");
|
||||
sd.result = FALSE;
|
||||
}
|
||||
|
||||
return sd.result;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
save_parts (const char *path, const char *filename, const MuConfig *opts)
|
||||
save_parts(const char* path, const char* filename, const MuConfig* opts)
|
||||
{
|
||||
MuMsg* msg;
|
||||
MuMsg* msg;
|
||||
gboolean rv;
|
||||
GError *err;
|
||||
GError* err;
|
||||
|
||||
err = NULL;
|
||||
msg = mu_msg_new_from_file (path, NULL, &err);
|
||||
msg = mu_msg_new_from_file(path, NULL, &err);
|
||||
if (!msg) {
|
||||
if (err) {
|
||||
g_printerr ("error: %s", err->message);
|
||||
g_error_free (err);
|
||||
g_printerr("error: %s", err->message);
|
||||
g_error_free(err);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@ -276,21 +263,25 @@ save_parts (const char *path, const char *filename, const MuConfig *opts)
|
||||
|
||||
/* should we save some explicit parts? */
|
||||
if (opts->parts)
|
||||
rv = save_numbered_parts (msg, opts);
|
||||
rv = save_numbered_parts(msg, opts);
|
||||
else if (filename)
|
||||
rv = save_part_with_filename (msg, filename, opts);
|
||||
rv = save_part_with_filename(msg, filename, opts);
|
||||
else
|
||||
rv = save_certain_parts (msg, opts);
|
||||
rv = save_certain_parts(msg, opts);
|
||||
|
||||
mu_msg_unref (msg);
|
||||
mu_msg_unref(msg);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define color_maybe(C) do{ if (color) fputs ((C),stdout);}while(0)
|
||||
#define color_maybe(C) \
|
||||
do { \
|
||||
if (color) \
|
||||
fputs((C), stdout); \
|
||||
} while (0)
|
||||
|
||||
static const char*
|
||||
disp_str (MuMsgPartType ptype)
|
||||
disp_str(MuMsgPartType ptype)
|
||||
{
|
||||
if (ptype & MU_MSG_PART_TYPE_ATTACHMENT)
|
||||
return "attach";
|
||||
@ -300,94 +291,89 @@ disp_str (MuMsgPartType ptype)
|
||||
}
|
||||
|
||||
static void
|
||||
each_part_show (MuMsg *msg, MuMsgPart *part, gboolean color)
|
||||
each_part_show(MuMsg* msg, MuMsgPart* part, gboolean color)
|
||||
{
|
||||
/* index */
|
||||
g_print (" %u ", part->index);
|
||||
g_print(" %u ", part->index);
|
||||
|
||||
/* filename */
|
||||
color_maybe (MU_COLOR_GREEN); {
|
||||
gchar *fname;
|
||||
fname = mu_msg_part_get_filename (part, FALSE);
|
||||
mu_util_fputs_encoded (fname ? fname : "<none>", stdout);
|
||||
g_free (fname);
|
||||
color_maybe(MU_COLOR_GREEN);
|
||||
{
|
||||
gchar* fname;
|
||||
fname = mu_msg_part_get_filename(part, FALSE);
|
||||
mu_util_fputs_encoded(fname ? fname : "<none>", stdout);
|
||||
g_free(fname);
|
||||
}
|
||||
/* content-type */
|
||||
color_maybe (MU_COLOR_BLUE);
|
||||
mu_util_print_encoded (
|
||||
" %s/%s ",
|
||||
part->type ? part->type : "<none>",
|
||||
part->subtype ? part->subtype : "<none>");
|
||||
color_maybe(MU_COLOR_BLUE);
|
||||
mu_util_print_encoded(" %s/%s ",
|
||||
part->type ? part->type : "<none>",
|
||||
part->subtype ? part->subtype : "<none>");
|
||||
|
||||
/* /\* disposition *\/ */
|
||||
color_maybe (MU_COLOR_MAGENTA);
|
||||
mu_util_print_encoded ("[%s]", disp_str(part->part_type));
|
||||
color_maybe(MU_COLOR_MAGENTA);
|
||||
mu_util_print_encoded("[%s]", disp_str(part->part_type));
|
||||
|
||||
/* size */
|
||||
if (part->size > 0) {
|
||||
color_maybe (MU_COLOR_CYAN);
|
||||
g_print (" (%s)", mu_str_size_s (part->size));
|
||||
color_maybe(MU_COLOR_CYAN);
|
||||
g_print(" (%s)", mu_str_size_s(part->size));
|
||||
}
|
||||
|
||||
color_maybe (MU_COLOR_DEFAULT);
|
||||
fputs ("\n", stdout);
|
||||
color_maybe(MU_COLOR_DEFAULT);
|
||||
fputs("\n", stdout);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
show_parts (const char* path, const MuConfig *opts, GError **err)
|
||||
show_parts(const char* path, const MuConfig* opts, GError** err)
|
||||
{
|
||||
MuMsg *msg;
|
||||
MuMsg* msg;
|
||||
MuMsgOptions msgopts;
|
||||
|
||||
msg = mu_msg_new_from_file (path, NULL, err);
|
||||
msg = mu_msg_new_from_file(path, NULL, err);
|
||||
if (!msg)
|
||||
return FALSE;
|
||||
|
||||
msgopts = mu_config_get_msg_options (opts);
|
||||
msgopts = mu_config_get_msg_options(opts);
|
||||
|
||||
/* TODO: update this for crypto */
|
||||
g_print ("MIME-parts in this message:\n");
|
||||
mu_msg_part_foreach
|
||||
(msg, msgopts,
|
||||
(MuMsgPartForeachFunc)each_part_show,
|
||||
GUINT_TO_POINTER(!opts->nocolor));
|
||||
g_print("MIME-parts in this message:\n");
|
||||
mu_msg_part_foreach(msg,
|
||||
msgopts,
|
||||
(MuMsgPartForeachFunc)each_part_show,
|
||||
GUINT_TO_POINTER(!opts->nocolor));
|
||||
|
||||
mu_msg_unref (msg);
|
||||
mu_msg_unref(msg);
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
check_params (const MuConfig *opts, GError **err)
|
||||
check_params(const MuConfig* opts, GError** err)
|
||||
{
|
||||
size_t param_num;
|
||||
|
||||
param_num = mu_config_param_num (opts);
|
||||
param_num = mu_config_param_num(opts);
|
||||
|
||||
if (param_num < 2) {
|
||||
mu_util_g_set_error
|
||||
(err, MU_ERROR_IN_PARAMETERS,
|
||||
"parameters missing");
|
||||
mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "parameters missing");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (opts->save_attachments || opts->save_all)
|
||||
if (opts->parts || param_num == 3) {
|
||||
mu_util_g_set_error
|
||||
(err, MU_ERROR_IN_PARAMETERS,
|
||||
"--save-attachments and --save-all don't "
|
||||
"accept a filename pattern or --parts");
|
||||
mu_util_g_set_error(err,
|
||||
MU_ERROR_IN_PARAMETERS,
|
||||
"--save-attachments and --save-all don't "
|
||||
"accept a filename pattern or --parts");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (opts->save_attachments && opts->save_all) {
|
||||
mu_util_g_set_error
|
||||
(err, MU_ERROR_IN_PARAMETERS,
|
||||
"only one of --save-attachments and"
|
||||
" --save-all is allowed");
|
||||
mu_util_g_set_error(err,
|
||||
MU_ERROR_IN_PARAMETERS,
|
||||
"only one of --save-attachments and"
|
||||
" --save-all is allowed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -395,32 +381,28 @@ check_params (const MuConfig *opts, GError **err)
|
||||
}
|
||||
|
||||
MuError
|
||||
Mu::mu_cmd_extract (const MuConfig *opts, GError **err)
|
||||
Mu::mu_cmd_extract(const MuConfig* opts, GError** err)
|
||||
{
|
||||
int rv;
|
||||
|
||||
g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_EXTRACT,
|
||||
MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail(opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_EXTRACT, MU_ERROR_INTERNAL);
|
||||
|
||||
if (!check_params (opts, err))
|
||||
if (!check_params(opts, err))
|
||||
return MU_ERROR_IN_PARAMETERS;
|
||||
|
||||
if (!opts->params[2] && !opts->parts &&
|
||||
!opts->save_attachments && !opts->save_all)
|
||||
if (!opts->params[2] && !opts->parts && !opts->save_attachments && !opts->save_all)
|
||||
/* show, don't save */
|
||||
rv = show_parts (opts->params[1], opts, err);
|
||||
rv = show_parts(opts->params[1], opts, err);
|
||||
else {
|
||||
rv = mu_util_check_dir(opts->targetdir, FALSE, TRUE);
|
||||
if (!rv)
|
||||
mu_util_g_set_error
|
||||
(err, MU_ERROR_FILE_CANNOT_WRITE,
|
||||
"target '%s' is not a writable directory",
|
||||
opts->targetdir);
|
||||
mu_util_g_set_error(err,
|
||||
MU_ERROR_FILE_CANNOT_WRITE,
|
||||
"target '%s' is not a writable directory",
|
||||
opts->targetdir);
|
||||
else
|
||||
rv = save_parts (opts->params[1],
|
||||
opts->params[2],
|
||||
opts); /* save */
|
||||
rv = save_parts(opts->params[1], opts->params[2], opts); /* save */
|
||||
}
|
||||
|
||||
return rv ? MU_OK : MU_ERROR;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -42,111 +42,107 @@ using namespace Mu;
|
||||
static std::atomic<bool> CaughtSignal{};
|
||||
|
||||
static void
|
||||
install_sig_handler (void)
|
||||
install_sig_handler(void)
|
||||
{
|
||||
struct sigaction action;
|
||||
int i, sigs[] = { SIGINT, SIGHUP, SIGTERM };
|
||||
int i, sigs[] = {SIGINT, SIGHUP, SIGTERM};
|
||||
|
||||
sigemptyset(&action.sa_mask);
|
||||
action.sa_flags = SA_RESETHAND;
|
||||
action.sa_handler = [](int sig) {
|
||||
if (!CaughtSignal && sig == SIGINT) /* Ctrl-C */
|
||||
g_print ("\nshutting down gracefully, "
|
||||
"press again to kill immediately");
|
||||
CaughtSignal = true;
|
||||
};
|
||||
action.sa_handler = [](int sig) {
|
||||
if (!CaughtSignal && sig == SIGINT) /* Ctrl-C */
|
||||
g_print("\nshutting down gracefully, "
|
||||
"press again to kill immediately");
|
||||
CaughtSignal = true;
|
||||
};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(sigs); ++i)
|
||||
if (sigaction (sigs[i], &action, NULL) != 0)
|
||||
g_critical ("set sigaction for %d failed: %s",
|
||||
sigs[i], g_strerror (errno));;
|
||||
if (sigaction(sigs[i], &action, NULL) != 0)
|
||||
g_critical("set sigaction for %d failed: %s", sigs[i], g_strerror(errno));
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_stats (const Indexer::Progress& stats, bool color)
|
||||
print_stats(const Indexer::Progress& stats, bool color)
|
||||
{
|
||||
const char *kars = "-\\|/";
|
||||
static auto i = 0U;
|
||||
const char* kars = "-\\|/";
|
||||
static auto i = 0U;
|
||||
|
||||
MaybeAnsi col{color};
|
||||
using Color = MaybeAnsi::Color;
|
||||
MaybeAnsi col{color};
|
||||
using Color = MaybeAnsi::Color;
|
||||
|
||||
std::cout << col.fg(Color::Yellow) << kars[++i % 4] << col.reset()
|
||||
<< " indexing messages; "
|
||||
<< "processed: " << col.fg(Color::Green) << stats.processed << col.reset()
|
||||
<< "; updated/new: " << col.fg(Color::Green) << stats.updated << col.reset()
|
||||
<< "; cleaned-up: " << col.fg(Color::Green) << stats.removed << col.reset();
|
||||
std::cout << col.fg(Color::Yellow) << kars[++i % 4] << col.reset() << " indexing messages; "
|
||||
<< "processed: " << col.fg(Color::Green) << stats.processed << col.reset()
|
||||
<< "; updated/new: " << col.fg(Color::Green) << stats.updated << col.reset()
|
||||
<< "; cleaned-up: " << col.fg(Color::Green) << stats.removed << col.reset();
|
||||
}
|
||||
|
||||
|
||||
MuError
|
||||
Mu::mu_cmd_index (Mu::Store& store, const MuConfig *opts, GError **err)
|
||||
Mu::mu_cmd_index(Mu::Store& store, const MuConfig* opts, GError** err)
|
||||
{
|
||||
g_return_val_if_fail (opts, MU_ERROR);
|
||||
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_INDEX, MU_ERROR);
|
||||
g_return_val_if_fail(opts, MU_ERROR);
|
||||
g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_INDEX, MU_ERROR);
|
||||
|
||||
/* param[0] == 'index' there should be no param[1] */
|
||||
/* param[0] == 'index' there should be no param[1] */
|
||||
if (opts->params[1]) {
|
||||
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
|
||||
"unexpected parameter");
|
||||
mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "unexpected parameter");
|
||||
return MU_ERROR;
|
||||
}
|
||||
if (opts->max_msg_size < 0) {
|
||||
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
|
||||
"the maximum message size must be >= 0");
|
||||
mu_util_g_set_error(err,
|
||||
MU_ERROR_IN_PARAMETERS,
|
||||
"the maximum message size must be >= 0");
|
||||
return MU_ERROR;
|
||||
}
|
||||
|
||||
const auto mdir{store.metadata().root_maildir};
|
||||
if (G_UNLIKELY(access (mdir.c_str(), R_OK) != 0)) {
|
||||
mu_util_g_set_error(err, MU_ERROR_FILE,
|
||||
"'%s' is not readable: %s", mdir.c_str(), g_strerror (errno));
|
||||
return MU_ERROR;
|
||||
}
|
||||
const auto mdir{store.metadata().root_maildir};
|
||||
if (G_UNLIKELY(access(mdir.c_str(), R_OK) != 0)) {
|
||||
mu_util_g_set_error(err,
|
||||
MU_ERROR_FILE,
|
||||
"'%s' is not readable: %s",
|
||||
mdir.c_str(),
|
||||
g_strerror(errno));
|
||||
return MU_ERROR;
|
||||
}
|
||||
|
||||
MaybeAnsi col{!opts->nocolor};
|
||||
using Color = MaybeAnsi::Color;
|
||||
if (!opts->quiet) {
|
||||
MaybeAnsi col{!opts->nocolor};
|
||||
using Color = MaybeAnsi::Color;
|
||||
if (!opts->quiet) {
|
||||
if (opts->lazycheck)
|
||||
std::cout << "lazily ";
|
||||
|
||||
if (opts->lazycheck)
|
||||
std::cout << "lazily ";
|
||||
std::cout << "indexing maildir " << col.fg(Color::Green)
|
||||
<< store.metadata().root_maildir << col.reset() << " -> store "
|
||||
<< col.fg(Color::Green) << store.metadata().database_path << col.reset()
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
std::cout << "indexing maildir "
|
||||
<< col.fg(Color::Green) << store.metadata().root_maildir
|
||||
<< col.reset()
|
||||
<< " -> store "
|
||||
<< col.fg(Color::Green) << store.metadata().database_path
|
||||
<< col.reset()
|
||||
<< std::endl;
|
||||
}
|
||||
Mu::Indexer::Config conf{};
|
||||
conf.cleanup = !opts->nocleanup;
|
||||
conf.lazy_check = opts->lazycheck;
|
||||
|
||||
Mu::Indexer::Config conf{};
|
||||
conf.cleanup = !opts->nocleanup;
|
||||
conf.lazy_check = opts->lazycheck;
|
||||
install_sig_handler();
|
||||
|
||||
install_sig_handler ();
|
||||
auto& indexer{store.indexer()};
|
||||
indexer.start(conf);
|
||||
while (!CaughtSignal && indexer.is_running()) {
|
||||
if (!opts->quiet)
|
||||
print_stats(indexer.progress(), !opts->nocolor);
|
||||
|
||||
auto& indexer{store.indexer()};
|
||||
indexer.start(conf);
|
||||
while (!CaughtSignal && indexer.is_running()) {
|
||||
if (!opts->quiet)
|
||||
print_stats (indexer.progress(), !opts->nocolor);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
||||
if (!opts->quiet) {
|
||||
std::cout << "\r";
|
||||
std::cout.flush();
|
||||
}
|
||||
}
|
||||
|
||||
if (!opts->quiet) {
|
||||
std::cout << "\r";
|
||||
std::cout.flush();
|
||||
}
|
||||
}
|
||||
store.indexer().stop();
|
||||
|
||||
store.indexer().stop();
|
||||
if (!opts->quiet) {
|
||||
print_stats(store.indexer().progress(), !opts->nocolor);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
if (!opts->quiet) {
|
||||
print_stats (store.indexer().progress(), !opts->nocolor);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
return MU_OK;
|
||||
return MU_OK;
|
||||
}
|
||||
|
||||
@ -31,97 +31,100 @@
|
||||
#include "mu-script.hh"
|
||||
#include "mu-runtime.hh"
|
||||
|
||||
|
||||
#include "utils/mu-util.h"
|
||||
#include "utils/mu-str.h"
|
||||
|
||||
|
||||
#define MU_GUILE_EXT ".scm"
|
||||
#define MU_GUILE_DESCR_PREFIX ";; INFO: "
|
||||
|
||||
#define COL(C) ((color)?C:"")
|
||||
#define COL(C) ((color) ? C : "")
|
||||
|
||||
using namespace Mu;
|
||||
|
||||
static void
|
||||
print_script (const char *name, const char *oneline, const char *descr,
|
||||
gboolean color, gboolean verbose)
|
||||
print_script(const char* name,
|
||||
const char* oneline,
|
||||
const char* descr,
|
||||
gboolean color,
|
||||
gboolean verbose)
|
||||
{
|
||||
g_print ("%s%s%s%s%s%s%s%s",
|
||||
verbose ? "\n" : " * ",
|
||||
COL(MU_COLOR_GREEN),name,COL(MU_COLOR_DEFAULT),
|
||||
oneline ? ": " : "",
|
||||
COL(MU_COLOR_BLUE),oneline ? oneline :"",MU_COLOR_DEFAULT);
|
||||
g_print("%s%s%s%s%s%s%s%s",
|
||||
verbose ? "\n" : " * ",
|
||||
COL(MU_COLOR_GREEN),
|
||||
name,
|
||||
COL(MU_COLOR_DEFAULT),
|
||||
oneline ? ": " : "",
|
||||
COL(MU_COLOR_BLUE),
|
||||
oneline ? oneline : "",
|
||||
MU_COLOR_DEFAULT);
|
||||
|
||||
if (verbose && descr)
|
||||
g_print ("%s%s%s",
|
||||
COL(MU_COLOR_MAGENTA),descr,COL(MU_COLOR_DEFAULT));
|
||||
g_print("%s%s%s", COL(MU_COLOR_MAGENTA), descr, COL(MU_COLOR_DEFAULT));
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
print_scripts (GSList *scripts, gboolean color,
|
||||
gboolean verbose, const char *rxstr, GError **err)
|
||||
print_scripts(GSList* scripts, gboolean color, gboolean verbose, const char* rxstr, GError** err)
|
||||
{
|
||||
GSList *cur;
|
||||
const char *verb;
|
||||
GSList* cur;
|
||||
const char* verb;
|
||||
|
||||
if (!scripts) {
|
||||
g_print ("No scripts available\n");
|
||||
g_print("No scripts available\n");
|
||||
return TRUE; /* not an error */
|
||||
}
|
||||
|
||||
verb = verbose ? "" : " (use --verbose for details)";
|
||||
|
||||
if (rxstr)
|
||||
g_print ("Available scripts matching '%s'%s:\n",
|
||||
rxstr, verb);
|
||||
g_print("Available scripts matching '%s'%s:\n", rxstr, verb);
|
||||
else
|
||||
g_print ("Available scripts%s:\n", verb);
|
||||
g_print("Available scripts%s:\n", verb);
|
||||
|
||||
for (cur = scripts; cur; cur = g_slist_next (cur)) {
|
||||
|
||||
MuScriptInfo *msi;
|
||||
const char* descr, *oneline, *name;
|
||||
for (cur = scripts; cur; cur = g_slist_next(cur)) {
|
||||
MuScriptInfo* msi;
|
||||
const char * descr, *oneline, *name;
|
||||
|
||||
msi = (MuScriptInfo*)cur->data;
|
||||
name = mu_script_info_name (msi);
|
||||
oneline = mu_script_info_one_line (msi);
|
||||
descr = mu_script_info_description (msi);
|
||||
name = mu_script_info_name(msi);
|
||||
oneline = mu_script_info_one_line(msi);
|
||||
descr = mu_script_info_description(msi);
|
||||
|
||||
/* if rxstr is provide, only consider matching scriptinfos */
|
||||
if (rxstr && !mu_script_info_matches_regex (msi, rxstr, err)) {
|
||||
if (rxstr && !mu_script_info_matches_regex(msi, rxstr, err)) {
|
||||
if (err && *err)
|
||||
return FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
print_script (name, oneline, descr, color, verbose);
|
||||
print_script(name, oneline, descr, color, verbose);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static char*
|
||||
get_userpath (const char *muhome)
|
||||
get_userpath(const char* muhome)
|
||||
{
|
||||
if (muhome)
|
||||
return g_build_path (G_DIR_SEPARATOR_S, muhome, "scripts", NULL);
|
||||
return g_build_path(G_DIR_SEPARATOR_S, muhome, "scripts", NULL);
|
||||
else
|
||||
return g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir(),
|
||||
"mu", "scripts", NULL);
|
||||
return g_build_path(G_DIR_SEPARATOR_S,
|
||||
g_get_user_data_dir(),
|
||||
"mu",
|
||||
"scripts",
|
||||
NULL);
|
||||
}
|
||||
|
||||
static GSList*
|
||||
get_script_info_list (const char *muhome, GError **err)
|
||||
get_script_info_list(const char* muhome, GError** err)
|
||||
{
|
||||
GSList *scripts, *userscripts, *last;
|
||||
char *userpath;
|
||||
char* userpath;
|
||||
|
||||
scripts = mu_script_get_script_info_list
|
||||
(MU_SCRIPTS_DIR, MU_GUILE_EXT,
|
||||
MU_GUILE_DESCR_PREFIX,
|
||||
err);
|
||||
scripts = mu_script_get_script_info_list(MU_SCRIPTS_DIR,
|
||||
MU_GUILE_EXT,
|
||||
MU_GUILE_DESCR_PREFIX,
|
||||
err);
|
||||
|
||||
if (err && *err)
|
||||
return NULL;
|
||||
@ -129,26 +132,25 @@ get_script_info_list (const char *muhome, GError **err)
|
||||
userpath = get_userpath(muhome);
|
||||
|
||||
/* is there are userdir for scripts? */
|
||||
if (!mu_util_check_dir (userpath, TRUE, FALSE)) {
|
||||
g_free (userpath);
|
||||
if (!mu_util_check_dir(userpath, TRUE, FALSE)) {
|
||||
g_free(userpath);
|
||||
return scripts;
|
||||
}
|
||||
|
||||
/* append it to the list we already have */
|
||||
userscripts = mu_script_get_script_info_list (userpath, MU_GUILE_EXT,
|
||||
MU_GUILE_DESCR_PREFIX,
|
||||
err);
|
||||
g_free (userpath);
|
||||
userscripts =
|
||||
mu_script_get_script_info_list(userpath, MU_GUILE_EXT, MU_GUILE_DESCR_PREFIX, err);
|
||||
g_free(userpath);
|
||||
|
||||
/* some error, return nothing */
|
||||
if (err && *err) {
|
||||
mu_script_info_list_destroy (userscripts);
|
||||
mu_script_info_list_destroy (scripts);
|
||||
mu_script_info_list_destroy(userscripts);
|
||||
mu_script_info_list_destroy(scripts);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* append the user scripts */
|
||||
last = g_slist_last (scripts);
|
||||
last = g_slist_last(scripts);
|
||||
if (last) {
|
||||
last->next = userscripts;
|
||||
return scripts;
|
||||
@ -156,57 +158,51 @@ get_script_info_list (const char *muhome, GError **err)
|
||||
return userscripts; /* apparently, scripts was NULL */
|
||||
}
|
||||
|
||||
|
||||
|
||||
static gboolean
|
||||
check_params (const 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,
|
||||
"the 'script' command is not available "
|
||||
"in this version of mu");
|
||||
if (!mu_util_supports(MU_FEATURE_GUILE)) {
|
||||
mu_util_g_set_error(err,
|
||||
MU_ERROR_IN_PARAMETERS,
|
||||
"the 'script' command is not available "
|
||||
"in this version of mu");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
MuError
|
||||
Mu::mu_cmd_script (const MuConfig *opts, GError **err)
|
||||
Mu::mu_cmd_script(const MuConfig* opts, GError** err)
|
||||
{
|
||||
MuScriptInfo *msi;
|
||||
GSList *scripts;
|
||||
MuScriptInfo* msi;
|
||||
GSList* scripts;
|
||||
|
||||
g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_SCRIPT,
|
||||
MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail(opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_SCRIPT, MU_ERROR_INTERNAL);
|
||||
|
||||
if (!check_params (opts, err))
|
||||
if (!check_params(opts, err))
|
||||
return MU_ERROR;
|
||||
|
||||
scripts = get_script_info_list (opts->muhome, err);
|
||||
scripts = get_script_info_list(opts->muhome, err);
|
||||
if (err && *err)
|
||||
goto leave;
|
||||
|
||||
if (g_strcmp0 (opts->cmdstr, "script") == 0) {
|
||||
print_scripts (scripts, !opts->nocolor, opts->verbose,
|
||||
opts->script_params[0], err);
|
||||
if (g_strcmp0(opts->cmdstr, "script") == 0) {
|
||||
print_scripts(scripts, !opts->nocolor, opts->verbose, opts->script_params[0], err);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
msi = mu_script_find_script_with_name (scripts, opts->script);
|
||||
msi = mu_script_find_script_with_name(scripts, opts->script);
|
||||
if (!msi) {
|
||||
mu_util_g_set_error (err, MU_ERROR_SCRIPT_NOT_FOUND,
|
||||
"command or script not found");
|
||||
mu_util_g_set_error(err, MU_ERROR_SCRIPT_NOT_FOUND, "command or script not found");
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* do it! */
|
||||
mu_script_guile_run (msi, mu_runtime_path(MU_RUNTIME_PATH_CACHE),
|
||||
opts->script_params, err);
|
||||
mu_script_guile_run(msi, mu_runtime_path(MU_RUNTIME_PATH_CACHE), opts->script_params, err);
|
||||
leave:
|
||||
/* this won't be reached, unless there is some error */
|
||||
mu_script_info_list_destroy (scripts);
|
||||
mu_script_info_list_destroy(scripts);
|
||||
return (err && *err) ? MU_ERROR : MU_OK;
|
||||
}
|
||||
|
||||
@ -30,31 +30,30 @@
|
||||
#include "mu-cmd.hh"
|
||||
#include "mu-server.hh"
|
||||
|
||||
|
||||
#include "utils/mu-utils.hh"
|
||||
#include "utils/mu-command-parser.hh"
|
||||
#include "utils/mu-readline.hh"
|
||||
|
||||
using namespace Mu;
|
||||
static std::atomic<bool> MuTerminate{false};
|
||||
static bool tty;
|
||||
static bool tty;
|
||||
|
||||
static void
|
||||
install_sig_handler (void)
|
||||
install_sig_handler(void)
|
||||
{
|
||||
struct sigaction action;
|
||||
int i, sigs[] = { SIGINT, SIGHUP, SIGTERM, SIGPIPE };
|
||||
struct sigaction action;
|
||||
int i, sigs[] = {SIGINT, SIGHUP, SIGTERM, SIGPIPE};
|
||||
|
||||
MuTerminate = false;
|
||||
MuTerminate = false;
|
||||
|
||||
action.sa_handler = [](int sig){ MuTerminate = true; };
|
||||
sigemptyset(&action.sa_mask);
|
||||
action.sa_flags = SA_RESETHAND;
|
||||
action.sa_handler = [](int sig) { MuTerminate = true; };
|
||||
sigemptyset(&action.sa_mask);
|
||||
action.sa_flags = SA_RESETHAND;
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(sigs); ++i)
|
||||
if (sigaction (sigs[i], &action, NULL) != 0)
|
||||
g_critical ("set sigaction for %d failed: %s",
|
||||
sigs[i], g_strerror (errno));;
|
||||
for (i = 0; i != G_N_ELEMENTS(sigs); ++i)
|
||||
if (sigaction(sigs[i], &action, NULL) != 0)
|
||||
g_critical("set sigaction for %d failed: %s", sigs[i], g_strerror(errno));
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -68,85 +67,86 @@ install_sig_handler (void)
|
||||
static void
|
||||
cookie(size_t n)
|
||||
{
|
||||
const auto num{static_cast<unsigned>(n)};
|
||||
const auto num{static_cast<unsigned>(n)};
|
||||
|
||||
if (tty) // for testing.
|
||||
::printf ("[%x]", num);
|
||||
else
|
||||
::printf (COOKIE_PRE "%x" COOKIE_POST, num);
|
||||
if (tty) // for testing.
|
||||
::printf("[%x]", num);
|
||||
else
|
||||
::printf(COOKIE_PRE "%x" COOKIE_POST, num);
|
||||
}
|
||||
|
||||
static void
|
||||
output_sexp_stdout (Sexp&& sexp)
|
||||
output_sexp_stdout(Sexp&& sexp)
|
||||
{
|
||||
const auto str{sexp.to_sexp_string()};
|
||||
cookie(str.size() + 1);
|
||||
if (G_UNLIKELY(::puts(str.c_str()) < 0)) {
|
||||
g_critical ("failed to write output '%s'", str.c_str());
|
||||
::raise (SIGTERM); /* terminate ourselves */
|
||||
}
|
||||
const auto str{sexp.to_sexp_string()};
|
||||
cookie(str.size() + 1);
|
||||
if (G_UNLIKELY(::puts(str.c_str()) < 0)) {
|
||||
g_critical("failed to write output '%s'", str.c_str());
|
||||
::raise(SIGTERM); /* terminate ourselves */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
report_error(const Mu::Error& err) noexcept
|
||||
{
|
||||
Sexp::List e;
|
||||
Sexp::List e;
|
||||
|
||||
e.add_prop(":error", Sexp::make_number(static_cast<size_t>(err.code())));
|
||||
e.add_prop(":message", Sexp::make_string(err.what()));
|
||||
e.add_prop(":error", Sexp::make_number(static_cast<size_t>(err.code())));
|
||||
e.add_prop(":message", Sexp::make_string(err.what()));
|
||||
|
||||
output_sexp_stdout(Sexp::make_list(std::move(e)));
|
||||
output_sexp_stdout(Sexp::make_list(std::move(e)));
|
||||
}
|
||||
|
||||
MuError
|
||||
Mu::mu_cmd_server (const MuConfig *opts, GError **err) try {
|
||||
Mu::mu_cmd_server(const MuConfig* opts, GError** err)
|
||||
try {
|
||||
Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), false /*writable*/};
|
||||
Server server{store, output_sexp_stdout};
|
||||
|
||||
Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), false/*writable*/};
|
||||
Server server{store, output_sexp_stdout};
|
||||
g_message("created server with store @ %s; maildir @ %s; debug-mode %s",
|
||||
store.metadata().database_path.c_str(),
|
||||
store.metadata().root_maildir.c_str(),
|
||||
opts->debug ? "yes" : "no");
|
||||
|
||||
g_message ("created server with store @ %s; maildir @ %s; debug-mode %s",
|
||||
store.metadata().database_path.c_str(),
|
||||
store.metadata().root_maildir.c_str(),
|
||||
opts->debug ? "yes" : "no");
|
||||
tty = ::isatty(::fileno(stdout));
|
||||
|
||||
tty = ::isatty(::fileno(stdout));
|
||||
const auto eval = std::string{opts->commands ? "(help :full t)"
|
||||
: opts->eval ? opts->eval
|
||||
: ""};
|
||||
if (!eval.empty()) {
|
||||
server.invoke(eval);
|
||||
return MU_OK;
|
||||
}
|
||||
|
||||
const auto eval = std::string {
|
||||
opts->commands ? "(help :full t)" : opts->eval ? opts->eval : ""};
|
||||
if (!eval.empty()) {
|
||||
server.invoke(eval);
|
||||
return MU_OK;
|
||||
}
|
||||
// Note, the readline stuff is inactive unless on a tty.
|
||||
const auto histpath{std::string{mu_runtime_path(MU_RUNTIME_PATH_CACHE)} + "/history"};
|
||||
setup_readline(histpath, 50);
|
||||
|
||||
// Note, the readline stuff is inactive unless on a tty.
|
||||
const auto histpath{std::string{mu_runtime_path(MU_RUNTIME_PATH_CACHE)} + "/history"};
|
||||
setup_readline(histpath, 50);
|
||||
install_sig_handler();
|
||||
std::cout << ";; Welcome to the " << PACKAGE_STRING << " command-server\n"
|
||||
<< ";; Use (help) to get a list of commands, (quit) to quit.\n";
|
||||
|
||||
install_sig_handler();
|
||||
std::cout << ";; Welcome to the " << PACKAGE_STRING << " command-server\n"
|
||||
<< ";; Use (help) to get a list of commands, (quit) to quit.\n";
|
||||
bool do_quit{};
|
||||
while (!MuTerminate && !do_quit) {
|
||||
std::fflush(stdout); // Needed for Windows, see issue #1827.
|
||||
const auto line{read_line(do_quit)};
|
||||
if (line.find_first_not_of(" \t") == std::string::npos)
|
||||
continue; // skip whitespace-only lines
|
||||
|
||||
bool do_quit{};
|
||||
while (!MuTerminate && !do_quit) {
|
||||
std::fflush(stdout); // Needed for Windows, see issue #1827.
|
||||
const auto line{read_line(do_quit)};
|
||||
if (line.find_first_not_of(" \t") == std::string::npos)
|
||||
continue; // skip whitespace-only lines
|
||||
do_quit = server.invoke(line) ? false : true;
|
||||
save_line(line);
|
||||
}
|
||||
shutdown_readline();
|
||||
|
||||
do_quit = server.invoke(line) ? false : true;
|
||||
save_line(line);
|
||||
}
|
||||
shutdown_readline();
|
||||
|
||||
return MU_OK;
|
||||
return MU_OK;
|
||||
|
||||
} catch (const Error& er) {
|
||||
/* note: user-level error, "OK" for mu */
|
||||
report_error(er);
|
||||
g_warning ("server caught exception: %s", er.what());
|
||||
return MU_OK;
|
||||
/* note: user-level error, "OK" for mu */
|
||||
report_error(er);
|
||||
g_warning("server caught exception: %s", er.what());
|
||||
return MU_OK;
|
||||
} catch (...) {
|
||||
g_critical ("server caught exception");
|
||||
g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", "caught exception");
|
||||
return MU_ERROR;
|
||||
g_critical("server caught exception");
|
||||
g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", "caught exception");
|
||||
return MU_ERROR;
|
||||
}
|
||||
|
||||
639
mu/mu-cmd.cc
639
mu/mu-cmd.cc
@ -28,7 +28,6 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#include "mu-msg.hh"
|
||||
#include "mu-msg-part.hh"
|
||||
#include "mu-cmd.hh"
|
||||
@ -48,223 +47,205 @@
|
||||
using namespace Mu;
|
||||
|
||||
static gboolean
|
||||
view_msg_sexp (MuMsg *msg, const MuConfig *opts)
|
||||
view_msg_sexp(MuMsg* msg, const MuConfig* opts)
|
||||
{
|
||||
::fputs(msg_to_sexp(msg,0, mu_config_get_msg_options(opts))
|
||||
.to_sexp_string(). c_str(), stdout);
|
||||
::fputs(msg_to_sexp(msg, 0, mu_config_get_msg_options(opts)).to_sexp_string().c_str(),
|
||||
stdout);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
each_part (MuMsg *msg, MuMsgPart *part, gchar **attach)
|
||||
each_part(MuMsg* msg, MuMsgPart* part, gchar** attach)
|
||||
{
|
||||
char *fname, *tmp;
|
||||
|
||||
if (!mu_msg_part_maybe_attachment (part))
|
||||
if (!mu_msg_part_maybe_attachment(part))
|
||||
return;
|
||||
|
||||
fname = mu_msg_part_get_filename (part, FALSE);
|
||||
fname = mu_msg_part_get_filename(part, FALSE);
|
||||
if (!fname)
|
||||
return;
|
||||
|
||||
tmp = *attach;
|
||||
*attach = g_strdup_printf ("%s%s'%s'",
|
||||
*attach ? *attach : "",
|
||||
*attach ? ", " : "",
|
||||
fname);
|
||||
g_free (tmp);
|
||||
tmp = *attach;
|
||||
*attach = g_strdup_printf("%s%s'%s'", *attach ? *attach : "", *attach ? ", " : "", fname);
|
||||
g_free(tmp);
|
||||
}
|
||||
|
||||
/* return comma-sep'd list of attachments */
|
||||
static gchar *
|
||||
get_attach_str (MuMsg *msg, const MuConfig *opts)
|
||||
static gchar*
|
||||
get_attach_str(MuMsg* msg, const MuConfig* opts)
|
||||
{
|
||||
gchar *attach;
|
||||
gchar* attach;
|
||||
|
||||
const auto msgopts = (MuMsgOptions)
|
||||
(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,
|
||||
(MuMsgPartForeachFunc)each_part, &attach);
|
||||
mu_msg_part_foreach(msg, msgopts, (MuMsgPartForeachFunc)each_part, &attach);
|
||||
return attach;
|
||||
}
|
||||
|
||||
#define color_maybe(C) do { if(color) fputs ((C),stdout);} while(0)
|
||||
#define color_maybe(C) \
|
||||
do { \
|
||||
if (color) \
|
||||
fputs((C), stdout); \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
print_field (const char* field, const char *val, gboolean color)
|
||||
print_field(const char* field, const char* val, gboolean color)
|
||||
{
|
||||
if (!val)
|
||||
return;
|
||||
|
||||
color_maybe (MU_COLOR_MAGENTA);
|
||||
mu_util_fputs_encoded (field, stdout);
|
||||
color_maybe (MU_COLOR_DEFAULT);
|
||||
fputs (": ", stdout);
|
||||
color_maybe(MU_COLOR_MAGENTA);
|
||||
mu_util_fputs_encoded(field, stdout);
|
||||
color_maybe(MU_COLOR_DEFAULT);
|
||||
fputs(": ", stdout);
|
||||
|
||||
if (val) {
|
||||
color_maybe (MU_COLOR_GREEN);
|
||||
mu_util_fputs_encoded (val, stdout);
|
||||
color_maybe(MU_COLOR_GREEN);
|
||||
mu_util_fputs_encoded(val, stdout);
|
||||
}
|
||||
|
||||
color_maybe (MU_COLOR_DEFAULT);
|
||||
fputs ("\n", stdout);
|
||||
color_maybe(MU_COLOR_DEFAULT);
|
||||
fputs("\n", stdout);
|
||||
}
|
||||
|
||||
|
||||
/* a summary_len of 0 mean 'don't show summary, show body */
|
||||
static void
|
||||
body_or_summary (MuMsg *msg, const MuConfig *opts)
|
||||
body_or_summary(MuMsg* msg, const MuConfig* opts)
|
||||
{
|
||||
const char *body;
|
||||
const char* body;
|
||||
gboolean color;
|
||||
int my_opts = mu_config_get_msg_options(opts) |
|
||||
MU_MSG_OPTION_CONSOLE_PASSWORD;
|
||||
int my_opts = mu_config_get_msg_options(opts) | MU_MSG_OPTION_CONSOLE_PASSWORD;
|
||||
|
||||
color = !opts->nocolor;
|
||||
body = mu_msg_get_body_text (msg, (MuMsgOptions)my_opts);
|
||||
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);
|
||||
g_print ("[No body found; "
|
||||
"message has encrypted parts]\n");
|
||||
if (mu_msg_get_flags(msg) & MU_FLAG_ENCRYPTED) {
|
||||
color_maybe(MU_COLOR_CYAN);
|
||||
g_print("[No body found; "
|
||||
"message has encrypted parts]\n");
|
||||
} else {
|
||||
color_maybe (MU_COLOR_MAGENTA);
|
||||
g_print ("[No body found]\n");
|
||||
color_maybe(MU_COLOR_MAGENTA);
|
||||
g_print("[No body found]\n");
|
||||
}
|
||||
color_maybe (MU_COLOR_DEFAULT);
|
||||
color_maybe(MU_COLOR_DEFAULT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (opts->summary_len != 0) {
|
||||
gchar *summ;
|
||||
summ = mu_str_summarize (body, opts->summary_len);
|
||||
print_field ("Summary", summ, color);
|
||||
g_free (summ);
|
||||
gchar* summ;
|
||||
summ = mu_str_summarize(body, opts->summary_len);
|
||||
print_field("Summary", summ, color);
|
||||
g_free(summ);
|
||||
} else {
|
||||
mu_util_print_encoded ("%s", body);
|
||||
if (!g_str_has_suffix (body, "\n"))
|
||||
g_print ("\n");
|
||||
mu_util_print_encoded("%s", body);
|
||||
if (!g_str_has_suffix(body, "\n"))
|
||||
g_print("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* we ignore fields for now */
|
||||
/* summary_len == 0 means "no summary */
|
||||
static gboolean
|
||||
view_msg_plain (MuMsg *msg, const MuConfig *opts)
|
||||
view_msg_plain(MuMsg* msg, const MuConfig* opts)
|
||||
{
|
||||
gchar *attachs;
|
||||
time_t date;
|
||||
const GSList *lst;
|
||||
gboolean color;
|
||||
gchar* attachs;
|
||||
time_t date;
|
||||
const GSList* lst;
|
||||
gboolean color;
|
||||
|
||||
color = !opts->nocolor;
|
||||
|
||||
print_field ("From", mu_msg_get_from (msg), color);
|
||||
print_field ("To", mu_msg_get_to (msg), color);
|
||||
print_field ("Cc", mu_msg_get_cc (msg), color);
|
||||
print_field ("Bcc", mu_msg_get_bcc (msg), color);
|
||||
print_field ("Subject", mu_msg_get_subject (msg), color);
|
||||
print_field("From", mu_msg_get_from(msg), color);
|
||||
print_field("To", mu_msg_get_to(msg), color);
|
||||
print_field("Cc", mu_msg_get_cc(msg), color);
|
||||
print_field("Bcc", mu_msg_get_bcc(msg), color);
|
||||
print_field("Subject", mu_msg_get_subject(msg), color);
|
||||
|
||||
if ((date = mu_msg_get_date (msg)))
|
||||
print_field ("Date", mu_date_str_s ("%c", date),
|
||||
color);
|
||||
if ((date = mu_msg_get_date(msg)))
|
||||
print_field("Date", mu_date_str_s("%c", date), color);
|
||||
|
||||
if ((lst = mu_msg_get_tags (msg))) {
|
||||
gchar *tags;
|
||||
tags = mu_str_from_list (lst,',');
|
||||
print_field ("Tags", tags, color);
|
||||
g_free (tags);
|
||||
if ((lst = mu_msg_get_tags(msg))) {
|
||||
gchar* tags;
|
||||
tags = mu_str_from_list(lst, ',');
|
||||
print_field("Tags", tags, color);
|
||||
g_free(tags);
|
||||
}
|
||||
|
||||
if ((attachs = get_attach_str (msg, opts))) {
|
||||
print_field ("Attachments", attachs, color);
|
||||
g_free (attachs);
|
||||
if ((attachs = get_attach_str(msg, opts))) {
|
||||
print_field("Attachments", attachs, color);
|
||||
g_free(attachs);
|
||||
}
|
||||
|
||||
body_or_summary (msg, opts);
|
||||
body_or_summary(msg, opts);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
handle_msg (const char *fname, const MuConfig *opts, GError **err)
|
||||
handle_msg(const char* fname, const MuConfig* opts, GError** err)
|
||||
{
|
||||
MuMsg *msg;
|
||||
MuMsg* msg;
|
||||
gboolean rv;
|
||||
|
||||
msg = mu_msg_new_from_file (fname, NULL, err);
|
||||
msg = mu_msg_new_from_file(fname, NULL, err);
|
||||
if (!msg)
|
||||
return FALSE;
|
||||
|
||||
switch (opts->format) {
|
||||
case MU_CONFIG_FORMAT_PLAIN:
|
||||
rv = view_msg_plain (msg, opts);
|
||||
break;
|
||||
case MU_CONFIG_FORMAT_SEXP:
|
||||
rv = view_msg_sexp (msg, opts);
|
||||
break;
|
||||
default:
|
||||
g_critical ("bug: should not be reached");
|
||||
rv = FALSE;
|
||||
case MU_CONFIG_FORMAT_PLAIN: rv = view_msg_plain(msg, opts); break;
|
||||
case MU_CONFIG_FORMAT_SEXP: rv = view_msg_sexp(msg, opts); break;
|
||||
default: g_critical("bug: should not be reached"); rv = FALSE;
|
||||
}
|
||||
|
||||
mu_msg_unref (msg);
|
||||
mu_msg_unref(msg);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
view_params_valid (const 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]) {
|
||||
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
|
||||
"error in parameters");
|
||||
mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "error in parameters");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (opts->format) {
|
||||
case MU_CONFIG_FORMAT_PLAIN:
|
||||
case MU_CONFIG_FORMAT_SEXP:
|
||||
break;
|
||||
case MU_CONFIG_FORMAT_SEXP: break;
|
||||
default:
|
||||
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
|
||||
"invalid output format");
|
||||
mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "invalid output format");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static MuError
|
||||
cmd_view (const MuConfig *opts, GError **err)
|
||||
cmd_view(const MuConfig* opts, GError** err)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
gboolean rv;
|
||||
|
||||
g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_VIEW,
|
||||
MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail(opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_VIEW, MU_ERROR_INTERNAL);
|
||||
|
||||
rv = view_params_valid (opts, err);
|
||||
rv = view_params_valid(opts, err);
|
||||
if (!rv)
|
||||
goto leave;
|
||||
|
||||
for (i = 1; opts->params[i]; ++i) {
|
||||
|
||||
rv = handle_msg (opts->params[i], opts, err);
|
||||
rv = handle_msg(opts->params[i], opts, err);
|
||||
if (!rv)
|
||||
break;
|
||||
|
||||
/* add a separator between two messages? */
|
||||
if (opts->terminator)
|
||||
g_print ("%c", VIEW_TERMINATOR);
|
||||
g_print("%c", VIEW_TERMINATOR);
|
||||
}
|
||||
|
||||
leave:
|
||||
@ -275,189 +256,173 @@ leave:
|
||||
}
|
||||
|
||||
static MuError
|
||||
cmd_mkdir (const MuConfig *opts, GError **err)
|
||||
cmd_mkdir(const MuConfig* opts, GError** err)
|
||||
{
|
||||
int i;
|
||||
|
||||
g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_MKDIR,
|
||||
MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail(opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_MKDIR, MU_ERROR_INTERNAL);
|
||||
|
||||
if (!opts->params[1]) {
|
||||
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
|
||||
"missing directory parameter");
|
||||
mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "missing directory parameter");
|
||||
return MU_ERROR_IN_PARAMETERS;
|
||||
}
|
||||
|
||||
for (i = 1; opts->params[i]; ++i)
|
||||
if (!mu_maildir_mkdir (opts->params[i], opts->dirmode,
|
||||
FALSE, err))
|
||||
return err && *err ? (MuError)(*err)->code :
|
||||
MU_ERROR_FILE_CANNOT_MKDIR;
|
||||
if (!mu_maildir_mkdir(opts->params[i], opts->dirmode, FALSE, err))
|
||||
return err && *err ? (MuError)(*err)->code : MU_ERROR_FILE_CANNOT_MKDIR;
|
||||
return MU_OK;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
check_file_okay (const char *path, gboolean cmd_add)
|
||||
check_file_okay(const char* path, gboolean cmd_add)
|
||||
{
|
||||
if (!g_path_is_absolute (path)) {
|
||||
g_printerr ("path is not absolute: %s\n", path);
|
||||
if (!g_path_is_absolute(path)) {
|
||||
g_printerr("path is not absolute: %s\n", path);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (cmd_add && access(path, R_OK) != 0) {
|
||||
g_printerr ("path is not readable: %s: %s\n",
|
||||
path, g_strerror (errno));
|
||||
g_printerr("path is not readable: %s: %s\n", path, g_strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef bool (*ForeachMsgFunc) (Mu::Store& store, const char *path, GError **err);
|
||||
typedef bool (*ForeachMsgFunc)(Mu::Store& store, const char* path, GError** err);
|
||||
|
||||
static MuError
|
||||
foreach_msg_file (Mu::Store& store, const MuConfig *opts,
|
||||
ForeachMsgFunc foreach_func, GError **err)
|
||||
foreach_msg_file(Mu::Store& store, const MuConfig* opts, ForeachMsgFunc foreach_func, GError** err)
|
||||
{
|
||||
unsigned u;
|
||||
gboolean all_ok;
|
||||
unsigned u;
|
||||
gboolean all_ok;
|
||||
|
||||
/* note: params[0] will be 'add' */
|
||||
if (!opts->params[0] || !opts->params[1]) {
|
||||
g_print ("usage: mu %s <file> [<files>]\n",
|
||||
opts->params[0] ? opts->params[0] : "<cmd>");
|
||||
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
|
||||
"missing parameters");
|
||||
g_print("usage: mu %s <file> [<files>]\n",
|
||||
opts->params[0] ? opts->params[0] : "<cmd>");
|
||||
mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "missing parameters");
|
||||
return MU_ERROR_IN_PARAMETERS;
|
||||
}
|
||||
|
||||
for (u = 1, all_ok = TRUE; opts->params[u]; ++u) {
|
||||
|
||||
const char* path;
|
||||
|
||||
path = opts->params[u];
|
||||
|
||||
if (!check_file_okay (path, TRUE)) {
|
||||
if (!check_file_okay(path, TRUE)) {
|
||||
all_ok = FALSE;
|
||||
g_printerr ("not a valid message file: %s\n", path);
|
||||
g_printerr("not a valid message file: %s\n", path);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!foreach_func (store, path, err)) {
|
||||
if (!foreach_func(store, path, err)) {
|
||||
all_ok = FALSE;
|
||||
g_printerr ("error with %s: %s\n", path,
|
||||
(err&&*err) ? (*err)->message :
|
||||
"something went wrong");
|
||||
g_clear_error (err);
|
||||
g_printerr("error with %s: %s\n",
|
||||
path,
|
||||
(err && *err) ? (*err)->message : "something went wrong");
|
||||
g_clear_error(err);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!all_ok) {
|
||||
mu_util_g_set_error (err, MU_ERROR_XAPIAN_STORE_FAILED,
|
||||
"%s failed for some message(s)",
|
||||
opts->params[0]);
|
||||
mu_util_g_set_error(err,
|
||||
MU_ERROR_XAPIAN_STORE_FAILED,
|
||||
"%s failed for some message(s)",
|
||||
opts->params[0]);
|
||||
return MU_ERROR_XAPIAN_STORE_FAILED;
|
||||
}
|
||||
|
||||
return MU_OK;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
add_path_func (Mu::Store& store, const char *path, GError **err)
|
||||
add_path_func(Mu::Store& store, const char* path, GError** err)
|
||||
{
|
||||
const auto docid = store.add_message (path);
|
||||
g_debug ("added message @ %s, docid=%u", path, docid);
|
||||
const auto docid = store.add_message(path);
|
||||
g_debug("added message @ %s, docid=%u", path, docid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static MuError
|
||||
cmd_add (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_ADD,
|
||||
MU_ERROR_INTERNAL);
|
||||
|
||||
return foreach_msg_file (store, opts, add_path_func, err);
|
||||
}
|
||||
|
||||
static bool
|
||||
remove_path_func (Mu::Store& store, const char *path, GError **err)
|
||||
{
|
||||
const auto res = store.remove_message (path);
|
||||
g_debug ("removed %s (%s)", path, res ? "yes" : "no");
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static MuError
|
||||
cmd_remove (Mu::Store& store, const MuConfig *opts, GError **err)
|
||||
cmd_add(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,
|
||||
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);
|
||||
|
||||
return foreach_msg_file (store, opts, remove_path_func, err);
|
||||
return foreach_msg_file(store, opts, add_path_func, err);
|
||||
}
|
||||
|
||||
static bool
|
||||
tickle_func (Mu::Store& store, const char *path, GError **err)
|
||||
remove_path_func(Mu::Store& store, const char* path, GError** err)
|
||||
{
|
||||
MuMsg *msg{mu_msg_new_from_file (path, NULL, err)};
|
||||
const auto res = store.remove_message(path);
|
||||
g_debug("removed %s (%s)", path, res ? "yes" : "no");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static MuError
|
||||
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, MU_ERROR_INTERNAL);
|
||||
|
||||
return foreach_msg_file(store, opts, remove_path_func, err);
|
||||
}
|
||||
|
||||
static bool
|
||||
tickle_func(Mu::Store& store, const char* path, GError** err)
|
||||
{
|
||||
MuMsg* msg{mu_msg_new_from_file(path, NULL, err)};
|
||||
if (!msg)
|
||||
return false;
|
||||
|
||||
const auto res = mu_msg_tickle (msg, err);
|
||||
g_debug ("tickled %s (%s)", path, res ? "ok" : "failed");
|
||||
mu_msg_unref (msg);
|
||||
const auto res = mu_msg_tickle(msg, err);
|
||||
g_debug("tickled %s (%s)", path, res ? "ok" : "failed");
|
||||
mu_msg_unref(msg);
|
||||
|
||||
return res == TRUE;
|
||||
}
|
||||
|
||||
|
||||
static MuError
|
||||
cmd_tickle (Mu::Store& store, const 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,
|
||||
MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail(opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_TICKLE, MU_ERROR_INTERNAL);
|
||||
|
||||
return foreach_msg_file (store, opts, tickle_func, err);
|
||||
return foreach_msg_file(store, opts, tickle_func, err);
|
||||
}
|
||||
|
||||
struct _VData {
|
||||
MuMsgPartSigStatus combined_status;
|
||||
char *report;
|
||||
gboolean oneline;
|
||||
char* report;
|
||||
gboolean oneline;
|
||||
};
|
||||
typedef struct _VData VData;
|
||||
|
||||
static void
|
||||
each_sig (MuMsg *msg, MuMsgPart *part, VData *vdata)
|
||||
each_sig(MuMsg* msg, MuMsgPart* part, VData* vdata)
|
||||
{
|
||||
MuMsgPartSigStatusReport *report;
|
||||
MuMsgPartSigStatusReport* report;
|
||||
|
||||
report = part->sig_status_report;
|
||||
if (!report)
|
||||
return;
|
||||
|
||||
if (vdata->oneline)
|
||||
vdata->report = g_strdup_printf
|
||||
("%s%s%s",
|
||||
vdata->report ? vdata->report : "",
|
||||
vdata->report ? "; " : "",
|
||||
report->report);
|
||||
vdata->report = g_strdup_printf("%s%s%s",
|
||||
vdata->report ? vdata->report : "",
|
||||
vdata->report ? "; " : "",
|
||||
report->report);
|
||||
else
|
||||
vdata->report = g_strdup_printf
|
||||
("%s%s\t%s",
|
||||
vdata->report ? vdata->report : "",
|
||||
vdata->report ? "\n" : "",
|
||||
report->report);
|
||||
vdata->report = g_strdup_printf("%s%s\t%s",
|
||||
vdata->report ? vdata->report : "",
|
||||
vdata->report ? "\n" : "",
|
||||
report->report);
|
||||
|
||||
if (vdata->combined_status == MU_MSG_PART_SIG_STATUS_BAD ||
|
||||
vdata->combined_status == MU_MSG_PART_SIG_STATUS_ERROR)
|
||||
@ -466,170 +431,157 @@ each_sig (MuMsg *msg, MuMsgPart *part, VData *vdata)
|
||||
vdata->combined_status = report->verdict;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_verdict (VData *vdata, gboolean color, gboolean verbose)
|
||||
print_verdict(VData* vdata, gboolean color, gboolean verbose)
|
||||
{
|
||||
g_print ("verdict: ");
|
||||
g_print("verdict: ");
|
||||
|
||||
switch (vdata->combined_status) {
|
||||
case MU_MSG_PART_SIG_STATUS_UNSIGNED:
|
||||
g_print ("no signature found");
|
||||
break;
|
||||
case MU_MSG_PART_SIG_STATUS_UNSIGNED: g_print("no signature found"); break;
|
||||
case MU_MSG_PART_SIG_STATUS_GOOD:
|
||||
color_maybe (MU_COLOR_GREEN);
|
||||
g_print ("signature(s) verified");
|
||||
color_maybe(MU_COLOR_GREEN);
|
||||
g_print("signature(s) verified");
|
||||
break;
|
||||
case MU_MSG_PART_SIG_STATUS_BAD:
|
||||
color_maybe (MU_COLOR_RED);
|
||||
g_print ("bad signature");
|
||||
color_maybe(MU_COLOR_RED);
|
||||
g_print("bad signature");
|
||||
break;
|
||||
case MU_MSG_PART_SIG_STATUS_ERROR:
|
||||
color_maybe (MU_COLOR_RED);
|
||||
g_print ("verification failed");
|
||||
color_maybe(MU_COLOR_RED);
|
||||
g_print("verification failed");
|
||||
break;
|
||||
case MU_MSG_PART_SIG_STATUS_FAIL:
|
||||
color_maybe(MU_COLOR_RED);
|
||||
g_print ("error in verification process");
|
||||
g_print("error in verification process");
|
||||
break;
|
||||
default: g_return_if_reached ();
|
||||
default: g_return_if_reached();
|
||||
}
|
||||
|
||||
color_maybe (MU_COLOR_DEFAULT);
|
||||
color_maybe(MU_COLOR_DEFAULT);
|
||||
if (vdata->report && verbose)
|
||||
g_print ("%s%s\n",
|
||||
(vdata->oneline) ? ";" : "\n",
|
||||
vdata->report);
|
||||
g_print("%s%s\n", (vdata->oneline) ? ";" : "\n", vdata->report);
|
||||
else
|
||||
g_print ("\n");
|
||||
g_print("\n");
|
||||
}
|
||||
|
||||
|
||||
static MuError
|
||||
cmd_verify (const MuConfig *opts, GError **err)
|
||||
cmd_verify(const MuConfig* opts, GError** err)
|
||||
{
|
||||
MuMsg *msg;
|
||||
MuMsg* msg;
|
||||
int msgopts;
|
||||
VData vdata;
|
||||
|
||||
g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_VERIFY,
|
||||
MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail(opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail(opts->cmd == MU_CONFIG_CMD_VERIFY, MU_ERROR_INTERNAL);
|
||||
|
||||
if (!opts->params[1]) {
|
||||
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
|
||||
"missing message-file parameter");
|
||||
mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "missing message-file parameter");
|
||||
return MU_ERROR_IN_PARAMETERS;
|
||||
}
|
||||
|
||||
msg = mu_msg_new_from_file (opts->params[1], NULL, err);
|
||||
msg = mu_msg_new_from_file(opts->params[1], NULL, err);
|
||||
if (!msg)
|
||||
return MU_ERROR;
|
||||
|
||||
msgopts = mu_config_get_msg_options (opts)
|
||||
| MU_MSG_OPTION_VERIFY
|
||||
| MU_MSG_OPTION_CONSOLE_PASSWORD;
|
||||
msgopts =
|
||||
mu_config_get_msg_options(opts) | MU_MSG_OPTION_VERIFY | MU_MSG_OPTION_CONSOLE_PASSWORD;
|
||||
|
||||
vdata.report = NULL;
|
||||
vdata.report = NULL;
|
||||
vdata.combined_status = MU_MSG_PART_SIG_STATUS_UNSIGNED;
|
||||
vdata.oneline = FALSE;
|
||||
vdata.oneline = FALSE;
|
||||
|
||||
mu_msg_part_foreach (msg, (MuMsgOptions)msgopts,
|
||||
(MuMsgPartForeachFunc)each_sig, &vdata);
|
||||
mu_msg_part_foreach(msg, (MuMsgOptions)msgopts, (MuMsgPartForeachFunc)each_sig, &vdata);
|
||||
|
||||
if (!opts->quiet)
|
||||
print_verdict (&vdata, !opts->nocolor, opts->verbose);
|
||||
print_verdict(&vdata, !opts->nocolor, opts->verbose);
|
||||
|
||||
mu_msg_unref (msg);
|
||||
g_free (vdata.report);
|
||||
mu_msg_unref(msg);
|
||||
g_free(vdata.report);
|
||||
|
||||
return vdata.combined_status == MU_MSG_PART_SIG_STATUS_GOOD ?
|
||||
MU_OK : MU_ERROR;
|
||||
return vdata.combined_status == MU_MSG_PART_SIG_STATUS_GOOD ? MU_OK : MU_ERROR;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void key_val(const Mu::MaybeAnsi& col, const std::string& key, T val)
|
||||
static void
|
||||
key_val(const Mu::MaybeAnsi& col, const std::string& key, T val)
|
||||
{
|
||||
using Color = Mu::MaybeAnsi::Color;
|
||||
using Color = Mu::MaybeAnsi::Color;
|
||||
|
||||
std::cout << col.fg(Color::BrightBlue)
|
||||
<< std::left << std::setw(18) << key
|
||||
<< col.reset() << ": ";
|
||||
std::cout << col.fg(Color::BrightBlue) << std::left << std::setw(18) << key << col.reset()
|
||||
<< ": ";
|
||||
|
||||
std::cout << col.fg(Color::Green)
|
||||
<< val << col.reset() << "\n";
|
||||
std::cout << col.fg(Color::Green) << val << col.reset() << "\n";
|
||||
}
|
||||
|
||||
|
||||
static MuError
|
||||
cmd_info (const Mu::Store& store, const MuConfig *opts, GError **err)
|
||||
cmd_info(const Mu::Store& store, const MuConfig* opts, GError** err)
|
||||
{
|
||||
Mu::MaybeAnsi col{!opts->nocolor};
|
||||
Mu::MaybeAnsi col{!opts->nocolor};
|
||||
|
||||
key_val(col, "maildir", store.metadata().root_maildir);
|
||||
key_val(col, "database-path", store.metadata().database_path);
|
||||
key_val(col, "schema-version", store.metadata().schema_version);
|
||||
key_val(col, "max-message-size", store.metadata().max_message_size);
|
||||
key_val(col, "batch-size", store.metadata().batch_size);
|
||||
key_val(col, "messages in store", store.size());
|
||||
key_val(col, "maildir", store.metadata().root_maildir);
|
||||
key_val(col, "database-path", store.metadata().database_path);
|
||||
key_val(col, "schema-version", store.metadata().schema_version);
|
||||
key_val(col, "max-message-size", store.metadata().max_message_size);
|
||||
key_val(col, "batch-size", store.metadata().batch_size);
|
||||
key_val(col, "messages in store", store.size());
|
||||
|
||||
const auto created{store.metadata().created};
|
||||
const auto tstamp{::localtime (&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);
|
||||
char tbuf[64];
|
||||
strftime(tbuf, sizeof(tbuf), "%c", tstamp);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
key_val(col, "created", tbuf);
|
||||
key_val(col, "created", tbuf);
|
||||
|
||||
const auto addrs{store.metadata().personal_addresses};
|
||||
if (addrs.empty())
|
||||
key_val(col, "personal-address", "<none>");
|
||||
else
|
||||
for (auto&& c: addrs)
|
||||
key_val(col, "personal-address", c);
|
||||
if (addrs.empty())
|
||||
key_val(col, "personal-address", "<none>");
|
||||
else
|
||||
for (auto&& c : addrs)
|
||||
key_val(col, "personal-address", c);
|
||||
|
||||
return MU_OK;
|
||||
return MU_OK;
|
||||
}
|
||||
|
||||
static MuError
|
||||
cmd_init (const MuConfig *opts, GError **err)
|
||||
cmd_init(const MuConfig* opts, GError** err)
|
||||
{
|
||||
/* not provided, nor could we find a good default */
|
||||
if (!opts->maildir) {
|
||||
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
|
||||
"missing --maildir parameter and could "
|
||||
"not determine default");
|
||||
/* not provided, nor could we find a good default */
|
||||
if (!opts->maildir) {
|
||||
mu_util_g_set_error(err,
|
||||
MU_ERROR_IN_PARAMETERS,
|
||||
"missing --maildir parameter and could "
|
||||
"not determine default");
|
||||
return MU_ERROR_IN_PARAMETERS;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts->max_msg_size < 0) {
|
||||
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
|
||||
"invalid value for max-message-size");
|
||||
if (opts->max_msg_size < 0) {
|
||||
mu_util_g_set_error(err,
|
||||
MU_ERROR_IN_PARAMETERS,
|
||||
"invalid value for max-message-size");
|
||||
return MU_ERROR_IN_PARAMETERS;
|
||||
} else if (opts->batch_size < 0) {
|
||||
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
|
||||
"invalid value for batch-size");
|
||||
} else if (opts->batch_size < 0) {
|
||||
mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "invalid value for batch-size");
|
||||
return MU_ERROR_IN_PARAMETERS;
|
||||
}
|
||||
}
|
||||
|
||||
Mu::Store::Config conf{};
|
||||
conf.max_message_size = opts->max_msg_size;
|
||||
conf.batch_size = opts->batch_size;
|
||||
Mu::Store::Config conf{};
|
||||
conf.max_message_size = opts->max_msg_size;
|
||||
conf.batch_size = opts->batch_size;
|
||||
|
||||
Mu::StringVec my_addrs;
|
||||
auto addrs = opts->my_addresses;
|
||||
while (addrs && *addrs) {
|
||||
my_addrs.emplace_back (*addrs);
|
||||
++addrs;
|
||||
}
|
||||
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, conf);
|
||||
Mu::Store store(mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), opts->maildir, my_addrs, conf);
|
||||
if (!opts->quiet) {
|
||||
cmd_info (store, opts, NULL);
|
||||
cmd_info(store, opts, NULL);
|
||||
std::cout << "\nstore created; use the 'index' command to fill/update it.\n";
|
||||
}
|
||||
|
||||
@ -637,49 +589,46 @@ cmd_init (const MuConfig *opts, GError **err)
|
||||
}
|
||||
|
||||
static MuError
|
||||
cmd_find (const MuConfig *opts, GError **err)
|
||||
cmd_find(const MuConfig* opts, GError** err)
|
||||
{
|
||||
Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), true/*readonly*/};
|
||||
Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), true /*readonly*/};
|
||||
|
||||
return mu_cmd_find(store, opts, err);
|
||||
return mu_cmd_find(store, opts, err);
|
||||
}
|
||||
|
||||
static void
|
||||
show_usage (void)
|
||||
show_usage(void)
|
||||
{
|
||||
g_print ("usage: mu command [options] [parameters]\n");
|
||||
g_print ("where command is one of index, find, cfind, view, mkdir, "
|
||||
"extract, add, remove, script, verify or server\n");
|
||||
g_print ("see the mu, mu-<command> or mu-easy manpages for "
|
||||
"more information\n");
|
||||
g_print("usage: mu command [options] [parameters]\n");
|
||||
g_print("where command is one of index, find, cfind, view, mkdir, "
|
||||
"extract, add, remove, script, verify or server\n");
|
||||
g_print("see the mu, mu-<command> or mu-easy manpages for "
|
||||
"more information\n");
|
||||
}
|
||||
|
||||
typedef MuError (*readonly_store_func) (const Mu::Store&, const MuConfig *, GError **err);
|
||||
typedef MuError (*writable_store_func) (Mu::Store&, const 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_readonly_store (readonly_store_func func, const MuConfig *opts, GError **err)
|
||||
with_readonly_store(readonly_store_func func, const MuConfig* opts, GError** err)
|
||||
{
|
||||
const Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), true/*readonly*/};
|
||||
return func (store, opts, err);
|
||||
const Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), true /*readonly*/};
|
||||
return func(store, opts, err);
|
||||
}
|
||||
|
||||
static MuError
|
||||
with_writable_store (writable_store_func func, const MuConfig *opts, GError **err)
|
||||
with_writable_store(writable_store_func func, const MuConfig* opts, GError** err)
|
||||
{
|
||||
Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), false/*!readonly*/};
|
||||
return func (store, opts, err);
|
||||
Mu::Store store{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), false /*!readonly*/};
|
||||
return func(store, opts, err);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
check_params (const MuConfig *opts, GError **err)
|
||||
check_params(const MuConfig* opts, GError** err)
|
||||
{
|
||||
if (!opts->params||!opts->params[0]) {/* no command? */
|
||||
show_usage ();
|
||||
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
|
||||
"error in parameters");
|
||||
if (!opts->params || !opts->params[0]) { /* no command? */
|
||||
show_usage();
|
||||
mu_util_g_set_error(err, MU_ERROR_IN_PARAMETERS, "error in parameters");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -687,64 +636,58 @@ check_params (const MuConfig *opts, GError **err)
|
||||
}
|
||||
|
||||
MuError
|
||||
Mu::mu_cmd_execute (const MuConfig *opts, GError **err) try
|
||||
{
|
||||
Mu::mu_cmd_execute(const MuConfig* opts, GError** err)
|
||||
try {
|
||||
MuError merr;
|
||||
|
||||
g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail(opts, MU_ERROR_INTERNAL);
|
||||
|
||||
if (!check_params(opts, err))
|
||||
return MU_G_ERROR_CODE(err);
|
||||
|
||||
switch (opts->cmd) {
|
||||
|
||||
/* already handled in mu-config.c */
|
||||
case MU_CONFIG_CMD_HELP: return MU_OK;
|
||||
case MU_CONFIG_CMD_HELP:
|
||||
return MU_OK;
|
||||
|
||||
/* no store needed */
|
||||
/* no store needed */
|
||||
|
||||
case MU_CONFIG_CMD_MKDIR: merr = cmd_mkdir (opts, err); break;
|
||||
case MU_CONFIG_CMD_SCRIPT: merr = mu_cmd_script (opts, err); break;
|
||||
case MU_CONFIG_CMD_VIEW: merr = cmd_view (opts, err); break;
|
||||
case MU_CONFIG_CMD_VERIFY: merr = cmd_verify (opts, err); break;
|
||||
case MU_CONFIG_CMD_EXTRACT: merr = mu_cmd_extract (opts, err); break;
|
||||
case MU_CONFIG_CMD_MKDIR: merr = cmd_mkdir(opts, err); break;
|
||||
case MU_CONFIG_CMD_SCRIPT: merr = mu_cmd_script(opts, err); break;
|
||||
case MU_CONFIG_CMD_VIEW: merr = cmd_view(opts, err); break;
|
||||
case MU_CONFIG_CMD_VERIFY: merr = cmd_verify(opts, err); break;
|
||||
case MU_CONFIG_CMD_EXTRACT:
|
||||
merr = mu_cmd_extract(opts, err);
|
||||
break;
|
||||
|
||||
/* read-only store */
|
||||
/* read-only store */
|
||||
|
||||
case MU_CONFIG_CMD_CFIND:
|
||||
merr = with_readonly_store (mu_cmd_cfind, opts, err); break;
|
||||
case MU_CONFIG_CMD_FIND:
|
||||
merr = cmd_find(opts, err); break;
|
||||
case MU_CONFIG_CMD_CFIND: merr = with_readonly_store(mu_cmd_cfind, opts, err); break;
|
||||
case MU_CONFIG_CMD_FIND: 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 */
|
||||
/* writable store */
|
||||
|
||||
case MU_CONFIG_CMD_ADD:
|
||||
merr = with_writable_store (cmd_add, opts, err); break;
|
||||
case MU_CONFIG_CMD_REMOVE:
|
||||
merr = with_writable_store (cmd_remove, opts, err); break;
|
||||
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;
|
||||
case MU_CONFIG_CMD_ADD: merr = with_writable_store(cmd_add, opts, err); break;
|
||||
case MU_CONFIG_CMD_REMOVE: merr = with_writable_store(cmd_remove, opts, err); break;
|
||||
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;
|
||||
|
||||
/* commands instantiate store themselves */
|
||||
case MU_CONFIG_CMD_INIT:
|
||||
merr = cmd_init (opts,err); break;
|
||||
case MU_CONFIG_CMD_SERVER:
|
||||
merr = mu_cmd_server (opts, err); break;
|
||||
case MU_CONFIG_CMD_INIT: merr = cmd_init(opts, err); break;
|
||||
case MU_CONFIG_CMD_SERVER: merr = mu_cmd_server(opts, err); break;
|
||||
|
||||
default:
|
||||
merr = MU_ERROR_IN_PARAMETERS; break;
|
||||
default: merr = MU_ERROR_IN_PARAMETERS; break;
|
||||
}
|
||||
|
||||
return merr;
|
||||
|
||||
} catch (const Mu::Error& er) {
|
||||
g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", er.what());
|
||||
return MU_ERROR;
|
||||
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;
|
||||
g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", "caught exception");
|
||||
return MU_ERROR;
|
||||
}
|
||||
|
||||
18
mu/mu-cmd.hh
18
mu/mu-cmd.hh
@ -36,8 +36,7 @@ namespace Mu {
|
||||
* >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 (const Mu::Store& store, const MuConfig *opts,
|
||||
GError **err);
|
||||
MuError mu_cmd_find(const Mu::Store& store, const MuConfig* opts, GError** err);
|
||||
|
||||
/**
|
||||
* execute the 'extract' command
|
||||
@ -48,8 +47,7 @@ MuError mu_cmd_find (const Mu::Store& store, const MuConfig *opts,
|
||||
* @return MU_OK (0) if the command succeeds,
|
||||
* some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_extract (const MuConfig *opts, GError **err);
|
||||
|
||||
MuError mu_cmd_extract(const MuConfig* opts, GError** err);
|
||||
|
||||
/**
|
||||
* execute the 'script' command
|
||||
@ -60,7 +58,7 @@ MuError mu_cmd_extract (const MuConfig *opts, GError **err);
|
||||
* @return MU_OK (0) if the command succeeds,
|
||||
* some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_script (const MuConfig *opts, GError **err);
|
||||
MuError mu_cmd_script(const MuConfig* opts, GError** err);
|
||||
|
||||
/**
|
||||
* execute the cfind command
|
||||
@ -72,8 +70,7 @@ MuError mu_cmd_script (const MuConfig *opts, GError **err);
|
||||
* @return MU_OK (0) if the command succeeds,
|
||||
* some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_cfind (const Mu::Store& store, const 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 +80,7 @@ MuError mu_cmd_cfind (const Mu::Store& store, const MuConfig *opts,
|
||||
*
|
||||
* @return MU_OK if all went wall, some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_execute (const MuConfig *opts, GError **err);
|
||||
MuError mu_cmd_execute(const MuConfig* opts, GError** err);
|
||||
|
||||
/**
|
||||
* execute the 'index' command
|
||||
@ -95,7 +92,7 @@ MuError mu_cmd_execute (const MuConfig *opts, GError **err);
|
||||
* @return MU_OK (0) if the command succeeded,
|
||||
* some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_index (Mu::Store& store, const MuConfig *opt, GError **err);
|
||||
MuError mu_cmd_index(Mu::Store& store, const MuConfig* opt, GError** err);
|
||||
|
||||
/**
|
||||
* execute the server command
|
||||
@ -104,8 +101,7 @@ MuError mu_cmd_index (Mu::Store& store, const MuConfig *opt, GError **err);
|
||||
*
|
||||
* @return MU_OK (0) if the command succeeds, some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_server (const MuConfig *opts, GError **err);
|
||||
|
||||
MuError mu_cmd_server(const MuConfig* opts, GError** err);
|
||||
|
||||
} // namespace Mu
|
||||
|
||||
|
||||
971
mu/mu-config.cc
971
mu/mu-config.cc
File diff suppressed because it is too large
Load Diff
205
mu/mu-config.hh
205
mu/mu-config.hh
@ -35,28 +35,28 @@ typedef enum {
|
||||
MU_CONFIG_FORMAT_UNKNOWN = 0,
|
||||
|
||||
/* for cfind, find, view */
|
||||
MU_CONFIG_FORMAT_PLAIN, /* plain output */
|
||||
MU_CONFIG_FORMAT_PLAIN, /* plain output */
|
||||
|
||||
/* for cfind */
|
||||
MU_CONFIG_FORMAT_MUTT_ALIAS, /* mutt alias style */
|
||||
MU_CONFIG_FORMAT_MUTT_AB, /* mutt ext abook */
|
||||
MU_CONFIG_FORMAT_WL, /* Wanderlust abook */
|
||||
MU_CONFIG_FORMAT_CSV, /* comma-sep'd values */
|
||||
MU_CONFIG_FORMAT_ORG_CONTACT, /* org-contact */
|
||||
MU_CONFIG_FORMAT_BBDB, /* BBDB */
|
||||
MU_CONFIG_FORMAT_MUTT_ALIAS, /* mutt alias style */
|
||||
MU_CONFIG_FORMAT_MUTT_AB, /* mutt ext abook */
|
||||
MU_CONFIG_FORMAT_WL, /* Wanderlust abook */
|
||||
MU_CONFIG_FORMAT_CSV, /* comma-sep'd values */
|
||||
MU_CONFIG_FORMAT_ORG_CONTACT, /* org-contact */
|
||||
MU_CONFIG_FORMAT_BBDB, /* BBDB */
|
||||
MU_CONFIG_FORMAT_DEBUG,
|
||||
|
||||
/* for find, view */
|
||||
MU_CONFIG_FORMAT_SEXP, /* output sexps (emacs) */
|
||||
MU_CONFIG_FORMAT_JSON, /* output JSON */
|
||||
MU_CONFIG_FORMAT_SEXP, /* output sexps (emacs) */
|
||||
MU_CONFIG_FORMAT_JSON, /* output JSON */
|
||||
|
||||
/* for find */
|
||||
MU_CONFIG_FORMAT_LINKS, /* output as symlinks */
|
||||
MU_CONFIG_FORMAT_XML, /* output xml */
|
||||
MU_CONFIG_FORMAT_XQUERY, /* output the xapian query */
|
||||
MU_CONFIG_FORMAT_MQUERY, /* output the mux query */
|
||||
MU_CONFIG_FORMAT_LINKS, /* output as symlinks */
|
||||
MU_CONFIG_FORMAT_XML, /* output xml */
|
||||
MU_CONFIG_FORMAT_XQUERY, /* output the xapian query */
|
||||
MU_CONFIG_FORMAT_MQUERY, /* output the mux query */
|
||||
|
||||
MU_CONFIG_FORMAT_EXEC /* execute some command */
|
||||
MU_CONFIG_FORMAT_EXEC /* execute some command */
|
||||
} MuConfigFormat;
|
||||
|
||||
typedef enum {
|
||||
@ -68,8 +68,8 @@ typedef enum {
|
||||
MU_CONFIG_CMD_FIND,
|
||||
MU_CONFIG_CMD_HELP,
|
||||
MU_CONFIG_CMD_INDEX,
|
||||
MU_CONFIG_CMD_INFO,
|
||||
MU_CONFIG_CMD_INIT,
|
||||
MU_CONFIG_CMD_INFO,
|
||||
MU_CONFIG_CMD_INIT,
|
||||
MU_CONFIG_CMD_MKDIR,
|
||||
MU_CONFIG_CMD_REMOVE,
|
||||
MU_CONFIG_CMD_SCRIPT,
|
||||
@ -81,115 +81,110 @@ typedef enum {
|
||||
MU_CONFIG_CMD_NONE
|
||||
} MuConfigCmd;
|
||||
|
||||
|
||||
#define mu_config_cmd_is_valid(C) \
|
||||
((C) > MU_CONFIG_CMD_UNKNOWN && (C) < MU_CONFIG_CMD_NONE)
|
||||
|
||||
#define mu_config_cmd_is_valid(C) ((C) > MU_CONFIG_CMD_UNKNOWN && (C) < MU_CONFIG_CMD_NONE)
|
||||
|
||||
/* struct with all configuration options for mu; it will be filled
|
||||
* from the config file, and/or command line arguments */
|
||||
|
||||
struct _MuConfig {
|
||||
|
||||
MuConfigCmd cmd; /* the command, or
|
||||
* MU_CONFIG_CMD_NONE */
|
||||
char *cmdstr; /* cmd string, for user
|
||||
* info */
|
||||
MuConfigCmd cmd; /* the command, or
|
||||
* MU_CONFIG_CMD_NONE */
|
||||
char* cmdstr; /* cmd string, for user
|
||||
* info */
|
||||
/* general options */
|
||||
gboolean quiet; /* don't give any output */
|
||||
gboolean debug; /* log debug-level info */
|
||||
gchar *muhome; /* the House of Mu */
|
||||
gboolean version; /* request mu version */
|
||||
gboolean log_stderr; /* log to stderr (not logfile) */
|
||||
gchar** params; /* parameters (for querying) */
|
||||
gboolean nocolor; /* don't use use ansi-colors
|
||||
* in some output */
|
||||
gboolean verbose; /* verbose output */
|
||||
gboolean quiet; /* don't give any output */
|
||||
gboolean debug; /* log debug-level info */
|
||||
gchar* muhome; /* the House of Mu */
|
||||
gboolean version; /* request mu version */
|
||||
gboolean log_stderr; /* log to stderr (not logfile) */
|
||||
gchar** params; /* parameters (for querying) */
|
||||
gboolean nocolor; /* don't use use ansi-colors
|
||||
* in some output */
|
||||
gboolean verbose; /* verbose output */
|
||||
|
||||
/* options for init */
|
||||
gchar *maildir; /* where the mails are */
|
||||
char** my_addresses; /* 'my e-mail address', for mu cfind;
|
||||
* can be use multiple times */
|
||||
int max_msg_size; /* maximum size for message files */
|
||||
int batch_size; /* database transaction batch size */
|
||||
/* options for init */
|
||||
gchar* maildir; /* where the mails are */
|
||||
char** my_addresses; /* 'my e-mail address', for mu cfind;
|
||||
* can be use multiple times */
|
||||
int max_msg_size; /* maximum size for message files */
|
||||
int batch_size; /* database transaction batch size */
|
||||
|
||||
/* options for indexing */
|
||||
|
||||
gboolean nocleanup; /* don't cleanup del'd mails from db */
|
||||
gboolean rebuild; /* empty the database before indexing */
|
||||
gboolean lazycheck; /* don't check dirs with up-to-date
|
||||
* timestamps */
|
||||
|
||||
gboolean nocleanup; /* don't cleanup del'd mails from db */
|
||||
gboolean rebuild; /* empty the database before indexing */
|
||||
gboolean lazycheck; /* don't check dirs with up-to-date
|
||||
* timestamps */
|
||||
|
||||
/* options for querying 'find' (and view-> 'summary') */
|
||||
gchar *fields; /* fields to show in output */
|
||||
gchar *sortfield; /* field to sort by (string) */
|
||||
int maxnum; /* max # of entries to print */
|
||||
gboolean reverse; /* sort in revers order (z->a) */
|
||||
gboolean threads; /* show message threads */
|
||||
gchar* fields; /* fields to show in output */
|
||||
gchar* sortfield; /* field to sort by (string) */
|
||||
int maxnum; /* max # of entries to print */
|
||||
gboolean reverse; /* sort in revers order (z->a) */
|
||||
gboolean threads; /* show message threads */
|
||||
|
||||
gboolean summary; /* OBSOLETE: use summary_len */
|
||||
int summary_len; /* max # of lines for summary */
|
||||
gboolean summary; /* OBSOLETE: use summary_len */
|
||||
int summary_len; /* max # of lines for summary */
|
||||
|
||||
gchar *bookmark; /* use bookmark */
|
||||
gchar *formatstr; /* output type for find
|
||||
* (plain,links,xml,json,sexp)
|
||||
* and view (plain, sexp) and cfind
|
||||
*/
|
||||
MuConfigFormat format; /* the decoded formatstr */
|
||||
gchar *exec; /* command to execute on the
|
||||
* files for the matched
|
||||
* messages */
|
||||
gboolean skip_dups; /* if there are multiple
|
||||
* messages with the same
|
||||
* msgid, show only the first
|
||||
* one */
|
||||
gboolean include_related; /* included related messages
|
||||
* in results */
|
||||
gchar* bookmark; /* use bookmark */
|
||||
gchar* formatstr; /* output type for find
|
||||
* (plain,links,xml,json,sexp)
|
||||
* and view (plain, sexp) and cfind
|
||||
*/
|
||||
MuConfigFormat format; /* the decoded formatstr */
|
||||
gchar* exec; /* command to execute on the
|
||||
* files for the matched
|
||||
* messages */
|
||||
gboolean skip_dups; /* if there are multiple
|
||||
* messages with the same
|
||||
* msgid, show only the first
|
||||
* one */
|
||||
gboolean include_related; /* included related messages
|
||||
* in results */
|
||||
/* for find and cind */
|
||||
time_t after; /* only show messages or
|
||||
* addresses last seen after
|
||||
* T */
|
||||
time_t after; /* only show messages or
|
||||
* addresses last seen after
|
||||
* T */
|
||||
/* options for crypto
|
||||
* ie, 'view', 'extract' */
|
||||
gboolean auto_retrieve; /* assume we're online */
|
||||
gboolean use_agent; /* attempt to use the gpg-agent */
|
||||
gboolean decrypt; /* try to decrypt the
|
||||
* message body, if any */
|
||||
gboolean verify; /* try to crypto-verify the
|
||||
* message */
|
||||
gboolean auto_retrieve; /* assume we're online */
|
||||
gboolean use_agent; /* attempt to use the gpg-agent */
|
||||
gboolean decrypt; /* try to decrypt the
|
||||
* message body, if any */
|
||||
gboolean verify; /* try to crypto-verify the
|
||||
* message */
|
||||
|
||||
/* options for view */
|
||||
gboolean terminator; /* add separator \f between
|
||||
* multiple messages in mu
|
||||
* view */
|
||||
gboolean terminator; /* add separator \f between
|
||||
* multiple messages in mu
|
||||
* view */
|
||||
|
||||
/* options for cfind (and 'find' --> "after") */
|
||||
gboolean personal; /* only show 'personal' addresses */
|
||||
gboolean personal; /* only show 'personal' addresses */
|
||||
/* also 'after' --> see above */
|
||||
|
||||
/* output to a maildir with symlinks */
|
||||
gchar *linksdir; /* maildir to output symlinks */
|
||||
gboolean clearlinks; /* clear a linksdir before filling */
|
||||
mode_t dirmode; /* mode for the created maildir */
|
||||
gchar* linksdir; /* maildir to output symlinks */
|
||||
gboolean clearlinks; /* clear a linksdir before filling */
|
||||
mode_t dirmode; /* mode for the created maildir */
|
||||
|
||||
/* options for extracting parts */
|
||||
gboolean save_all; /* extract all parts */
|
||||
gboolean save_attachments; /* extract all attachment parts */
|
||||
gchar *parts; /* comma-sep'd list of parts
|
||||
* to save / open */
|
||||
gchar *targetdir; /* where to save the attachments */
|
||||
gboolean overwrite; /* should we overwrite same-named files */
|
||||
gboolean play; /* after saving, try to 'play'
|
||||
* (open) the attmnt using xdgopen */
|
||||
gboolean save_all; /* extract all parts */
|
||||
gboolean save_attachments; /* extract all attachment parts */
|
||||
gchar* parts; /* comma-sep'd list of parts
|
||||
* to save / open */
|
||||
gchar* targetdir; /* where to save the attachments */
|
||||
gboolean overwrite; /* should we overwrite same-named files */
|
||||
gboolean play; /* after saving, try to 'play'
|
||||
* (open) the attmnt using xdgopen */
|
||||
/* for server */
|
||||
gboolean commands; /* dump documentations for server
|
||||
* commands */
|
||||
gchar *eval; /* command to evaluate */
|
||||
gboolean commands; /* dump documentations for server
|
||||
* commands */
|
||||
gchar* eval; /* command to evaluate */
|
||||
|
||||
/* options for mu-script */
|
||||
gchar *script; /* script to run */
|
||||
const char **script_params; /* parameters for scripts */
|
||||
/* options for mu-script */
|
||||
gchar* script; /* script to run */
|
||||
const char** script_params; /* parameters for scripts */
|
||||
};
|
||||
typedef struct _MuConfig MuConfig;
|
||||
|
||||
@ -207,15 +202,13 @@ typedef struct _MuConfig MuConfig;
|
||||
* @param argvp: pointer to argv
|
||||
* @param err: receives error information
|
||||
*/
|
||||
MuConfig *mu_config_init (int *argcp, char ***argvp, GError **err)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
MuConfig* mu_config_init(int* argcp, char*** argvp, GError** err) G_GNUC_WARN_UNUSED_RESULT;
|
||||
/**
|
||||
* free the MuConfig structure
|
||||
*
|
||||
* @param opts a MuConfig struct, or NULL
|
||||
*/
|
||||
void mu_config_uninit (MuConfig *conf);
|
||||
|
||||
void mu_config_uninit(MuConfig* conf);
|
||||
|
||||
/**
|
||||
* execute the command / options in this config
|
||||
@ -227,7 +220,7 @@ void mu_config_uninit (MuConfig *conf);
|
||||
* the exit code of the process
|
||||
*
|
||||
*/
|
||||
MuError mu_config_execute (const MuConfig *conf);
|
||||
MuError mu_config_execute(const MuConfig* conf);
|
||||
|
||||
/**
|
||||
* count the number of non-option parameters
|
||||
@ -236,8 +229,7 @@ MuError mu_config_execute (const MuConfig *conf);
|
||||
*
|
||||
* @return the number of non-option parameters, or 0 in case of error
|
||||
*/
|
||||
size_t mu_config_param_num (const MuConfig *conf);
|
||||
|
||||
size_t mu_config_param_num(const MuConfig* conf);
|
||||
|
||||
/**
|
||||
* determine MuMsgOptions for command line args
|
||||
@ -246,15 +238,14 @@ size_t mu_config_param_num (const MuConfig *conf);
|
||||
*
|
||||
* @return the corresponding MuMsgOptions
|
||||
*/
|
||||
MuMsgOptions mu_config_get_msg_options (const MuConfig *opts);
|
||||
|
||||
MuMsgOptions mu_config_get_msg_options(const MuConfig* opts);
|
||||
|
||||
/**
|
||||
* print help text for the current command
|
||||
*
|
||||
* @param cmd the command to show help for
|
||||
*/
|
||||
void mu_config_show_help (const MuConfigCmd cmd);
|
||||
void mu_config_show_help(const MuConfigCmd cmd);
|
||||
|
||||
} // namespace Mu.
|
||||
|
||||
|
||||
155
mu/mu.cc
155
mu/mu.cc
@ -31,110 +31,105 @@
|
||||
using namespace Mu;
|
||||
|
||||
static void
|
||||
show_version (void)
|
||||
show_version(void)
|
||||
{
|
||||
const char* blurb =
|
||||
"mu (mail indexer/searcher) version " VERSION "\n"
|
||||
"Copyright (C) 2008-2021 Dirk-Jan C. Binnema\n"
|
||||
"License GPLv3+: GNU GPL version 3 or later "
|
||||
"<http://gnu.org/licenses/gpl.html>.\n"
|
||||
"This is free software: you are free to change "
|
||||
"and redistribute it.\n"
|
||||
"There is NO WARRANTY, to the extent permitted by law.";
|
||||
const char* blurb = "mu (mail indexer/searcher) version " VERSION "\n"
|
||||
"Copyright (C) 2008-2021 Dirk-Jan C. Binnema\n"
|
||||
"License GPLv3+: GNU GPL version 3 or later "
|
||||
"<http://gnu.org/licenses/gpl.html>.\n"
|
||||
"This is free software: you are free to change "
|
||||
"and redistribute it.\n"
|
||||
"There is NO WARRANTY, to the extent permitted by law.";
|
||||
|
||||
g_print ("%s\n", blurb);
|
||||
g_print("%s\n", blurb);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handle_error (MuConfig *conf, MuError merr, GError **err)
|
||||
handle_error(MuConfig* conf, MuError merr, GError** err)
|
||||
{
|
||||
if (!(err && *err))
|
||||
return;
|
||||
if (!(err && *err))
|
||||
return;
|
||||
|
||||
using Color = MaybeAnsi::Color;
|
||||
MaybeAnsi col{conf ? !conf->nocolor : false};
|
||||
using Color = MaybeAnsi::Color;
|
||||
MaybeAnsi col{conf ? !conf->nocolor : false};
|
||||
|
||||
if (*err)
|
||||
std::cerr << col.fg(Color::Red) << "error" << col.reset() << ": "
|
||||
<< col.fg(Color::BrightYellow)
|
||||
<< ((*err) ? (*err)->message : "something when wrong")
|
||||
<< "\n";
|
||||
if (*err)
|
||||
std::cerr << col.fg(Color::Red) << "error" << col.reset() << ": "
|
||||
<< col.fg(Color::BrightYellow)
|
||||
<< ((*err) ? (*err)->message : "something when wrong") << "\n";
|
||||
|
||||
std::cerr << col.fg(Color::Green);
|
||||
std::cerr << col.fg(Color::Green);
|
||||
|
||||
switch ((*err)->code) {
|
||||
case MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK:
|
||||
std::cerr << "Maybe mu is already running?\n";
|
||||
break;
|
||||
switch ((*err)->code) {
|
||||
case MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK:
|
||||
std::cerr << "Maybe mu is already running?\n";
|
||||
break;
|
||||
|
||||
case MU_ERROR_XAPIAN_NEEDS_REINDEX:
|
||||
std::cerr << "Database needs (re)indexing.\n"
|
||||
<< "try 'mu index' "
|
||||
<< "(see mu-index(1) for details)\n";
|
||||
return;
|
||||
case MU_ERROR_IN_PARAMETERS:
|
||||
if (conf && mu_config_cmd_is_valid(conf->cmd))
|
||||
mu_config_show_help (conf->cmd);
|
||||
break;
|
||||
case MU_ERROR_SCRIPT_NOT_FOUND:
|
||||
std::cerr << "See the mu manpage for commands, or "
|
||||
<< "'mu script' for the scripts\n";
|
||||
break;
|
||||
case MU_ERROR_XAPIAN_CANNOT_OPEN:
|
||||
std::cerr << "Please (re)initialize mu with 'mu init' "
|
||||
<< "see mu-init(1) for details\n";
|
||||
return;
|
||||
case MU_ERROR_XAPIAN_SCHEMA_MISMATCH:
|
||||
std::cerr << "Please (re)initialize mu with 'mu init' "
|
||||
<< "see mu-init(1) for details\n";
|
||||
return;
|
||||
default:
|
||||
break; /* nothing to do */
|
||||
}
|
||||
case MU_ERROR_XAPIAN_NEEDS_REINDEX:
|
||||
std::cerr << "Database needs (re)indexing.\n"
|
||||
<< "try 'mu index' "
|
||||
<< "(see mu-index(1) for details)\n";
|
||||
return;
|
||||
case MU_ERROR_IN_PARAMETERS:
|
||||
if (conf && mu_config_cmd_is_valid(conf->cmd))
|
||||
mu_config_show_help(conf->cmd);
|
||||
break;
|
||||
case MU_ERROR_SCRIPT_NOT_FOUND:
|
||||
std::cerr << "See the mu manpage for commands, or "
|
||||
<< "'mu script' for the scripts\n";
|
||||
break;
|
||||
case MU_ERROR_XAPIAN_CANNOT_OPEN:
|
||||
std::cerr << "Please (re)initialize mu with 'mu init' "
|
||||
<< "see mu-init(1) for details\n";
|
||||
return;
|
||||
case MU_ERROR_XAPIAN_SCHEMA_MISMATCH:
|
||||
std::cerr << "Please (re)initialize mu with 'mu init' "
|
||||
<< "see mu-init(1) for details\n";
|
||||
return;
|
||||
default: break; /* nothing to do */
|
||||
}
|
||||
|
||||
std::cerr << col.reset();
|
||||
std::cerr << col.reset();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
GError *err;
|
||||
MuError rv;
|
||||
MuConfig *conf;
|
||||
GError* err;
|
||||
MuError rv;
|
||||
MuConfig* conf;
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
err = NULL;
|
||||
rv = MU_OK;
|
||||
err = NULL;
|
||||
rv = MU_OK;
|
||||
|
||||
conf = mu_config_init (&argc, &argv, &err);
|
||||
if (!conf) {
|
||||
rv = err ? (MuError)err->code : MU_ERROR;
|
||||
goto cleanup;
|
||||
} else if (conf->version) {
|
||||
show_version ();
|
||||
goto cleanup;
|
||||
}
|
||||
conf = mu_config_init(&argc, &argv, &err);
|
||||
if (!conf) {
|
||||
rv = err ? (MuError)err->code : MU_ERROR;
|
||||
goto cleanup;
|
||||
} else if (conf->version) {
|
||||
show_version();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* nothing to do */
|
||||
if (conf->cmd == MU_CONFIG_CMD_NONE)
|
||||
return 0;
|
||||
/* nothing to do */
|
||||
if (conf->cmd == MU_CONFIG_CMD_NONE)
|
||||
return 0;
|
||||
|
||||
if (!mu_runtime_init (conf->muhome, PACKAGE_NAME, conf->debug)) {
|
||||
mu_config_uninit (conf);
|
||||
return 1;
|
||||
}
|
||||
if (!mu_runtime_init(conf->muhome, PACKAGE_NAME, conf->debug)) {
|
||||
mu_config_uninit(conf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rv = mu_cmd_execute (conf, &err);
|
||||
rv = mu_cmd_execute(conf, &err);
|
||||
|
||||
cleanup:
|
||||
handle_error (conf, rv, &err);
|
||||
g_clear_error (&err);
|
||||
handle_error(conf, rv, &err);
|
||||
g_clear_error(&err);
|
||||
|
||||
mu_config_uninit (conf);
|
||||
mu_runtime_uninit ();
|
||||
mu_config_uninit(conf);
|
||||
mu_runtime_uninit();
|
||||
|
||||
return rv;
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -31,338 +31,327 @@
|
||||
#include "mu-store.hh"
|
||||
#include "mu-query.hh"
|
||||
|
||||
static gchar *CONTACTS_CACHE = NULL;
|
||||
static gchar* CONTACTS_CACHE = NULL;
|
||||
|
||||
static gchar*
|
||||
fill_contacts_cache (void)
|
||||
fill_contacts_cache(void)
|
||||
{
|
||||
gchar *cmdline, *tmpdir;
|
||||
GError *err;
|
||||
gchar * cmdline, *tmpdir;
|
||||
GError* err;
|
||||
|
||||
tmpdir = test_mu_common_get_random_tmpdir();
|
||||
cmdline = g_strdup_printf (
|
||||
"/bin/sh -c '"
|
||||
"%s init --muhome=%s --maildir=%s --quiet; "
|
||||
"%s index --muhome=%s --quiet'",
|
||||
MU_PROGRAM, tmpdir, MU_TESTMAILDIR,
|
||||
MU_PROGRAM, tmpdir);
|
||||
tmpdir = test_mu_common_get_random_tmpdir();
|
||||
cmdline = g_strdup_printf("/bin/sh -c '"
|
||||
"%s init --muhome=%s --maildir=%s --quiet; "
|
||||
"%s index --muhome=%s --quiet'",
|
||||
MU_PROGRAM,
|
||||
tmpdir,
|
||||
MU_TESTMAILDIR,
|
||||
MU_PROGRAM,
|
||||
tmpdir);
|
||||
|
||||
if (g_test_verbose())
|
||||
g_print ("%s\n", cmdline);
|
||||
g_print("%s\n", cmdline);
|
||||
|
||||
err = NULL;
|
||||
if (!g_spawn_command_line_sync (cmdline, NULL, NULL,
|
||||
NULL, &err)) {
|
||||
g_printerr ("Error: %s\n", err ? err->message : "?");
|
||||
g_assert (0);
|
||||
err = NULL;
|
||||
if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &err)) {
|
||||
g_printerr("Error: %s\n", err ? err->message : "?");
|
||||
g_assert(0);
|
||||
}
|
||||
|
||||
g_free (cmdline);
|
||||
g_free(cmdline);
|
||||
return tmpdir;
|
||||
}
|
||||
|
||||
static void
|
||||
test_mu_cfind_plain (void)
|
||||
test_mu_cfind_plain(void)
|
||||
{
|
||||
gchar *cmdline, *output, *erroutput;
|
||||
|
||||
cmdline = g_strdup_printf ("%s cfind --muhome=%s --format=plain "
|
||||
"'testmu\\.xxx?'",
|
||||
MU_PROGRAM, CONTACTS_CACHE);
|
||||
cmdline = g_strdup_printf("%s cfind --muhome=%s --format=plain "
|
||||
"'testmu\\.xxx?'",
|
||||
MU_PROGRAM,
|
||||
CONTACTS_CACHE);
|
||||
if (g_test_verbose())
|
||||
g_print ("%s\n", cmdline);
|
||||
g_print("%s\n", cmdline);
|
||||
|
||||
output = erroutput = NULL;
|
||||
g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput,
|
||||
NULL, NULL));
|
||||
g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL));
|
||||
|
||||
/* note, output order is unspecified */
|
||||
g_assert (output);
|
||||
g_assert(output);
|
||||
if (output[0] == 'H')
|
||||
g_assert_cmpstr (output,
|
||||
==,
|
||||
"Helmut Kröger hk@testmu.xxx\n"
|
||||
"Mü testmu@testmu.xx\n");
|
||||
g_assert_cmpstr(output,
|
||||
==,
|
||||
"Helmut Kröger hk@testmu.xxx\n"
|
||||
"Mü testmu@testmu.xx\n");
|
||||
else
|
||||
g_assert_cmpstr (output,
|
||||
==,
|
||||
"Mü testmu@testmu.xx\n"
|
||||
"Helmut Kröger hk@testmu.xxx\n");
|
||||
g_free (cmdline);
|
||||
g_free (output);
|
||||
g_free (erroutput);
|
||||
g_assert_cmpstr(output,
|
||||
==,
|
||||
"Mü testmu@testmu.xx\n"
|
||||
"Helmut Kröger hk@testmu.xxx\n");
|
||||
g_free(cmdline);
|
||||
g_free(output);
|
||||
g_free(erroutput);
|
||||
}
|
||||
|
||||
static void
|
||||
test_mu_cfind_bbdb (void)
|
||||
test_mu_cfind_bbdb(void)
|
||||
{
|
||||
gchar *cmdline, *output, *erroutput, *expected;
|
||||
gchar today[12];
|
||||
struct tm *tmtoday;
|
||||
time_t now;
|
||||
const char *old_tz;
|
||||
gchar * cmdline, *output, *erroutput, *expected;
|
||||
gchar today[12];
|
||||
struct tm* tmtoday;
|
||||
time_t now;
|
||||
const char* old_tz;
|
||||
|
||||
old_tz = set_tz ("Europe/Helsinki");
|
||||
old_tz = set_tz("Europe/Helsinki");
|
||||
|
||||
cmdline = g_strdup_printf ("%s cfind --muhome=%s --format=bbdb "
|
||||
"'testmu\\.xxx?'",
|
||||
MU_PROGRAM, CONTACTS_CACHE);
|
||||
cmdline = g_strdup_printf("%s cfind --muhome=%s --format=bbdb "
|
||||
"'testmu\\.xxx?'",
|
||||
MU_PROGRAM,
|
||||
CONTACTS_CACHE);
|
||||
|
||||
output = erroutput = NULL;
|
||||
g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput,
|
||||
NULL, NULL));
|
||||
g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL));
|
||||
|
||||
#define frm1 ";; -*-coding: utf-8-emacs;-*-\n" \
|
||||
";;; file-version: 6\n" \
|
||||
"[\"Helmut\" \"Kröger\" nil nil nil nil (\"hk@testmu.xxx\") " \
|
||||
"((creation-date . \"%s\") " \
|
||||
"(time-stamp . \"1970-01-01\")) nil]\n" \
|
||||
"[\"Mü\" \"\" nil nil nil nil (\"testmu@testmu.xx\") " \
|
||||
"((creation-date . \"%s\") " \
|
||||
"(time-stamp . \"1970-01-01\")) nil]\n"
|
||||
#define frm1 \
|
||||
";; -*-coding: utf-8-emacs;-*-\n" \
|
||||
";;; file-version: 6\n" \
|
||||
"[\"Helmut\" \"Kröger\" nil nil nil nil (\"hk@testmu.xxx\") " \
|
||||
"((creation-date . \"%s\") " \
|
||||
"(time-stamp . \"1970-01-01\")) nil]\n" \
|
||||
"[\"Mü\" \"\" nil nil nil nil (\"testmu@testmu.xx\") " \
|
||||
"((creation-date . \"%s\") " \
|
||||
"(time-stamp . \"1970-01-01\")) nil]\n"
|
||||
|
||||
#define frm2 \
|
||||
";; -*-coding: utf-8-emacs;-*-\n" \
|
||||
";;; file-version: 6\n" \
|
||||
"[\"Mü\" \"\" nil nil nil nil (\"testmu@testmu.xx\") " \
|
||||
"((creation-date . \"%s\") " \
|
||||
"(time-stamp . \"1970-01-01\")) nil]\n" \
|
||||
"[\"Helmut\" \"Kröger\" nil nil nil nil (\"hk@testmu.xxx\") " \
|
||||
"((creation-date . \"%s\") " \
|
||||
"(time-stamp . \"1970-01-01\")) nil]\n"
|
||||
|
||||
#define frm2 ";; -*-coding: utf-8-emacs;-*-\n" \
|
||||
";;; file-version: 6\n" \
|
||||
"[\"Mü\" \"\" nil nil nil nil (\"testmu@testmu.xx\") " \
|
||||
"((creation-date . \"%s\") " \
|
||||
"(time-stamp . \"1970-01-01\")) nil]\n" \
|
||||
"[\"Helmut\" \"Kröger\" nil nil nil nil (\"hk@testmu.xxx\") " \
|
||||
"((creation-date . \"%s\") " \
|
||||
"(time-stamp . \"1970-01-01\")) nil]\n"
|
||||
g_assert(output);
|
||||
|
||||
g_assert (output);
|
||||
|
||||
now = time(NULL);
|
||||
now = time(NULL);
|
||||
tmtoday = localtime(&now);
|
||||
strftime(today,sizeof(today),"%Y-%m-%d", tmtoday);
|
||||
strftime(today, sizeof(today), "%Y-%m-%d", tmtoday);
|
||||
|
||||
expected = g_strdup_printf (output[52] == 'H' ? frm1 : frm2,
|
||||
today, today);
|
||||
expected = g_strdup_printf(output[52] == 'H' ? frm1 : frm2, today, today);
|
||||
|
||||
/* g_print ("\n%s\n", output); */
|
||||
|
||||
g_assert_cmpstr (output, ==, expected);
|
||||
g_assert_cmpstr(output, ==, expected);
|
||||
|
||||
g_free (cmdline);
|
||||
g_free (output);
|
||||
g_free (erroutput);
|
||||
g_free (expected);
|
||||
g_free(cmdline);
|
||||
g_free(output);
|
||||
g_free(erroutput);
|
||||
g_free(expected);
|
||||
|
||||
set_tz (old_tz);
|
||||
set_tz(old_tz);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_mu_cfind_wl (void)
|
||||
test_mu_cfind_wl(void)
|
||||
{
|
||||
gchar *cmdline, *output, *erroutput;
|
||||
|
||||
cmdline = g_strdup_printf ("%s cfind --muhome=%s --format=wl "
|
||||
"'testmu\\.xxx?'",
|
||||
MU_PROGRAM, CONTACTS_CACHE);
|
||||
cmdline = g_strdup_printf("%s cfind --muhome=%s --format=wl "
|
||||
"'testmu\\.xxx?'",
|
||||
MU_PROGRAM,
|
||||
CONTACTS_CACHE);
|
||||
|
||||
output = erroutput = NULL;
|
||||
g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput,
|
||||
NULL, NULL));
|
||||
g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL));
|
||||
|
||||
g_assert (output);
|
||||
g_assert(output);
|
||||
if (output[0] == 'h')
|
||||
g_assert_cmpstr (output,
|
||||
==,
|
||||
"hk@testmu.xxx \"HelmutK\" \"Helmut Kröger\"\n"
|
||||
"testmu@testmu.xx \"Mü\" \"Mü\"\n");
|
||||
g_assert_cmpstr(output,
|
||||
==,
|
||||
"hk@testmu.xxx \"HelmutK\" \"Helmut Kröger\"\n"
|
||||
"testmu@testmu.xx \"Mü\" \"Mü\"\n");
|
||||
else
|
||||
g_assert_cmpstr (output,
|
||||
==,
|
||||
"testmu@testmu.xx \"Mü\" \"Mü\"\n"
|
||||
"hk@testmu.xxx \"HelmutK\" \"Helmut Kröger\"\n");
|
||||
g_assert_cmpstr(output,
|
||||
==,
|
||||
"testmu@testmu.xx \"Mü\" \"Mü\"\n"
|
||||
"hk@testmu.xxx \"HelmutK\" \"Helmut Kröger\"\n");
|
||||
|
||||
g_free (cmdline);
|
||||
g_free (output);
|
||||
g_free (erroutput);
|
||||
g_free(cmdline);
|
||||
g_free(output);
|
||||
g_free(erroutput);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_mu_cfind_mutt_alias (void)
|
||||
test_mu_cfind_mutt_alias(void)
|
||||
{
|
||||
gchar *cmdline, *output, *erroutput;
|
||||
|
||||
cmdline = g_strdup_printf ("%s cfind --muhome=%s --format=mutt-alias "
|
||||
"'testmu\\.xxx?'",
|
||||
MU_PROGRAM, CONTACTS_CACHE);
|
||||
cmdline = g_strdup_printf("%s cfind --muhome=%s --format=mutt-alias "
|
||||
"'testmu\\.xxx?'",
|
||||
MU_PROGRAM,
|
||||
CONTACTS_CACHE);
|
||||
|
||||
output = erroutput = NULL;
|
||||
g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput,
|
||||
NULL, NULL));
|
||||
g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL));
|
||||
|
||||
/* both orders are possible... */
|
||||
g_assert (output);
|
||||
g_assert(output);
|
||||
|
||||
if (output[6] == 'H')
|
||||
g_assert_cmpstr (output,
|
||||
==,
|
||||
"alias HelmutK Helmut Kröger <hk@testmu.xxx>\n"
|
||||
"alias Mü Mü <testmu@testmu.xx>\n");
|
||||
g_assert_cmpstr(output,
|
||||
==,
|
||||
"alias HelmutK Helmut Kröger <hk@testmu.xxx>\n"
|
||||
"alias Mü Mü <testmu@testmu.xx>\n");
|
||||
else
|
||||
g_assert_cmpstr (output,
|
||||
==,
|
||||
"alias Mü Mü <testmu@testmu.xx>\n"
|
||||
"alias HelmutK Helmut Kröger <hk@testmu.xxx>\n");
|
||||
g_assert_cmpstr(output,
|
||||
==,
|
||||
"alias Mü Mü <testmu@testmu.xx>\n"
|
||||
"alias HelmutK Helmut Kröger <hk@testmu.xxx>\n");
|
||||
|
||||
|
||||
g_free (cmdline);
|
||||
g_free (output);
|
||||
g_free (erroutput);
|
||||
g_free(cmdline);
|
||||
g_free(output);
|
||||
g_free(erroutput);
|
||||
}
|
||||
|
||||
static void
|
||||
test_mu_cfind_mutt_ab (void)
|
||||
test_mu_cfind_mutt_ab(void)
|
||||
{
|
||||
gchar *cmdline, *output, *erroutput;
|
||||
|
||||
cmdline = g_strdup_printf ("%s cfind --muhome=%s --format=mutt-ab "
|
||||
"'testmu\\.xxx?'",
|
||||
MU_PROGRAM, CONTACTS_CACHE);
|
||||
cmdline = g_strdup_printf("%s cfind --muhome=%s --format=mutt-ab "
|
||||
"'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);
|
||||
g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL));
|
||||
g_assert(output);
|
||||
|
||||
if (output[39] == 'h')
|
||||
g_assert_cmpstr (output,
|
||||
==,
|
||||
"Matching addresses in the mu database:\n"
|
||||
"hk@testmu.xxx\tHelmut Kröger\t\n"
|
||||
"testmu@testmu.xx\tMü\t\n");
|
||||
g_assert_cmpstr(output,
|
||||
==,
|
||||
"Matching addresses in the mu database:\n"
|
||||
"hk@testmu.xxx\tHelmut Kröger\t\n"
|
||||
"testmu@testmu.xx\tMü\t\n");
|
||||
else
|
||||
g_assert_cmpstr (output,
|
||||
==,
|
||||
"Matching addresses in the mu database:\n"
|
||||
"testmu@testmu.xx\tMü\t\n"
|
||||
"hk@testmu.xxx\tHelmut Kröger\t\n");
|
||||
g_assert_cmpstr(output,
|
||||
==,
|
||||
"Matching addresses in the mu database:\n"
|
||||
"testmu@testmu.xx\tMü\t\n"
|
||||
"hk@testmu.xxx\tHelmut Kröger\t\n");
|
||||
|
||||
g_free (cmdline);
|
||||
g_free (output);
|
||||
g_free (erroutput);
|
||||
g_free(cmdline);
|
||||
g_free(output);
|
||||
g_free(erroutput);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_mu_cfind_org_contact (void)
|
||||
{
|
||||
gchar*cmdline, *output, *erroutput;
|
||||
|
||||
cmdline = g_strdup_printf ("%s cfind --muhome=%s --format=org-contact "
|
||||
"'testmu\\.xxx?'",
|
||||
MU_PROGRAM, CONTACTS_CACHE);
|
||||
|
||||
output = erroutput = NULL;
|
||||
g_assert (g_spawn_command_line_sync (cmdline, &output, &erroutput,
|
||||
NULL, NULL));
|
||||
|
||||
g_assert (output);
|
||||
|
||||
if (output[2] == 'H')
|
||||
g_assert_cmpstr (output,
|
||||
==,
|
||||
"* Helmut Kröger\n"
|
||||
":PROPERTIES:\n"
|
||||
":EMAIL: hk@testmu.xxx\n"
|
||||
":END:\n\n"
|
||||
"* Mü\n"
|
||||
":PROPERTIES:\n"
|
||||
":EMAIL: testmu@testmu.xx\n"
|
||||
":END:\n\n");
|
||||
else
|
||||
g_assert_cmpstr (output,
|
||||
==,
|
||||
"* Mü\n"
|
||||
":PROPERTIES:\n"
|
||||
":EMAIL: testmu@testmu.xx\n"
|
||||
":END:\n\n"
|
||||
"* Helmut Kröger\n"
|
||||
":PROPERTIES:\n"
|
||||
":EMAIL: hk@testmu.xxx\n"
|
||||
":END:\n\n");
|
||||
|
||||
|
||||
g_free (cmdline);
|
||||
g_free (output);
|
||||
g_free (erroutput);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
test_mu_cfind_csv (void)
|
||||
test_mu_cfind_org_contact(void)
|
||||
{
|
||||
gchar *cmdline, *output, *erroutput;
|
||||
|
||||
cmdline = g_strdup_printf ("%s cfind --muhome=%s --format=csv "
|
||||
"'testmu\\.xxx?'",
|
||||
MU_PROGRAM, CONTACTS_CACHE);
|
||||
cmdline = g_strdup_printf("%s cfind --muhome=%s --format=org-contact "
|
||||
"'testmu\\.xxx?'",
|
||||
MU_PROGRAM,
|
||||
CONTACTS_CACHE);
|
||||
|
||||
output = erroutput = NULL;
|
||||
g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL));
|
||||
|
||||
g_assert(output);
|
||||
|
||||
if (output[2] == 'H')
|
||||
g_assert_cmpstr(output,
|
||||
==,
|
||||
"* Helmut Kröger\n"
|
||||
":PROPERTIES:\n"
|
||||
":EMAIL: hk@testmu.xxx\n"
|
||||
":END:\n\n"
|
||||
"* Mü\n"
|
||||
":PROPERTIES:\n"
|
||||
":EMAIL: testmu@testmu.xx\n"
|
||||
":END:\n\n");
|
||||
else
|
||||
g_assert_cmpstr(output,
|
||||
==,
|
||||
"* Mü\n"
|
||||
":PROPERTIES:\n"
|
||||
":EMAIL: testmu@testmu.xx\n"
|
||||
":END:\n\n"
|
||||
"* Helmut Kröger\n"
|
||||
":PROPERTIES:\n"
|
||||
":EMAIL: hk@testmu.xxx\n"
|
||||
":END:\n\n");
|
||||
|
||||
g_free(cmdline);
|
||||
g_free(output);
|
||||
g_free(erroutput);
|
||||
}
|
||||
|
||||
static void
|
||||
test_mu_cfind_csv(void)
|
||||
{
|
||||
gchar *cmdline, *output, *erroutput;
|
||||
|
||||
cmdline = g_strdup_printf("%s cfind --muhome=%s --format=csv "
|
||||
"'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);
|
||||
g_assert(g_spawn_command_line_sync(cmdline, &output, &erroutput, NULL, NULL));
|
||||
g_assert(output);
|
||||
if (output[1] == 'H')
|
||||
g_assert_cmpstr (output,
|
||||
==,
|
||||
"\"Helmut Kröger\",\"hk@testmu.xxx\"\n"
|
||||
"\"Mü\",\"testmu@testmu.xx\"\n");
|
||||
g_assert_cmpstr(output,
|
||||
==,
|
||||
"\"Helmut Kröger\",\"hk@testmu.xxx\"\n"
|
||||
"\"Mü\",\"testmu@testmu.xx\"\n");
|
||||
else
|
||||
g_assert_cmpstr (output,
|
||||
==,
|
||||
"\"Mü\",\"testmu@testmu.xx\"\n"
|
||||
"\"Helmut Kröger\",\"hk@testmu.xxx\"\n");
|
||||
g_free (cmdline);
|
||||
g_free (output);
|
||||
g_free (erroutput);
|
||||
g_assert_cmpstr(output,
|
||||
==,
|
||||
"\"Mü\",\"testmu@testmu.xx\"\n"
|
||||
"\"Helmut Kröger\",\"hk@testmu.xxx\"\n");
|
||||
g_free(cmdline);
|
||||
g_free(output);
|
||||
g_free(erroutput);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
int rv;
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
if (!set_en_us_utf8_locale())
|
||||
return 0; /* don't error out... */
|
||||
|
||||
CONTACTS_CACHE = fill_contacts_cache ();
|
||||
CONTACTS_CACHE = fill_contacts_cache();
|
||||
|
||||
g_test_add_func ("/mu-cmd-cfind/test-mu-cfind-plain", test_mu_cfind_plain);
|
||||
g_test_add_func ("/mu-cmd-cfind/test-mu-cfind-bbdb", test_mu_cfind_bbdb);
|
||||
g_test_add_func ("/mu-cmd-cfind/test-mu-cfind-wl", test_mu_cfind_wl);
|
||||
g_test_add_func ("/mu-cmd-cfind/test-mu-cfind-mutt-alias",
|
||||
test_mu_cfind_mutt_alias);
|
||||
g_test_add_func ("/mu-cmd-cfind/test-mu-cfind-mutt-ab",
|
||||
test_mu_cfind_mutt_ab);
|
||||
g_test_add_func ("/mu-cmd-cfind/test-mu-cfind-org-contact",
|
||||
test_mu_cfind_org_contact);
|
||||
g_test_add_func ("/mu-cmd-cfind/test-mu-cfind-csv",
|
||||
test_mu_cfind_csv);
|
||||
g_test_add_func("/mu-cmd-cfind/test-mu-cfind-plain", test_mu_cfind_plain);
|
||||
g_test_add_func("/mu-cmd-cfind/test-mu-cfind-bbdb", test_mu_cfind_bbdb);
|
||||
g_test_add_func("/mu-cmd-cfind/test-mu-cfind-wl", test_mu_cfind_wl);
|
||||
g_test_add_func("/mu-cmd-cfind/test-mu-cfind-mutt-alias", test_mu_cfind_mutt_alias);
|
||||
g_test_add_func("/mu-cmd-cfind/test-mu-cfind-mutt-ab", test_mu_cfind_mutt_ab);
|
||||
g_test_add_func("/mu-cmd-cfind/test-mu-cfind-org-contact", test_mu_cfind_org_contact);
|
||||
g_test_add_func("/mu-cmd-cfind/test-mu-cfind-csv", 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),
|
||||
(GLogFunc)black_hole, NULL);
|
||||
g_log_set_handler(NULL,
|
||||
(GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_LEVEL_WARNING |
|
||||
G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION),
|
||||
(GLogFunc)black_hole,
|
||||
NULL);
|
||||
|
||||
rv = g_test_run ();
|
||||
rv = g_test_run();
|
||||
|
||||
g_free (CONTACTS_CACHE);
|
||||
g_free(CONTACTS_CACHE);
|
||||
CONTACTS_CACHE = NULL;
|
||||
|
||||
return rv;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -42,24 +42,24 @@ static std::string DB_PATH1;
|
||||
static std::string DB_PATH2;
|
||||
|
||||
static std::string
|
||||
make_database (const std::string& testdir)
|
||||
make_database(const std::string& testdir)
|
||||
{
|
||||
char *tmpdir{test_mu_common_get_random_tmpdir()};
|
||||
const auto cmdline{
|
||||
format("/bin/sh -c '"
|
||||
"%s init --muhome=%s --maildir=%s --quiet ; "
|
||||
"%s index --muhome=%s --quiet'",
|
||||
MU_PROGRAM, tmpdir, testdir.c_str(),
|
||||
MU_PROGRAM, tmpdir)};
|
||||
|
||||
char* tmpdir{test_mu_common_get_random_tmpdir()};
|
||||
const auto cmdline{format("/bin/sh -c '"
|
||||
"%s init --muhome=%s --maildir=%s --quiet ; "
|
||||
"%s index --muhome=%s --quiet'",
|
||||
MU_PROGRAM,
|
||||
tmpdir,
|
||||
testdir.c_str(),
|
||||
MU_PROGRAM,
|
||||
tmpdir)};
|
||||
|
||||
if (g_test_verbose())
|
||||
g_printerr ("\n%s\n", cmdline.c_str());
|
||||
g_printerr("\n%s\n", cmdline.c_str());
|
||||
|
||||
g_assert (g_spawn_command_line_sync (cmdline.c_str(), NULL, NULL,
|
||||
NULL, NULL));
|
||||
auto xpath= g_strdup_printf ("%s%c%s", tmpdir, G_DIR_SEPARATOR, "xapian");
|
||||
g_free (tmpdir);
|
||||
g_assert(g_spawn_command_line_sync(cmdline.c_str(), NULL, NULL, NULL, NULL));
|
||||
auto xpath = g_strdup_printf("%s%c%s", tmpdir, G_DIR_SEPARATOR, "xapian");
|
||||
g_free(tmpdir);
|
||||
|
||||
std::string dbpath{xpath};
|
||||
g_free(xpath);
|
||||
@ -67,518 +67,476 @@ make_database (const std::string& testdir)
|
||||
return dbpath;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
assert_no_dups (const QueryResults& qres)
|
||||
assert_no_dups(const QueryResults& qres)
|
||||
{
|
||||
std::unordered_set<std::string> msgid_set, path_set;
|
||||
std::unordered_set<std::string> msgid_set, path_set;
|
||||
|
||||
for (auto&& mi: qres) {
|
||||
g_assert_true(msgid_set.find(mi.message_id().value()) == msgid_set.end());
|
||||
g_assert_true(path_set.find(mi.path().value()) == path_set.end());
|
||||
for (auto&& mi : qres) {
|
||||
g_assert_true(msgid_set.find(mi.message_id().value()) == msgid_set.end());
|
||||
g_assert_true(path_set.find(mi.path().value()) == path_set.end());
|
||||
|
||||
path_set.emplace(*mi.path());
|
||||
msgid_set.emplace(*mi.message_id());
|
||||
path_set.emplace(*mi.path());
|
||||
msgid_set.emplace(*mi.message_id());
|
||||
|
||||
g_assert_false(msgid_set.find(mi.message_id().value()) == msgid_set.end());
|
||||
g_assert_false(path_set.find(mi.path().value()) == path_set.end());
|
||||
}
|
||||
g_assert_false(msgid_set.find(mi.message_id().value()) == msgid_set.end());
|
||||
g_assert_false(path_set.find(mi.path().value()) == path_set.end());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* note: this also *moves the iter* */
|
||||
static size_t
|
||||
run_and_count_matches (const std::string& xpath, const std::string& expr,
|
||||
Mu::QueryFlags flags = Mu::QueryFlags::None)
|
||||
run_and_count_matches(const std::string& xpath,
|
||||
const std::string& expr,
|
||||
Mu::QueryFlags flags = Mu::QueryFlags::None)
|
||||
{
|
||||
Mu::Store store{xpath};
|
||||
Mu::Query query{store};
|
||||
|
||||
if (g_test_verbose()) {
|
||||
std::cout << "==> mquery: " << query.parse (expr, false) << "\n";
|
||||
std::cout << "==> xquery: " << query.parse (expr, true) << "\n";
|
||||
std::cout << "==> mquery: " << query.parse(expr, false) << "\n";
|
||||
std::cout << "==> xquery: " << query.parse(expr, true) << "\n";
|
||||
}
|
||||
|
||||
Mu::allow_warnings();
|
||||
|
||||
auto qres{query.run (expr, MU_MSG_FIELD_ID_NONE, flags)};
|
||||
g_assert_true (!!qres);
|
||||
assert_no_dups (*qres);
|
||||
auto qres{query.run(expr, MU_MSG_FIELD_ID_NONE, flags)};
|
||||
g_assert_true(!!qres);
|
||||
assert_no_dups(*qres);
|
||||
|
||||
return qres->size();
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *query;
|
||||
size_t count; /* expected number of matches */
|
||||
typedef struct {
|
||||
const char* query;
|
||||
size_t count; /* expected number of matches */
|
||||
} QResults;
|
||||
|
||||
static void
|
||||
test_mu_query_01 (void)
|
||||
test_mu_query_01(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
QResults queries[] = {
|
||||
{ "basic", 3 },
|
||||
{ "question", 5 },
|
||||
{ "thanks", 2 },
|
||||
{ "html", 4 },
|
||||
{ "subject:exception", 1 },
|
||||
{ "exception", 1 },
|
||||
{ "subject:A&B", 1 },
|
||||
{ "A&B", 1 },
|
||||
{ "subject:elisp", 1 },
|
||||
{ "html AND contains", 1 },
|
||||
{ "html and contains", 1 },
|
||||
{ "from:pepernoot", 0 },
|
||||
{ "foo:pepernoot", 0 },
|
||||
{ "funky", 1 },
|
||||
{ "fünkÿ", 1 },
|
||||
// { "", 18 },
|
||||
{ "msgid:abcd$efgh@example.com", 1},
|
||||
{ "i:abcd$efgh@example.com", 1},
|
||||
{"basic", 3},
|
||||
{"question", 5},
|
||||
{"thanks", 2},
|
||||
{"html", 4},
|
||||
{"subject:exception", 1},
|
||||
{"exception", 1},
|
||||
{"subject:A&B", 1},
|
||||
{"A&B", 1},
|
||||
{"subject:elisp", 1},
|
||||
{"html AND contains", 1},
|
||||
{"html and contains", 1},
|
||||
{"from:pepernoot", 0},
|
||||
{"foo:pepernoot", 0},
|
||||
{"funky", 1},
|
||||
{"fünkÿ", 1},
|
||||
// { "", 18 },
|
||||
{"msgid:abcd$efgh@example.com", 1},
|
||||
{"i:abcd$efgh@example.com", 1},
|
||||
};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i)
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH1,
|
||||
queries[i].query),
|
||||
==, queries[i].count);
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
|
||||
static void
|
||||
test_mu_query_02 (void)
|
||||
test_mu_query_02(void)
|
||||
{
|
||||
const char* q;
|
||||
q = "i:f7ccd24b0808061357t453f5962w8b61f9a453b684d0@mail.gmail.com";
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH1, q), ==, 1);
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH1, q), ==, 1);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_mu_query_03 (void)
|
||||
test_mu_query_03(void)
|
||||
{
|
||||
int i;
|
||||
QResults queries[] = {
|
||||
{ "ploughed", 1},
|
||||
{ "i:3BE9E6535E3029448670913581E7A1A20D852173@"
|
||||
"emss35m06.us.lmco.com", 1},
|
||||
{ "i:!&!AAAAAAAAAYAAAAAAAAAOH1+8mkk+lLn7Gg5fke7"
|
||||
"FbCgAAAEAAAAJ7eBDgcactKhXL6r8cEnJ8BAAAAAA==@"
|
||||
"example.com", 1},
|
||||
int i;
|
||||
QResults queries[] = {{"ploughed", 1},
|
||||
{"i:3BE9E6535E3029448670913581E7A1A20D852173@"
|
||||
"emss35m06.us.lmco.com",
|
||||
1},
|
||||
{"i:!&!AAAAAAAAAYAAAAAAAAAOH1+8mkk+lLn7Gg5fke7"
|
||||
"FbCgAAAEAAAAJ7eBDgcactKhXL6r8cEnJ8BAAAAAA==@"
|
||||
"example.com",
|
||||
1},
|
||||
|
||||
/* subsets of the words in the subject should match */
|
||||
{ "s:gcc include search order" , 1},
|
||||
{ "s:gcc include search" , 1},
|
||||
{ "s:search order" , 1},
|
||||
{ "s:include" , 1},
|
||||
/* subsets of the words in the subject should match */
|
||||
{"s:gcc include search order", 1},
|
||||
{"s:gcc include search", 1},
|
||||
{"s:search order", 1},
|
||||
{"s:include", 1},
|
||||
|
||||
{ "s:lisp", 1},
|
||||
{ "s:LISP", 1},
|
||||
{"s:lisp", 1},
|
||||
{"s:LISP", 1},
|
||||
|
||||
/* { "s:\"Re: Learning LISP; Scheme vs elisp.\"", 1}, */
|
||||
/* { "subject:Re: Learning LISP; Scheme vs elisp.", 1}, */
|
||||
/* { "subject:\"Re: Learning LISP; Scheme vs elisp.\"", 1}, */
|
||||
{ "to:help-gnu-emacs@gnu.org", 4},
|
||||
{ "t:help-gnu-emacs", 4},
|
||||
{ "flag:flagged", 1}
|
||||
};
|
||||
/* { "s:\"Re: Learning LISP; Scheme vs elisp.\"", 1}, */
|
||||
/* { "subject:Re: Learning LISP; Scheme vs elisp.", 1}, */
|
||||
/* { "subject:\"Re: Learning LISP; Scheme vs elisp.\"", 1}, */
|
||||
{"to:help-gnu-emacs@gnu.org", 4},
|
||||
{"t:help-gnu-emacs", 4},
|
||||
{"flag:flagged", 1}};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i)
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH1,
|
||||
queries[i].query),
|
||||
==, queries[i].count);
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_mu_query_04 (void)
|
||||
test_mu_query_04(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
QResults queries[] = {
|
||||
{ "frodo@example.com", 1},
|
||||
{ "f:frodo@example.com", 1},
|
||||
{ "f:Frodo Baggins", 1},
|
||||
{ "bilbo@anotherexample.com", 1},
|
||||
{ "t:bilbo@anotherexample.com", 1},
|
||||
{ "t:bilbo", 1},
|
||||
{ "f:bilbo", 0},
|
||||
{ "baggins", 1},
|
||||
{ "prio:h", 1},
|
||||
{ "prio:high", 1},
|
||||
{ "prio:normal", 11},
|
||||
{ "prio:l", 7},
|
||||
{ "not prio:l", 12},
|
||||
{"frodo@example.com", 1},
|
||||
{"f:frodo@example.com", 1},
|
||||
{"f:Frodo Baggins", 1},
|
||||
{"bilbo@anotherexample.com", 1},
|
||||
{"t:bilbo@anotherexample.com", 1},
|
||||
{"t:bilbo", 1},
|
||||
{"f:bilbo", 0},
|
||||
{"baggins", 1},
|
||||
{"prio:h", 1},
|
||||
{"prio:high", 1},
|
||||
{"prio:normal", 11},
|
||||
{"prio:l", 7},
|
||||
{"not prio:l", 12},
|
||||
};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i)
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH1,
|
||||
queries[i].query),
|
||||
==, queries[i].count);
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_mu_query_logic (void)
|
||||
test_mu_query_logic(void)
|
||||
{
|
||||
int i;
|
||||
QResults queries[] = {
|
||||
{ "subject:gcc" , 1},
|
||||
{ "subject:lisp" , 1},
|
||||
{ "subject:gcc OR subject:lisp" , 2},
|
||||
{ "subject:gcc or subject:lisp" , 2},
|
||||
{ "subject:gcc AND subject:lisp" , 0},
|
||||
int i;
|
||||
QResults queries[] = {{"subject:gcc", 1},
|
||||
{"subject:lisp", 1},
|
||||
{"subject:gcc OR subject:lisp", 2},
|
||||
{"subject:gcc or subject:lisp", 2},
|
||||
{"subject:gcc AND subject:lisp", 0},
|
||||
|
||||
{ "subject:gcc OR (subject:scheme AND subject:elisp)" , 2},
|
||||
{ "(subject:gcc OR subject:scheme) AND subject:elisp" , 1}
|
||||
};
|
||||
{"subject:gcc OR (subject:scheme AND subject:elisp)", 2},
|
||||
{"(subject:gcc OR subject:scheme) AND subject:elisp", 1}};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i)
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH1,
|
||||
queries[i].query),
|
||||
==, queries[i].count);
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
|
||||
static void
|
||||
test_mu_query_accented_chars_01 (void)
|
||||
test_mu_query_accented_chars_01(void)
|
||||
{
|
||||
Store store{DB_PATH1};
|
||||
Query q{store};
|
||||
|
||||
auto qres{q.run("fünkÿ")};
|
||||
g_assert_true(!!qres);
|
||||
g_assert_false(qres->empty());
|
||||
auto qres{q.run("fünkÿ")};
|
||||
g_assert_true(!!qres);
|
||||
g_assert_false(qres->empty());
|
||||
|
||||
auto begin{qres->begin()};
|
||||
auto msg{begin.floating_msg()};
|
||||
auto begin{qres->begin()};
|
||||
auto msg{begin.floating_msg()};
|
||||
if (!msg) {
|
||||
g_warning ("error getting message");
|
||||
g_assert_not_reached ();
|
||||
g_warning("error getting message");
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
g_assert_cmpstr (mu_msg_get_subject(msg),==,
|
||||
"Greetings from Lothlórien");
|
||||
g_assert_cmpstr(mu_msg_get_subject(msg), ==, "Greetings from Lothlórien");
|
||||
/* TODO: fix this again */
|
||||
|
||||
auto summ = mu_str_summarize (mu_msg_get_body_text
|
||||
(msg, MU_MSG_OPTION_NONE), 5);
|
||||
g_assert_cmpstr (summ,==,
|
||||
"Let's write some fünkÿ text using umlauts. Foo.");
|
||||
g_free (summ);
|
||||
auto summ = mu_str_summarize(mu_msg_get_body_text(msg, MU_MSG_OPTION_NONE), 5);
|
||||
g_assert_cmpstr(summ, ==, "Let's write some fünkÿ text using umlauts. Foo.");
|
||||
g_free(summ);
|
||||
}
|
||||
|
||||
static void
|
||||
test_mu_query_accented_chars_02 (void)
|
||||
test_mu_query_accented_chars_02(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
QResults queries[] = {
|
||||
{ "f:mü", 1},
|
||||
{ "s:motörhead", 1},
|
||||
{ "t:Helmut", 1},
|
||||
{ "t:Kröger", 1},
|
||||
{ "s:MotorHeäD", 1},
|
||||
{ "queensryche", 1},
|
||||
{ "Queensrÿche", 1}
|
||||
};
|
||||
QResults queries[] = {{"f:mü", 1},
|
||||
{"s:motörhead", 1},
|
||||
{"t:Helmut", 1},
|
||||
{"t:Kröger", 1},
|
||||
{"s:MotorHeäD", 1},
|
||||
{"queensryche", 1},
|
||||
{"Queensrÿche", 1}};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i)
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH1,
|
||||
queries[i].query),
|
||||
==, queries[i].count);
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_mu_query_accented_chars_fraiche (void)
|
||||
test_mu_query_accented_chars_fraiche(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
QResults queries[] = {
|
||||
{ "crème fraîche", 1},
|
||||
{ "creme fraiche", 1},
|
||||
{ "fraîche crème", 1},
|
||||
{ "будланула", 1},
|
||||
{ "БУДЛАНУЛА", 1},
|
||||
{ "CRÈME FRAÎCHE", 1},
|
||||
{ "CREME FRAICHE", 1}
|
||||
};
|
||||
QResults queries[] = {{"crème fraîche", 1},
|
||||
{"creme fraiche", 1},
|
||||
{"fraîche crème", 1},
|
||||
{"будланула", 1},
|
||||
{"БУДЛАНУЛА", 1},
|
||||
{"CRÈME FRAÎCHE", 1},
|
||||
{"CREME FRAICHE", 1}};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i) {
|
||||
if (g_test_verbose())
|
||||
g_print("'%s'\n", queries[i].query);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("'%s'\n", queries[i].query);
|
||||
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH2,
|
||||
queries[i].query),
|
||||
==, queries[i].count);
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH2, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_mu_query_wildcards (void)
|
||||
test_mu_query_wildcards(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
QResults queries[] = {
|
||||
{ "f:mü", 1},
|
||||
{ "s:mo*", 1},
|
||||
{ "t:Helm*", 1},
|
||||
{ "queensryche", 1},
|
||||
{ "Queen*", 1},
|
||||
{"f:mü", 1},
|
||||
{"s:mo*", 1},
|
||||
{"t:Helm*", 1},
|
||||
{"queensryche", 1},
|
||||
{"Queen*", 1},
|
||||
};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i)
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH1,
|
||||
queries[i].query),
|
||||
==, queries[i].count);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_mu_query_dates_helsinki (void)
|
||||
{
|
||||
int i;
|
||||
const char *old_tz;
|
||||
|
||||
QResults queries[] = {
|
||||
{ "date:20080731..20080804", 5},
|
||||
{ "date:20080731..20080804 s:gcc", 1},
|
||||
{ "date:200808110803..now", 7},
|
||||
{ "date:200808110803..today",7},
|
||||
{ "date:200808110801..now", 7}
|
||||
};
|
||||
|
||||
old_tz = set_tz ("Europe/Helsinki");
|
||||
|
||||
const auto xpath{make_database (MU_TESTMAILDIR)};
|
||||
g_assert_false (xpath.empty());
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i)
|
||||
g_assert_cmpuint (run_and_count_matches
|
||||
(xpath, queries[i].query),
|
||||
==, queries[i].count);
|
||||
|
||||
set_tz (old_tz);
|
||||
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
|
||||
static void
|
||||
test_mu_query_dates_sydney (void)
|
||||
test_mu_query_dates_helsinki(void)
|
||||
{
|
||||
int i;
|
||||
const char *old_tz;
|
||||
QResults queries[] = {
|
||||
{ "date:20080731..20080804", 5},
|
||||
{ "date:20080731..20080804 s:gcc", 1},
|
||||
{ "date:200808110803..now", 7},
|
||||
{ "date:200808110803..today", 7},
|
||||
{ "date:200808110801..now", 7}
|
||||
};
|
||||
int i;
|
||||
const char* old_tz;
|
||||
|
||||
old_tz = set_tz ("Australia/Sydney");
|
||||
QResults queries[] = {{"date:20080731..20080804", 5},
|
||||
{"date:20080731..20080804 s:gcc", 1},
|
||||
{"date:200808110803..now", 7},
|
||||
{"date:200808110803..today", 7},
|
||||
{"date:200808110801..now", 7}};
|
||||
|
||||
old_tz = set_tz("Europe/Helsinki");
|
||||
|
||||
const auto xpath{make_database(MU_TESTMAILDIR)};
|
||||
g_assert_false (xpath.empty());
|
||||
g_assert_false(xpath.empty());
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i)
|
||||
g_assert_cmpuint (run_and_count_matches
|
||||
(xpath, queries[i].query),
|
||||
==, queries[i].count);
|
||||
set_tz (old_tz);
|
||||
g_assert_cmpuint(run_and_count_matches(xpath, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
|
||||
set_tz(old_tz);
|
||||
}
|
||||
|
||||
static void
|
||||
test_mu_query_dates_la (void)
|
||||
test_mu_query_dates_sydney(void)
|
||||
{
|
||||
int i;
|
||||
const char *old_tz;
|
||||
int i;
|
||||
const char* old_tz;
|
||||
QResults queries[] = {{"date:20080731..20080804", 5},
|
||||
{"date:20080731..20080804 s:gcc", 1},
|
||||
{"date:200808110803..now", 7},
|
||||
{"date:200808110803..today", 7},
|
||||
{"date:200808110801..now", 7}};
|
||||
|
||||
QResults queries[] = {
|
||||
{ "date:20080731..20080804", 5},
|
||||
{ "date:2008-07-31..2008-08-04", 5},
|
||||
{ "date:20080804..20080731", 5},
|
||||
{ "date:20080731..20080804 s:gcc", 1},
|
||||
{ "date:200808110803..now", 6},
|
||||
{ "date:200808110803..today", 6},
|
||||
{ "date:200808110801..now", 6}
|
||||
};
|
||||
old_tz = set_tz("Australia/Sydney");
|
||||
|
||||
old_tz = set_tz ("America/Los_Angeles");
|
||||
const auto xpath{make_database(MU_TESTMAILDIR)};
|
||||
g_assert_false(xpath.empty());
|
||||
|
||||
const auto xpath = make_database (MU_TESTMAILDIR);
|
||||
g_assert_false (xpath.empty());
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i)
|
||||
g_assert_cmpuint(run_and_count_matches(xpath, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
set_tz(old_tz);
|
||||
}
|
||||
|
||||
static void
|
||||
test_mu_query_dates_la(void)
|
||||
{
|
||||
int i;
|
||||
const char* old_tz;
|
||||
|
||||
QResults queries[] = {{"date:20080731..20080804", 5},
|
||||
{"date:2008-07-31..2008-08-04", 5},
|
||||
{"date:20080804..20080731", 5},
|
||||
{"date:20080731..20080804 s:gcc", 1},
|
||||
{"date:200808110803..now", 6},
|
||||
{"date:200808110803..today", 6},
|
||||
{"date:200808110801..now", 6}};
|
||||
|
||||
old_tz = set_tz("America/Los_Angeles");
|
||||
|
||||
const auto xpath = make_database(MU_TESTMAILDIR);
|
||||
g_assert_false(xpath.empty());
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i) {
|
||||
/* g_print ("%s\n", queries[i].query); */
|
||||
g_assert_cmpuint (run_and_count_matches
|
||||
(xpath, queries[i].query),
|
||||
==, queries[i].count);
|
||||
g_assert_cmpuint(run_and_count_matches(xpath, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
|
||||
set_tz (old_tz);
|
||||
set_tz(old_tz);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
test_mu_query_sizes (void)
|
||||
test_mu_query_sizes(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
QResults queries[] = {
|
||||
{ "size:0b..2m", 19},
|
||||
{ "size:3b..2m", 19},
|
||||
{ "size:2k..4k", 4},
|
||||
{"size:0b..2m", 19},
|
||||
{"size:3b..2m", 19},
|
||||
{"size:2k..4k", 4},
|
||||
|
||||
{ "size:0b..2m", 19},
|
||||
{ "size:2m..0b", 19},
|
||||
{"size:0b..2m", 19},
|
||||
{"size:2m..0b", 19},
|
||||
};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i)
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH1,
|
||||
queries[i].query),
|
||||
==, queries[i].count);
|
||||
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_mu_query_attach (void)
|
||||
test_mu_query_attach(void)
|
||||
{
|
||||
int i;
|
||||
QResults queries[] = {
|
||||
{ "j:sittingbull.jpg", 1},
|
||||
{ "file:custer", 0},
|
||||
{ "file:custer.jpg", 1}
|
||||
};
|
||||
int i;
|
||||
QResults queries[] = {{"j:sittingbull.jpg", 1}, {"file:custer", 0}, {"file:custer.jpg", 1}};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i) {
|
||||
if (g_test_verbose())
|
||||
g_print ("query: %s\n", queries[i].query);
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH2,
|
||||
queries[i].query),
|
||||
==, queries[i].count);
|
||||
g_print("query: %s\n", queries[i].query);
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH2, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
test_mu_query_msgid (void)
|
||||
test_mu_query_msgid(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
QResults queries[] = {
|
||||
{ "i:CAHSaMxZ9rk5ASjqsbXizjTQuSk583=M6TORHz"
|
||||
"=bfogtmbGGs5A@mail.gmail.com", 1},
|
||||
{ "msgid:CAHSaMxZ9rk5ASjqsbXizjTQuSk583=M6TORHz="
|
||||
"bfogtmbGGs5A@mail.gmail.com", 1},
|
||||
{"i:CAHSaMxZ9rk5ASjqsbXizjTQuSk583=M6TORHz"
|
||||
"=bfogtmbGGs5A@mail.gmail.com",
|
||||
1},
|
||||
{"msgid:CAHSaMxZ9rk5ASjqsbXizjTQuSk583=M6TORHz="
|
||||
"bfogtmbGGs5A@mail.gmail.com",
|
||||
1},
|
||||
|
||||
};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i) {
|
||||
if (g_test_verbose())
|
||||
g_print ("query: %s\n", queries[i].query);
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH2,
|
||||
queries[i].query),
|
||||
==, queries[i].count);
|
||||
g_print("query: %s\n", queries[i].query);
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH2, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_mu_query_tags (void)
|
||||
test_mu_query_tags(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
QResults queries[] = {
|
||||
{ "x:paradise", 1},
|
||||
{ "tag:lost", 1},
|
||||
{ "tag:lost tag:paradise", 1},
|
||||
{ "tag:lost tag:horizon", 0},
|
||||
{ "tag:lost OR tag:horizon", 1},
|
||||
{ "x:paradise,lost", 0},
|
||||
{ "x:paradise AND x:lost", 1},
|
||||
{ "x:\\\\backslash", 1},
|
||||
{"x:paradise", 1},
|
||||
{"tag:lost", 1},
|
||||
{"tag:lost tag:paradise", 1},
|
||||
{"tag:lost tag:horizon", 0},
|
||||
{"tag:lost OR tag:horizon", 1},
|
||||
{"x:paradise,lost", 0},
|
||||
{"x:paradise AND x:lost", 1},
|
||||
{"x:\\\\backslash", 1},
|
||||
};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i)
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH2,
|
||||
queries[i].query),
|
||||
==, queries[i].count);
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH2, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
test_mu_query_wom_bat (void)
|
||||
test_mu_query_wom_bat(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
QResults queries[] = {
|
||||
{ "maildir:/wom_bat", 3},
|
||||
//{ "\"maildir:/wom bat\"", 3},
|
||||
// as expected, no longer works with new parser
|
||||
{"maildir:/wom_bat", 3},
|
||||
//{ "\"maildir:/wom bat\"", 3},
|
||||
// as expected, no longer works with new parser
|
||||
};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i)
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH2,
|
||||
queries[i].query),
|
||||
==, queries[i].count);
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH2, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
test_mu_query_signed_encrypted (void)
|
||||
test_mu_query_signed_encrypted(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
QResults queries[] = {
|
||||
{ "flag:encrypted", 2},
|
||||
{ "flag:signed", 2},
|
||||
{"flag:encrypted", 2},
|
||||
{"flag:signed", 2},
|
||||
};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i)
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH1,
|
||||
queries[i].query),
|
||||
==, queries[i].count);
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_mu_query_multi_to_cc (void)
|
||||
test_mu_query_multi_to_cc(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
QResults queries[] = {
|
||||
{ "to:a@example.com", 1},
|
||||
{ "cc:d@example.com", 1},
|
||||
{ "to:b@example.com", 1},
|
||||
{ "cc:e@example.com", 1},
|
||||
{ "cc:e@example.com AND cc:d@example.com", 1},
|
||||
{"to:a@example.com", 1},
|
||||
{"cc:d@example.com", 1},
|
||||
{"to:b@example.com", 1},
|
||||
{"cc:e@example.com", 1},
|
||||
{"cc:e@example.com AND cc:d@example.com", 1},
|
||||
};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i)
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH1,
|
||||
queries[i].query),
|
||||
==, queries[i].count);
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
|
||||
static void
|
||||
test_mu_query_tags_02 (void)
|
||||
test_mu_query_tags_02(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
QResults queries[] = {
|
||||
{ "x:paradise", 1},
|
||||
{ "tag:@NextActions", 1},
|
||||
{ "x:queensrÿche", 1},
|
||||
{ "tag:lost OR tag:operation*", 2},
|
||||
{"x:paradise", 1},
|
||||
{"tag:@NextActions", 1},
|
||||
{"x:queensrÿche", 1},
|
||||
{"tag:lost OR tag:operation*", 2},
|
||||
};
|
||||
|
||||
for (i = 0; i != G_N_ELEMENTS(queries); ++i) {
|
||||
g_assert_cmpuint (run_and_count_matches (DB_PATH2,
|
||||
queries[i].query),
|
||||
==, queries[i].count);
|
||||
g_assert_cmpuint(run_and_count_matches(DB_PATH2, queries[i].query),
|
||||
==,
|
||||
queries[i].count);
|
||||
}
|
||||
}
|
||||
|
||||
@ -588,87 +546,75 @@ test_mu_query_tags_02 (void)
|
||||
--related option doesn't work.
|
||||
*/
|
||||
static void
|
||||
test_mu_query_threads_compilation_error (void)
|
||||
test_mu_query_threads_compilation_error(void)
|
||||
{
|
||||
const auto xpath = make_database (MU_TESTMAILDIR);
|
||||
const auto xpath = make_database(MU_TESTMAILDIR);
|
||||
|
||||
g_assert_cmpuint (run_and_count_matches
|
||||
(xpath, "msgid:uwsireh25.fsf@one.dot.net"),
|
||||
==, 1);
|
||||
g_assert_cmpuint(run_and_count_matches(xpath, "msgid:uwsireh25.fsf@one.dot.net"), ==, 1);
|
||||
|
||||
g_assert_cmpuint (run_and_count_matches
|
||||
(xpath, "msgid:uwsireh25.fsf@one.dot.net",
|
||||
QueryFlags::IncludeRelated),
|
||||
==, 3);
|
||||
g_assert_cmpuint(run_and_count_matches(xpath,
|
||||
"msgid:uwsireh25.fsf@one.dot.net",
|
||||
QueryFlags::IncludeRelated),
|
||||
==,
|
||||
3);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
int rv;
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
DB_PATH1 = make_database (MU_TESTMAILDIR);
|
||||
g_assert_false (DB_PATH1.empty());
|
||||
DB_PATH1 = make_database(MU_TESTMAILDIR);
|
||||
g_assert_false(DB_PATH1.empty());
|
||||
|
||||
DB_PATH2 = make_database (MU_TESTMAILDIR2);
|
||||
g_assert_false (DB_PATH2.empty());
|
||||
DB_PATH2 = make_database(MU_TESTMAILDIR2);
|
||||
g_assert_false(DB_PATH2.empty());
|
||||
|
||||
g_test_add_func ("/mu-query/test-mu-query-01", test_mu_query_01);
|
||||
g_test_add_func ("/mu-query/test-mu-query-02", test_mu_query_02);
|
||||
g_test_add_func ("/mu-query/test-mu-query-03", test_mu_query_03);
|
||||
g_test_add_func ("/mu-query/test-mu-query-04", test_mu_query_04);
|
||||
g_test_add_func("/mu-query/test-mu-query-01", test_mu_query_01);
|
||||
g_test_add_func("/mu-query/test-mu-query-02", test_mu_query_02);
|
||||
g_test_add_func("/mu-query/test-mu-query-03", test_mu_query_03);
|
||||
g_test_add_func("/mu-query/test-mu-query-04", test_mu_query_04);
|
||||
|
||||
g_test_add_func ("/mu-query/test-mu-query-signed-encrypted",
|
||||
test_mu_query_signed_encrypted);
|
||||
g_test_add_func ("/mu-query/test-mu-query-multi-to-cc",
|
||||
test_mu_query_multi_to_cc);
|
||||
g_test_add_func ("/mu-query/test-mu-query-logic", test_mu_query_logic);
|
||||
g_test_add_func("/mu-query/test-mu-query-signed-encrypted", test_mu_query_signed_encrypted);
|
||||
g_test_add_func("/mu-query/test-mu-query-multi-to-cc", test_mu_query_multi_to_cc);
|
||||
g_test_add_func("/mu-query/test-mu-query-logic", test_mu_query_logic);
|
||||
|
||||
g_test_add_func ("/mu-query/test-mu-query-accented-chars-1",
|
||||
test_mu_query_accented_chars_01);
|
||||
g_test_add_func ("/mu-query/test-mu-query-accented-chars-2",
|
||||
test_mu_query_accented_chars_02);
|
||||
g_test_add_func ("/mu-query/test-mu-query-accented-chars-fraiche",
|
||||
test_mu_query_accented_chars_fraiche);
|
||||
g_test_add_func("/mu-query/test-mu-query-accented-chars-1",
|
||||
test_mu_query_accented_chars_01);
|
||||
g_test_add_func("/mu-query/test-mu-query-accented-chars-2",
|
||||
test_mu_query_accented_chars_02);
|
||||
g_test_add_func("/mu-query/test-mu-query-accented-chars-fraiche",
|
||||
test_mu_query_accented_chars_fraiche);
|
||||
|
||||
g_test_add_func ("/mu-query/test-mu-query-msgid",
|
||||
test_mu_query_msgid);
|
||||
g_test_add_func("/mu-query/test-mu-query-msgid", test_mu_query_msgid);
|
||||
|
||||
g_test_add_func ("/mu-query/test-mu-query-wom-bat",
|
||||
test_mu_query_wom_bat);
|
||||
g_test_add_func("/mu-query/test-mu-query-wom-bat", test_mu_query_wom_bat);
|
||||
|
||||
g_test_add_func ("/mu-query/test-mu-query-wildcards",
|
||||
test_mu_query_wildcards);
|
||||
g_test_add_func ("/mu-query/test-mu-query-sizes",
|
||||
test_mu_query_sizes);
|
||||
g_test_add_func("/mu-query/test-mu-query-wildcards", test_mu_query_wildcards);
|
||||
g_test_add_func("/mu-query/test-mu-query-sizes", test_mu_query_sizes);
|
||||
|
||||
g_test_add_func ("/mu-query/test-mu-query-dates-helsinki",
|
||||
test_mu_query_dates_helsinki);
|
||||
g_test_add_func ("/mu-query/test-mu-query-dates-sydney",
|
||||
test_mu_query_dates_sydney);
|
||||
g_test_add_func ("/mu-query/test-mu-query-dates-la",
|
||||
test_mu_query_dates_la);
|
||||
g_test_add_func("/mu-query/test-mu-query-dates-helsinki", test_mu_query_dates_helsinki);
|
||||
g_test_add_func("/mu-query/test-mu-query-dates-sydney", test_mu_query_dates_sydney);
|
||||
g_test_add_func("/mu-query/test-mu-query-dates-la", test_mu_query_dates_la);
|
||||
|
||||
g_test_add_func ("/mu-query/test-mu-query-attach",
|
||||
test_mu_query_attach);
|
||||
g_test_add_func ("/mu-query/test-mu-query-tags",
|
||||
test_mu_query_tags);
|
||||
g_test_add_func ("/mu-query/test-mu-query-tags_02",
|
||||
test_mu_query_tags_02);
|
||||
g_test_add_func("/mu-query/test-mu-query-attach", test_mu_query_attach);
|
||||
g_test_add_func("/mu-query/test-mu-query-tags", test_mu_query_tags);
|
||||
g_test_add_func("/mu-query/test-mu-query-tags_02", test_mu_query_tags_02);
|
||||
|
||||
g_test_add_func ("/mu-query/test-mu-query-threads-compilation-error",
|
||||
test_mu_query_threads_compilation_error);
|
||||
g_test_add_func("/mu-query/test-mu-query-threads-compilation-error",
|
||||
test_mu_query_threads_compilation_error);
|
||||
|
||||
if (!g_test_verbose())
|
||||
g_log_set_handler (NULL,
|
||||
(GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL|
|
||||
G_LOG_LEVEL_WARNING|G_LOG_FLAG_RECURSION),
|
||||
(GLogFunc)black_hole, NULL);
|
||||
rv = g_test_run ();
|
||||
g_log_set_handler(NULL,
|
||||
(GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL |
|
||||
G_LOG_LEVEL_WARNING | G_LOG_FLAG_RECURSION),
|
||||
(GLogFunc)black_hole,
|
||||
NULL);
|
||||
rv = g_test_run();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user