* minor changes, trailing whitespace fixes
This commit is contained in:
@ -64,22 +64,22 @@ upgrade_warning (void)
|
||||
MU_XAPIAN_DB_VERSION);
|
||||
g_message ("please run 'mu index --rebuild' (see the man page)");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static gboolean
|
||||
print_xapian_query (MuQuery *xapian, const gchar *query, size_t *count)
|
||||
{
|
||||
char *querystr;
|
||||
GError *err;
|
||||
|
||||
|
||||
err = NULL;
|
||||
|
||||
|
||||
querystr = mu_query_as_string (xapian, query, &err);
|
||||
if (!querystr) {
|
||||
g_warning ("error: %s", err->message);
|
||||
g_error_free (err);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
g_print ("%s\n", querystr);
|
||||
g_free (querystr);
|
||||
@ -93,14 +93,14 @@ static MuMsgFieldId
|
||||
sort_field_from_string (const char* fieldstr)
|
||||
{
|
||||
MuMsgFieldId mfid;
|
||||
|
||||
|
||||
mfid = mu_msg_field_id_from_name (fieldstr, FALSE);
|
||||
|
||||
/* not found? try a shortcut */
|
||||
if (mfid == MU_MSG_FIELD_ID_NONE &&
|
||||
strlen(fieldstr) == 1)
|
||||
mfid = mu_msg_field_id_from_shortcut(fieldstr[0],
|
||||
FALSE);
|
||||
FALSE);
|
||||
if (mfid == MU_MSG_FIELD_ID_NONE)
|
||||
g_warning ("not a valid sort field: '%s'\n",
|
||||
fieldstr);
|
||||
@ -115,7 +115,7 @@ output_query_results (MuMsgIter *iter, MuConfig *opts, size_t *count)
|
||||
case MU_CONFIG_FORMAT_LINKS:
|
||||
return output_links (iter, opts->linksdir, opts->clearlinks,
|
||||
count);
|
||||
case MU_CONFIG_FORMAT_PLAIN:
|
||||
case MU_CONFIG_FORMAT_PLAIN:
|
||||
return output_plain (iter, opts->fields, opts->summary,
|
||||
opts->threads, opts->color,
|
||||
opts->include_unreadable,
|
||||
@ -124,7 +124,7 @@ output_query_results (MuMsgIter *iter, MuConfig *opts, size_t *count)
|
||||
return output_xml (iter, opts->include_unreadable, count);
|
||||
case MU_CONFIG_FORMAT_SEXP:
|
||||
return output_sexp (iter, opts->threads,
|
||||
opts->include_unreadable, count);
|
||||
opts->include_unreadable, count);
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
@ -138,7 +138,7 @@ run_query (MuQuery *xapian, const gchar *query, MuConfig *opts, size_t *count)
|
||||
GError *err;
|
||||
MuMsgIter *iter;
|
||||
MuMsgFieldId sortid;
|
||||
|
||||
|
||||
sortid = MU_MSG_FIELD_ID_NONE;
|
||||
if (opts->sortfield) {
|
||||
sortid = sort_field_from_string (opts->sortfield);
|
||||
@ -147,7 +147,7 @@ run_query (MuQuery *xapian, const gchar *query, MuConfig *opts, size_t *count)
|
||||
}
|
||||
|
||||
err = NULL;
|
||||
iter = mu_query_run (xapian, query, opts->threads, sortid,
|
||||
iter = mu_query_run (xapian, query, opts->threads, sortid,
|
||||
opts->descending ? FALSE : TRUE,
|
||||
&err);
|
||||
if (!iter) {
|
||||
@ -158,7 +158,7 @@ run_query (MuQuery *xapian, const gchar *query, MuConfig *opts, size_t *count)
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static gboolean
|
||||
process_query (MuQuery *xapian, const gchar *query, MuConfig *opts,
|
||||
@ -166,16 +166,16 @@ process_query (MuQuery *xapian, const gchar *query, MuConfig *opts,
|
||||
{
|
||||
MuMsgIter *iter;
|
||||
gboolean rv;
|
||||
|
||||
|
||||
iter = run_query (xapian, query, opts, count);
|
||||
if (!iter)
|
||||
return FALSE;
|
||||
|
||||
|
||||
rv = output_query_results (iter, opts, count);
|
||||
|
||||
|
||||
if (rv && count && *count == 0)
|
||||
g_warning ("no matching messages found");
|
||||
|
||||
|
||||
mu_msg_iter_destroy (iter);
|
||||
|
||||
return rv;
|
||||
@ -189,14 +189,14 @@ exec_cmd (const char *path, const char *cmd)
|
||||
GError *err;
|
||||
char *cmdline, *escpath;
|
||||
gboolean rv;
|
||||
|
||||
|
||||
if (access (path, R_OK) != 0) {
|
||||
g_warning ("cannot read %s: %s", path, strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
escpath = g_strescape (path, NULL);
|
||||
|
||||
|
||||
cmdline = g_strdup_printf ("%s %s", cmd, escpath);
|
||||
err = NULL;
|
||||
rv = g_spawn_command_line_sync (cmdline, NULL, NULL,
|
||||
@ -221,7 +221,7 @@ exec_cmd_on_query (MuQuery *xapian, const gchar *query, MuConfig *opts,
|
||||
{
|
||||
MuMsgIter *iter;
|
||||
gboolean rv;
|
||||
|
||||
|
||||
if (!(iter = run_query (xapian, query, opts, count)))
|
||||
return FALSE;
|
||||
|
||||
@ -232,10 +232,10 @@ exec_cmd_on_query (MuQuery *xapian, const gchar *query, MuConfig *opts,
|
||||
if (rv)
|
||||
++*count;
|
||||
}
|
||||
|
||||
|
||||
if (rv && count && *count == 0)
|
||||
g_warning ("no matching messages found");
|
||||
|
||||
|
||||
mu_msg_iter_destroy (iter);
|
||||
|
||||
return rv;
|
||||
@ -258,7 +258,7 @@ format_params_valid (MuConfig *opts)
|
||||
opts->formatstr ? opts->formatstr : "<none>");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (opts->format == MU_CONFIG_FORMAT_LINKS && !opts->linksdir) {
|
||||
g_warning ("missing --linksdir argument");
|
||||
return FALSE;
|
||||
@ -276,15 +276,15 @@ static gboolean
|
||||
query_params_valid (MuConfig *opts)
|
||||
{
|
||||
const gchar *xpath;
|
||||
|
||||
|
||||
xpath = mu_runtime_path (MU_RUNTIME_PATH_XAPIANDB);
|
||||
|
||||
|
||||
if (mu_util_check_dir (xpath, TRUE, FALSE))
|
||||
return TRUE;
|
||||
|
||||
|
||||
g_warning ("'%s' is not a readable Xapian directory\n", xpath);
|
||||
g_message ("did you run 'mu index'?");
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -294,20 +294,20 @@ resolve_bookmark (MuConfig *opts)
|
||||
MuBookmarks *bm;
|
||||
char* val;
|
||||
const gchar *bmfile;
|
||||
|
||||
|
||||
bmfile = mu_runtime_path (MU_RUNTIME_PATH_BOOKMARKS);
|
||||
bm = mu_bookmarks_new (bmfile);
|
||||
if (!bm) {
|
||||
g_warning ("failed to open bookmarks file '%s'", bmfile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
val = (gchar*)mu_bookmarks_lookup (bm, opts->bookmark);
|
||||
if (!val)
|
||||
|
||||
val = (gchar*)mu_bookmarks_lookup (bm, opts->bookmark);
|
||||
if (!val)
|
||||
g_warning ("bookmark '%s' not found", opts->bookmark);
|
||||
else
|
||||
val = g_strdup (val);
|
||||
|
||||
|
||||
mu_bookmarks_destroy (bm);
|
||||
|
||||
return val;
|
||||
@ -331,7 +331,7 @@ get_query (MuConfig *opts)
|
||||
if (!bookmarkval)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
query = mu_util_str_from_strv ((const gchar**)&opts->params[1]);
|
||||
if (bookmarkval) {
|
||||
gchar *tmp;
|
||||
@ -341,20 +341,20 @@ get_query (MuConfig *opts)
|
||||
}
|
||||
|
||||
g_free (bookmarkval);
|
||||
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
db_is_ready (const char *xpath)
|
||||
{
|
||||
if (mu_util_xapian_is_empty (xpath)) {
|
||||
{
|
||||
if (mu_store_database_is_empty (xpath)) {
|
||||
g_warning ("database is empty; use 'mu index' to "
|
||||
"add messages");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (mu_util_xapian_needs_upgrade (xpath)) {
|
||||
|
||||
if (mu_store_database_needs_upgrade (xpath)) {
|
||||
upgrade_warning ();
|
||||
return FALSE;
|
||||
}
|
||||
@ -368,13 +368,13 @@ get_query_obj (void)
|
||||
GError *err;
|
||||
const char* xpath;
|
||||
MuQuery *mquery;
|
||||
|
||||
|
||||
xpath = mu_runtime_path (MU_RUNTIME_PATH_XAPIANDB);
|
||||
if (!db_is_ready(xpath)) {
|
||||
g_warning ("database '%s' is not ready", xpath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
err = NULL;
|
||||
mquery = mu_query_new (xpath, &err);
|
||||
if (!mquery) {
|
||||
@ -392,7 +392,7 @@ static gboolean
|
||||
create_linksdir_maybe (const char *linksdir, gboolean clearlinks)
|
||||
{
|
||||
GError *err;
|
||||
|
||||
|
||||
err = NULL;
|
||||
if (access (linksdir, F_OK) != 0) {
|
||||
if (!mu_maildir_mkdir (linksdir, 0700, TRUE, &err))
|
||||
@ -402,25 +402,25 @@ create_linksdir_maybe (const char *linksdir, gboolean clearlinks)
|
||||
goto fail;
|
||||
|
||||
return TRUE;
|
||||
|
||||
|
||||
fail:
|
||||
if (err) {
|
||||
g_warning ("%s", err->message ? err->message : "unknown error");
|
||||
g_error_free (err);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
link_message (const char *src, const char *destdir)
|
||||
{
|
||||
GError *err;
|
||||
|
||||
|
||||
if (access (src, R_OK) != 0) {
|
||||
if (errno == ENOENT)
|
||||
g_warning ("cannot find source message %s", src);
|
||||
else
|
||||
else
|
||||
g_warning ("cannot read source message %s: %s", src,
|
||||
strerror (errno));
|
||||
return FALSE;
|
||||
@ -433,9 +433,9 @@ link_message (const char *src, const char *destdir)
|
||||
err->message : "unknown error");
|
||||
g_error_free (err);
|
||||
}
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -448,40 +448,40 @@ output_links (MuMsgIter *iter, const char* linksdir,
|
||||
size_t mycount;
|
||||
gboolean errseen;
|
||||
MuMsgIter *myiter;
|
||||
|
||||
|
||||
g_return_val_if_fail (iter, FALSE);
|
||||
g_return_val_if_fail (linksdir, FALSE);
|
||||
g_return_val_if_fail (linksdir, FALSE);
|
||||
|
||||
/* note: we create the linksdir even if there are no search results */
|
||||
if (!create_linksdir_maybe (linksdir, clearlinks))
|
||||
return FALSE;
|
||||
|
||||
|
||||
for (myiter = iter, errseen = FALSE, mycount = 0; !mu_msg_iter_is_done (myiter);
|
||||
mu_msg_iter_next (myiter)) {
|
||||
|
||||
MuMsg *msg;
|
||||
const char* path;
|
||||
|
||||
|
||||
msg = mu_msg_iter_get_msg (iter, NULL); /* don't unref */
|
||||
if (!msg)
|
||||
return FALSE;
|
||||
|
||||
|
||||
path = mu_msg_get_path (msg);
|
||||
if (!access (path, R_OK)) /* only link to readable */
|
||||
continue;
|
||||
|
||||
|
||||
if (!link_message (path, linksdir))
|
||||
errseen = TRUE;
|
||||
else
|
||||
++mycount;
|
||||
}
|
||||
|
||||
if (errseen)
|
||||
if (errseen)
|
||||
g_warning ("error linking some of the messages");
|
||||
|
||||
if (count)
|
||||
*count = mycount;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -494,7 +494,7 @@ ansi_color_maybe (MuMsgFieldId mfid, gboolean color)
|
||||
|
||||
if (!color)
|
||||
return; /* nothing to do */
|
||||
|
||||
|
||||
switch (mfid) {
|
||||
|
||||
case MU_MSG_FIELD_ID_FROM:
|
||||
@ -507,7 +507,7 @@ ansi_color_maybe (MuMsgFieldId mfid, gboolean color)
|
||||
|
||||
case MU_MSG_FIELD_ID_SUBJECT:
|
||||
ansi = MU_COLOR_GREEN; break;
|
||||
|
||||
|
||||
case MU_MSG_FIELD_ID_DATE:
|
||||
ansi = MU_COLOR_MAGENTA; break;
|
||||
|
||||
@ -527,9 +527,9 @@ ansi_reset_maybe (MuMsgFieldId mfid, gboolean color)
|
||||
{
|
||||
if (!color)
|
||||
return; /* nothing to do */
|
||||
|
||||
|
||||
fputs (MU_COLOR_DEFAULT, stdout);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -537,15 +537,15 @@ static const char*
|
||||
display_field (MuMsg *msg, MuMsgFieldId mfid)
|
||||
{
|
||||
gint64 val;
|
||||
|
||||
|
||||
switch (mu_msg_field_type(mfid)) {
|
||||
case MU_MSG_FIELD_TYPE_STRING: {
|
||||
const gchar *str;
|
||||
str = mu_msg_get_field_string (msg, mfid);
|
||||
return str ? str : "";
|
||||
}
|
||||
}
|
||||
case MU_MSG_FIELD_TYPE_INT:
|
||||
|
||||
|
||||
if (mfid == MU_MSG_FIELD_ID_PRIO) {
|
||||
val = mu_msg_get_field_numeric (msg, mfid);
|
||||
return mu_msg_prio_name ((MuMsgPrio)val);
|
||||
@ -554,12 +554,12 @@ display_field (MuMsg *msg, MuMsgFieldId mfid)
|
||||
return mu_str_flags_s ((MuFlags)val);
|
||||
} else /* as string */
|
||||
return mu_msg_get_field_string (msg, mfid);
|
||||
|
||||
case MU_MSG_FIELD_TYPE_TIME_T:
|
||||
|
||||
case MU_MSG_FIELD_TYPE_TIME_T:
|
||||
val = mu_msg_get_field_numeric (msg, mfid);
|
||||
return mu_date_str_s ("%c", (time_t)val);
|
||||
|
||||
case MU_MSG_FIELD_TYPE_BYTESIZE:
|
||||
case MU_MSG_FIELD_TYPE_BYTESIZE:
|
||||
val = mu_msg_get_field_numeric (msg, mfid);
|
||||
return mu_str_size_s ((unsigned)val);
|
||||
default:
|
||||
@ -575,7 +575,7 @@ print_summary (MuMsg *msg)
|
||||
char *summ;
|
||||
|
||||
const guint SUMMARY_LEN = 5; /* summary based on first 5
|
||||
* lines */
|
||||
* lines */
|
||||
err = NULL;
|
||||
|
||||
summ = mu_str_summarize (mu_msg_get_body_text(msg), SUMMARY_LEN);
|
||||
@ -591,14 +591,14 @@ thread_indent (MuMsgIter *iter)
|
||||
const char* threadpath;
|
||||
int i;
|
||||
gboolean is_root, first_child, empty_parent, is_dup;
|
||||
|
||||
|
||||
ti = mu_msg_iter_get_thread_info (iter);
|
||||
if (!ti) {
|
||||
g_warning ("cannot get thread-info for %s",
|
||||
mu_msg_get_subject(mu_msg_iter_get_msg(iter, NULL)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
threadpath = ti->threadpath;
|
||||
/* fputs (threadpath, stdout); */
|
||||
/* fputs (" ", stdout); */
|
||||
@ -607,15 +607,15 @@ thread_indent (MuMsgIter *iter)
|
||||
first_child = ti->prop & MU_MSG_ITER_THREAD_PROP_FIRST_CHILD;
|
||||
empty_parent = ti->prop & MU_MSG_ITER_THREAD_PROP_EMPTY_PARENT;
|
||||
is_dup = ti->prop & MU_MSG_ITER_THREAD_PROP_DUP;
|
||||
|
||||
|
||||
/* FIXME: count the colons... */
|
||||
for (i = 0; *threadpath; ++threadpath)
|
||||
i += (*threadpath == ':') ? 1 : 0;
|
||||
|
||||
|
||||
/* indent */
|
||||
while (i --> 0)
|
||||
fputs (" ", stdout);
|
||||
|
||||
|
||||
if (!is_root) {
|
||||
fputs (first_child ? "`" : "|", stdout);
|
||||
fputs (empty_parent ? "*> " : is_dup ? "=> " : "-> ", stdout);
|
||||
@ -630,7 +630,7 @@ output_plain_fields (MuMsg *msg, const char *fields,
|
||||
{
|
||||
const char* myfields;
|
||||
size_t len;
|
||||
|
||||
|
||||
for (myfields = fields, len = 0; *myfields; ++myfields) {
|
||||
|
||||
MuMsgFieldId mfid;
|
||||
@ -659,22 +659,22 @@ output_plain (MuMsgIter *iter, const char *fields, gboolean summary,
|
||||
{
|
||||
MuMsgIter *myiter;
|
||||
size_t mycount;
|
||||
|
||||
|
||||
g_return_val_if_fail (iter, FALSE);
|
||||
g_return_val_if_fail (fields, FALSE);
|
||||
|
||||
|
||||
for (myiter = iter, mycount = 0; !mu_msg_iter_is_done (myiter);
|
||||
mu_msg_iter_next (myiter)) {
|
||||
|
||||
size_t len;
|
||||
MuMsg *msg;
|
||||
|
||||
|
||||
msg = mu_msg_iter_get_msg (iter, NULL); /* don't unref */
|
||||
if (!msg) {
|
||||
g_warning ("can't get message");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* only return messages if they're actually
|
||||
* readable (ie, live also outside the database) */
|
||||
if (!include_unreadable && !mu_msg_is_readable (msg))
|
||||
@ -685,9 +685,9 @@ output_plain (MuMsgIter *iter, const char *fields, gboolean summary,
|
||||
ansi_color_maybe (MU_MSG_FIELD_ID_PRIO, color);
|
||||
if (threads)
|
||||
thread_indent (iter);
|
||||
|
||||
|
||||
len = output_plain_fields (msg, fields, color, threads);
|
||||
|
||||
|
||||
g_print (len > 0 ? "\n" : "");
|
||||
if (summary)
|
||||
print_summary (msg);
|
||||
@ -697,7 +697,7 @@ output_plain (MuMsgIter *iter, const char *fields, gboolean summary,
|
||||
|
||||
if (count)
|
||||
*count = mycount;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -705,11 +705,11 @@ static void
|
||||
print_attr_xml (const char* elm, const char *str)
|
||||
{
|
||||
gchar *esc;
|
||||
|
||||
|
||||
if (mu_str_is_empty(str))
|
||||
return; /* empty: don't include */
|
||||
|
||||
esc = g_markup_escape_text (str, -1);
|
||||
esc = g_markup_escape_text (str, -1);
|
||||
g_print ("\t\t<%s>%s</%s>\n", elm, esc, elm);
|
||||
g_free (esc);
|
||||
}
|
||||
@ -722,27 +722,27 @@ output_sexp (MuMsgIter *iter, gboolean threads,
|
||||
{
|
||||
MuMsgIter *myiter;
|
||||
size_t mycount;
|
||||
|
||||
|
||||
g_return_val_if_fail (iter, FALSE);
|
||||
|
||||
|
||||
for (myiter = iter, mycount = 0; !mu_msg_iter_is_done (myiter);
|
||||
mu_msg_iter_next (myiter)) {
|
||||
|
||||
MuMsg *msg;
|
||||
char *sexp;
|
||||
const MuMsgIterThreadInfo *ti;
|
||||
|
||||
|
||||
msg = mu_msg_iter_get_msg (iter, NULL); /* don't unref */
|
||||
if (!msg)
|
||||
return FALSE;
|
||||
|
||||
|
||||
/* only return messages if they're actually
|
||||
* readable (ie, live also outside the database) */
|
||||
if (!include_unreadable && !mu_msg_is_readable (msg))
|
||||
continue;
|
||||
|
||||
ti = threads ? mu_msg_iter_get_thread_info (iter) : NULL;
|
||||
|
||||
|
||||
sexp = mu_msg_to_sexp (msg, ti, TRUE);
|
||||
fputs (sexp, stdout);
|
||||
g_free (sexp);
|
||||
@ -750,10 +750,10 @@ output_sexp (MuMsgIter *iter, gboolean threads,
|
||||
++mycount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (count)
|
||||
*count = mycount;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -781,34 +781,34 @@ output_xml (MuMsgIter *iter, gboolean include_unreadable, size_t *count)
|
||||
{
|
||||
MuMsgIter *myiter;
|
||||
size_t mycount;
|
||||
|
||||
|
||||
g_return_val_if_fail (iter, FALSE);
|
||||
|
||||
g_print ("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
|
||||
g_print ("<messages>\n");
|
||||
|
||||
|
||||
for (myiter = iter, mycount = 0; !mu_msg_iter_is_done (myiter);
|
||||
mu_msg_iter_next (myiter)) {
|
||||
|
||||
MuMsg *msg;
|
||||
MuMsg *msg;
|
||||
msg = mu_msg_iter_get_msg (iter, NULL); /* don't unref */
|
||||
if (!msg)
|
||||
return FALSE;
|
||||
|
||||
|
||||
/* only return messages if they're actually
|
||||
* readable (ie, live also outside the database) */
|
||||
if (!include_unreadable && !mu_msg_is_readable (msg))
|
||||
continue;
|
||||
|
||||
output_xml_msg (msg);
|
||||
|
||||
|
||||
++mycount;
|
||||
}
|
||||
g_print ("</messages>\n");
|
||||
|
||||
|
||||
if (count)
|
||||
*count = mycount;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -820,20 +820,20 @@ mu_cmd_find (MuConfig *opts)
|
||||
gboolean rv;
|
||||
gchar *query;
|
||||
size_t count = 0;
|
||||
|
||||
|
||||
g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_FIND,
|
||||
MU_ERROR_INTERNAL);
|
||||
|
||||
|
||||
if (!query_params_valid (opts) || !format_params_valid(opts))
|
||||
return MU_ERROR_IN_PARAMETERS;
|
||||
|
||||
|
||||
xapian = get_query_obj();
|
||||
query = get_query (opts);
|
||||
|
||||
if (!xapian ||!query)
|
||||
return MU_ERROR_INTERNAL;
|
||||
|
||||
|
||||
if (opts->format == MU_CONFIG_FORMAT_XQUERY)
|
||||
rv = print_xapian_query (xapian, query, &count);
|
||||
else if (opts->exec)
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
#include "mu-util.h"
|
||||
#include "mu-msg.h"
|
||||
#include "mu-index.h"
|
||||
#include "mu-store.h"
|
||||
#include "mu-runtime.h"
|
||||
|
||||
static gboolean MU_CAUGHT_SIGNAL;
|
||||
@ -54,7 +55,7 @@ sig_handler (int sig)
|
||||
g_warning ("shutting down gracefully, "
|
||||
"press again to kill immediately");
|
||||
}
|
||||
|
||||
|
||||
MU_CAUGHT_SIGNAL = TRUE;
|
||||
}
|
||||
|
||||
@ -63,7 +64,7 @@ install_sig_handler (void)
|
||||
{
|
||||
struct sigaction action;
|
||||
int i, sigs[] = { SIGINT, SIGHUP, SIGTERM };
|
||||
|
||||
|
||||
MU_CAUGHT_SIGNAL = FALSE;
|
||||
|
||||
action.sa_handler = sig_handler;
|
||||
@ -86,12 +87,12 @@ check_index_or_cleanup_params (MuConfig *opts)
|
||||
g_warning ("usage: mu %s [options]", opts->params[0]);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (opts->linksdir) {
|
||||
g_warning ("invalid option(s) for command");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (opts->xbatchsize < 0) {
|
||||
g_warning ("the Xapian batch size must be non-negative");
|
||||
return FALSE;
|
||||
@ -101,7 +102,7 @@ check_index_or_cleanup_params (MuConfig *opts)
|
||||
g_warning ("the maximum message size must be non-negative");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -113,12 +114,12 @@ check_maildir (const char *maildir)
|
||||
"use --maildir= to set it explicitly");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (!g_path_is_absolute (maildir)) {
|
||||
g_warning ("maildir path '%s' is not absolute", maildir);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (!mu_util_check_dir (maildir, TRUE, FALSE)) {
|
||||
g_warning ("not a valid Maildir: %s", maildir);
|
||||
return FALSE;
|
||||
@ -140,7 +141,7 @@ backspace (unsigned u)
|
||||
{
|
||||
static gboolean init = FALSE;
|
||||
static char backspace[80];
|
||||
|
||||
|
||||
if (G_UNLIKELY(!init)) {
|
||||
/* fill with backspaces */
|
||||
int i;
|
||||
@ -148,7 +149,7 @@ backspace (unsigned u)
|
||||
backspace[i] = '\b';
|
||||
init = TRUE;
|
||||
}
|
||||
|
||||
|
||||
backspace[MIN(u,sizeof(backspace))] = '\0';
|
||||
fputs (backspace, stdout);
|
||||
backspace[u] = '\b';
|
||||
@ -161,11 +162,11 @@ print_stats (MuIndexStats* stats, gboolean clear)
|
||||
{
|
||||
const char *kars="-\\|/";
|
||||
char output[120];
|
||||
|
||||
|
||||
static int i = 0;
|
||||
static unsigned len = 0;
|
||||
|
||||
if (clear)
|
||||
if (clear)
|
||||
backspace (len);
|
||||
|
||||
len = (unsigned)snprintf (output, sizeof(output),
|
||||
@ -185,9 +186,9 @@ index_msg_cb (MuIndexStats* stats, void *user_data)
|
||||
{
|
||||
if (stats->_processed % 25)
|
||||
return MU_OK;
|
||||
|
||||
|
||||
print_stats (stats, TRUE);
|
||||
|
||||
|
||||
return MU_CAUGHT_SIGNAL ? MU_STOP: MU_OK;
|
||||
}
|
||||
|
||||
@ -200,27 +201,27 @@ database_version_check_and_update (MuConfig *opts)
|
||||
|
||||
xpath = mu_runtime_path (MU_RUNTIME_PATH_XAPIANDB);
|
||||
ccache = mu_runtime_path (MU_RUNTIME_PATH_CONTACTS);
|
||||
|
||||
if (mu_util_xapian_is_empty (xpath))
|
||||
|
||||
if (mu_store_database_is_empty (xpath))
|
||||
return TRUE;
|
||||
|
||||
|
||||
/* when rebuilding, we empty the database before doing
|
||||
* anything */
|
||||
if (opts->rebuild) {
|
||||
opts->reindex = TRUE;
|
||||
g_message ("clearing database [%s]", xpath);
|
||||
g_message ("clearing contacts-cache [%s]", ccache);
|
||||
return mu_util_xapian_clear (xpath, ccache);
|
||||
return mu_store_database_clear (xpath, ccache);
|
||||
}
|
||||
|
||||
if (!mu_util_xapian_needs_upgrade (xpath))
|
||||
if (!mu_store_database_needs_upgrade (xpath))
|
||||
return TRUE; /* ok, nothing to do */
|
||||
|
||||
|
||||
/* ok, database is not up to date */
|
||||
if (opts->autoupgrade) {
|
||||
opts->reindex = TRUE;
|
||||
g_message ("auto-upgrade: clearing old database and cache");
|
||||
return mu_util_xapian_clear (xpath, ccache);
|
||||
return mu_store_database_clear (xpath, ccache);
|
||||
}
|
||||
|
||||
update_warning ();
|
||||
@ -243,7 +244,7 @@ static gboolean
|
||||
update_maildir_path_maybe (MuIndex *idx, MuConfig *opts)
|
||||
{
|
||||
gchar *exp;
|
||||
|
||||
|
||||
/* if 'maildir_guessed' is TRUE, we can override it later
|
||||
* with mu_index_last_used_maildir (in mu-cmd-index.c)
|
||||
*/
|
||||
@ -253,21 +254,21 @@ update_maildir_path_maybe (MuIndex *idx, MuConfig *opts)
|
||||
|
||||
/* try the last used one */
|
||||
tmp = mu_index_last_used_maildir (idx);
|
||||
if (tmp)
|
||||
if (tmp)
|
||||
opts->maildir = g_strdup (tmp);
|
||||
else
|
||||
opts->maildir = mu_util_guess_maildir ();
|
||||
}
|
||||
|
||||
|
||||
if (opts->maildir) {
|
||||
exp = mu_util_dir_expand(opts->maildir);
|
||||
if (exp) {
|
||||
g_free(opts->maildir);
|
||||
opts->maildir = exp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return check_maildir (opts->maildir);
|
||||
return check_maildir (opts->maildir);
|
||||
}
|
||||
|
||||
|
||||
@ -277,21 +278,21 @@ cmd_cleanup (MuIndex *midx, MuConfig *opts, MuIndexStats *stats,
|
||||
{
|
||||
MuError rv;
|
||||
time_t t;
|
||||
|
||||
|
||||
g_message ("cleaning up messages [%s]",
|
||||
mu_runtime_path (MU_RUNTIME_PATH_XAPIANDB));
|
||||
|
||||
|
||||
t = time (NULL);
|
||||
rv = mu_index_cleanup (midx, stats,
|
||||
show_progress ? index_msg_cb : index_msg_silent_cb,
|
||||
NULL);
|
||||
|
||||
|
||||
if (!opts->quiet) {
|
||||
print_stats (stats, TRUE);
|
||||
g_print ("\n");
|
||||
show_time ((unsigned)(time(NULL)-t),stats->_processed);
|
||||
}
|
||||
|
||||
|
||||
return (rv == MU_OK || rv == MU_STOP) ? MU_OK: MU_ERROR;
|
||||
}
|
||||
|
||||
@ -303,15 +304,15 @@ cmd_index (MuIndex *midx, MuConfig *opts, MuIndexStats *stats,
|
||||
{
|
||||
MuError rv;
|
||||
time_t t;
|
||||
|
||||
|
||||
g_message ("indexing messages under %s [%s]", opts->maildir,
|
||||
mu_runtime_path (MU_RUNTIME_PATH_XAPIANDB));
|
||||
|
||||
|
||||
t = time (NULL);
|
||||
rv = mu_index_run (midx, opts->maildir, opts->reindex, stats,
|
||||
show_progress ? index_msg_cb:index_msg_silent_cb,
|
||||
NULL, NULL);
|
||||
|
||||
|
||||
if (!opts->quiet) {
|
||||
print_stats (stats, TRUE);
|
||||
g_print ("\n");
|
||||
@ -321,7 +322,7 @@ cmd_index (MuIndex *midx, MuConfig *opts, MuIndexStats *stats,
|
||||
if (rv == MU_OK || rv == MU_STOP)
|
||||
MU_WRITE_LOG ("index: processed: %u; updated/new: %u",
|
||||
stats->_processed, stats->_updated);
|
||||
|
||||
|
||||
if (rv == MU_OK && !opts->nocleanup) {
|
||||
mu_index_stats_clear (stats);
|
||||
rv = cmd_cleanup (midx, opts, stats, show_progress);
|
||||
@ -331,7 +332,7 @@ cmd_index (MuIndex *midx, MuConfig *opts, MuIndexStats *stats,
|
||||
return MU_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (rv==MU_OK||rv==MU_STOP) ? MU_OK : MU_ERROR;
|
||||
}
|
||||
|
||||
@ -339,7 +340,7 @@ static MuError
|
||||
handle_index_error_and_free (GError *err)
|
||||
{
|
||||
MuError code;
|
||||
|
||||
|
||||
if (!err)
|
||||
return MU_ERROR_INTERNAL;
|
||||
|
||||
@ -371,7 +372,7 @@ init_mu_index (MuConfig *opts, MuError *code)
|
||||
{
|
||||
MuIndex *midx;
|
||||
GError *err;
|
||||
|
||||
|
||||
if (!check_index_or_cleanup_params (opts)) {
|
||||
*code = MU_ERROR_IN_PARAMETERS;
|
||||
return NULL;
|
||||
@ -381,7 +382,7 @@ init_mu_index (MuConfig *opts, MuError *code)
|
||||
*code = MU_ERROR_XAPIAN_NOT_UP_TO_DATE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
err = NULL;
|
||||
midx = mu_index_new (mu_runtime_path (MU_RUNTIME_PATH_XAPIANDB),
|
||||
mu_runtime_path (MU_RUNTIME_PATH_CONTACTS),
|
||||
@ -390,10 +391,10 @@ init_mu_index (MuConfig *opts, MuError *code)
|
||||
*code = handle_index_error_and_free (err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mu_index_set_max_msg_size (midx, opts->max_msg_size);
|
||||
|
||||
mu_index_set_max_msg_size (midx, opts->max_msg_size);
|
||||
mu_index_set_xbatch_size (midx, opts->xbatchsize);
|
||||
|
||||
|
||||
return midx;
|
||||
}
|
||||
|
||||
@ -410,13 +411,13 @@ cmd_index_or_cleanup (MuConfig *opts)
|
||||
midx = init_mu_index (opts, &code);
|
||||
if (!midx)
|
||||
return code;
|
||||
|
||||
|
||||
/* we determine the maildir path only here, as it may depend on
|
||||
* mu_index_last_used_maildir
|
||||
*/
|
||||
if (!update_maildir_path_maybe (midx, opts))
|
||||
return MU_ERROR_FILE;
|
||||
|
||||
|
||||
/* note, 'opts->quiet' already cause g_message output not to
|
||||
* be shown; here, we make sure we only print progress info if
|
||||
* opts->quiet is false case and when stdout is a tty */
|
||||
@ -434,8 +435,8 @@ cmd_index_or_cleanup (MuConfig *opts)
|
||||
rv = MU_ERROR_INTERNAL;
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
mu_index_destroy (midx);
|
||||
|
||||
mu_index_destroy (midx);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -446,7 +447,7 @@ mu_cmd_index (MuConfig *opts)
|
||||
g_return_val_if_fail (opts, FALSE);
|
||||
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_INDEX,
|
||||
FALSE);
|
||||
|
||||
|
||||
return cmd_index_or_cleanup (opts);
|
||||
}
|
||||
|
||||
@ -456,7 +457,7 @@ mu_cmd_cleanup (MuConfig *opts)
|
||||
g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail (opts->cmd != MU_CONFIG_CMD_CLEANUP,
|
||||
MU_ERROR_INTERNAL);
|
||||
|
||||
|
||||
return cmd_index_or_cleanup (opts);
|
||||
}
|
||||
|
||||
|
||||
107
src/mu-cmd.c
107
src/mu-cmd.c
@ -46,7 +46,12 @@
|
||||
static gboolean
|
||||
view_msg_sexp (MuMsg *msg)
|
||||
{
|
||||
fputs (mu_msg_to_sexp (msg, NULL, FALSE), stdout);
|
||||
char *sexp;
|
||||
|
||||
sexp = mu_msg_to_sexp (msg, NULL, FALSE);
|
||||
fputs (sexp, stdout);
|
||||
g_free (sexp);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -77,7 +82,7 @@ get_attach_str (MuMsg *msg)
|
||||
mu_msg_part_foreach (msg, (MuMsgPartForeachFunc)each_part, &attach);
|
||||
|
||||
return attach;
|
||||
}
|
||||
}
|
||||
|
||||
#define color_maybe(C) do{ if (color) fputs ((C),stdout);}while(0)
|
||||
|
||||
@ -86,12 +91,12 @@ 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);
|
||||
|
||||
|
||||
if (val) {
|
||||
color_maybe (MU_COLOR_GREEN);
|
||||
mu_util_fputs_encoded (val, stdout);
|
||||
@ -107,11 +112,11 @@ body_or_summary (MuMsg *msg, gboolean summary, gboolean color)
|
||||
{
|
||||
const char* field;
|
||||
const int SUMMARY_LEN = 5;
|
||||
|
||||
|
||||
field = mu_msg_get_body_text (msg);
|
||||
if (!field)
|
||||
return; /* no body -- nothing more to do */
|
||||
|
||||
|
||||
if (summary) {
|
||||
gchar *summ;
|
||||
summ = mu_str_summarize (field, SUMMARY_LEN);
|
||||
@ -133,14 +138,14 @@ view_msg_plain (MuMsg *msg, const gchar *fields, gboolean summary,
|
||||
gchar *attachs;
|
||||
time_t date;
|
||||
const GSList *lst;
|
||||
|
||||
|
||||
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)))
|
||||
|
||||
if ((date = mu_msg_get_date (msg)))
|
||||
print_field ("Date", mu_date_str_s ("%c", date),
|
||||
color);
|
||||
|
||||
@ -150,7 +155,7 @@ view_msg_plain (MuMsg *msg, const gchar *fields, gboolean summary,
|
||||
print_field ("Tags", tags, color);
|
||||
g_free (tags);
|
||||
}
|
||||
|
||||
|
||||
if ((attachs = get_attach_str (msg))) {
|
||||
print_field ("Attachments", attachs, color);
|
||||
g_free (attachs);
|
||||
@ -168,13 +173,15 @@ handle_msg (const char *fname, MuConfig *opts, MuError *code)
|
||||
GError *err;
|
||||
MuMsg *msg;
|
||||
gboolean rv;
|
||||
|
||||
|
||||
err = NULL;
|
||||
msg = mu_msg_new_from_file (fname, NULL, &err);
|
||||
|
||||
if (!msg) {
|
||||
g_warning ("error: %s", err->message);
|
||||
g_error_free (err);
|
||||
if (err && err->message) {
|
||||
g_warning ("%s", err->message);
|
||||
g_error_free (err);
|
||||
}
|
||||
*code = MU_ERROR;
|
||||
return FALSE;
|
||||
}
|
||||
@ -191,7 +198,7 @@ handle_msg (const char *fname, MuConfig *opts, MuError *code)
|
||||
*code = MU_ERROR_INTERNAL;
|
||||
rv = FALSE;
|
||||
}
|
||||
|
||||
|
||||
mu_msg_unref (msg);
|
||||
|
||||
return rv;
|
||||
@ -205,7 +212,7 @@ view_params_valid (MuConfig *opts)
|
||||
g_warning ("usage: mu view [options] <file> [<files>]");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
switch (opts->format) {
|
||||
case MU_CONFIG_FORMAT_PLAIN:
|
||||
case MU_CONFIG_FORMAT_SEXP:
|
||||
@ -215,7 +222,7 @@ view_params_valid (MuConfig *opts)
|
||||
opts->formatstr ? opts->formatstr : "<none>");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -226,14 +233,14 @@ mu_cmd_view (MuConfig *opts)
|
||||
int i;
|
||||
gboolean rv;
|
||||
MuError code;
|
||||
|
||||
|
||||
g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_VIEW,
|
||||
MU_ERROR_INTERNAL);
|
||||
|
||||
if (!view_params_valid(opts))
|
||||
return MU_ERROR_IN_PARAMETERS;
|
||||
|
||||
|
||||
for (i = 1, code = MU_OK; opts->params[i]; ++i) {
|
||||
|
||||
rv = handle_msg (opts->params[i], opts, &code);
|
||||
@ -243,7 +250,7 @@ mu_cmd_view (MuConfig *opts)
|
||||
if (opts->terminator)
|
||||
g_print ("%c", VIEW_TERMINATOR);
|
||||
}
|
||||
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
@ -252,17 +259,17 @@ MuError
|
||||
mu_cmd_mkdir (MuConfig *opts)
|
||||
{
|
||||
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);
|
||||
|
||||
|
||||
if (!opts->params[1]) {
|
||||
g_warning ("usage: mu mkdir [-u,--mode=<mode>] "
|
||||
"<dir> [more dirs]");
|
||||
return MU_ERROR_IN_PARAMETERS;
|
||||
}
|
||||
|
||||
|
||||
for (i = 1; opts->params[i]; ++i) {
|
||||
|
||||
GError *err;
|
||||
@ -309,7 +316,7 @@ mv_check_params (MuConfig *opts, MuFlags *flags)
|
||||
MU_FLAG_TYPE_MAILDIR |
|
||||
MU_FLAG_TYPE_MAILFILE);
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -321,7 +328,7 @@ cmd_mv_dev_null (MuConfig *opts)
|
||||
g_warning ("unlink failed: %s", strerror (errno));
|
||||
return MU_ERROR_FILE;
|
||||
}
|
||||
|
||||
|
||||
if (opts->print_target)
|
||||
g_print ("/dev/null\n"); /* /dev/null */
|
||||
|
||||
@ -335,7 +342,7 @@ mu_cmd_mv (MuConfig *opts)
|
||||
GError *err;
|
||||
gchar *fullpath;
|
||||
MuFlags flags;
|
||||
|
||||
|
||||
if (!mv_check_params (opts, &flags))
|
||||
return MU_ERROR_IN_PARAMETERS;
|
||||
|
||||
@ -357,19 +364,19 @@ mu_cmd_mv (MuConfig *opts)
|
||||
return code;
|
||||
}
|
||||
return MU_ERROR_FILE;
|
||||
|
||||
|
||||
} else {
|
||||
if (opts->print_target)
|
||||
g_print ("%s\n", fullpath);
|
||||
if (opts->print_target)
|
||||
g_print ("%s\n", fullpath);
|
||||
return MU_OK;
|
||||
}
|
||||
|
||||
|
||||
g_free (fullpath);
|
||||
|
||||
|
||||
return MU_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static gboolean
|
||||
check_file_okay (const char *path, gboolean cmd_add)
|
||||
{
|
||||
@ -377,7 +384,7 @@ check_file_okay (const char *path, gboolean cmd_add)
|
||||
g_warning ("path is not absolute: %s", path);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (cmd_add && access(path, R_OK) != 0) {
|
||||
g_warning ("path is not readable: %s: %s",
|
||||
path, strerror (errno));
|
||||
@ -386,7 +393,7 @@ check_file_okay (const char *path, gboolean cmd_add)
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static MuStore*
|
||||
get_store (void)
|
||||
@ -395,9 +402,10 @@ get_store (void)
|
||||
GError *err;
|
||||
|
||||
err = NULL;
|
||||
store = mu_store_new (mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB),
|
||||
mu_runtime_path(MU_RUNTIME_PATH_CONTACTS),
|
||||
&err);
|
||||
store = mu_store_new_writable
|
||||
(mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB),
|
||||
mu_runtime_path(MU_RUNTIME_PATH_CONTACTS),
|
||||
&err);
|
||||
if (!store) {
|
||||
if (err) {
|
||||
g_warning ("store error: %s", err->message);
|
||||
@ -407,18 +415,16 @@ get_store (void)
|
||||
}
|
||||
|
||||
return store;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
MuError
|
||||
mu_cmd_add (MuConfig *opts)
|
||||
{
|
||||
MuStore *store;
|
||||
gboolean allok;
|
||||
int i;
|
||||
|
||||
|
||||
g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_ADD,
|
||||
MU_ERROR_INTERNAL);
|
||||
@ -432,9 +438,9 @@ mu_cmd_add (MuConfig *opts)
|
||||
store = get_store ();
|
||||
if (!store)
|
||||
return MU_ERROR_INTERNAL;
|
||||
|
||||
|
||||
for (i = 1, allok = TRUE; opts->params[i]; ++i) {
|
||||
|
||||
|
||||
const char* src;
|
||||
src = opts->params[i];
|
||||
|
||||
@ -442,13 +448,13 @@ mu_cmd_add (MuConfig *opts)
|
||||
allok = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!mu_store_store_path (store, src)) {
|
||||
allok = FALSE;
|
||||
g_warning ("failed to store %s", src);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mu_store_destroy (store);
|
||||
|
||||
return allok ? MU_OK : MU_ERROR;
|
||||
@ -461,7 +467,7 @@ mu_cmd_remove (MuConfig *opts)
|
||||
MuStore *store;
|
||||
gboolean allok;
|
||||
int i;
|
||||
|
||||
|
||||
g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
|
||||
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_REMOVE,
|
||||
MU_ERROR_INTERNAL);
|
||||
@ -475,9 +481,9 @@ mu_cmd_remove (MuConfig *opts)
|
||||
store = get_store ();
|
||||
if (!store)
|
||||
return MU_ERROR_INTERNAL;
|
||||
|
||||
|
||||
for (i = 1, allok = TRUE; opts->params[i]; ++i) {
|
||||
|
||||
|
||||
const char* src;
|
||||
src = opts->params[i];
|
||||
|
||||
@ -485,14 +491,17 @@ mu_cmd_remove (MuConfig *opts)
|
||||
allok = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!mu_store_remove_path (store, src)) {
|
||||
allok = FALSE;
|
||||
g_warning ("failed to remove %s", src);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mu_store_destroy (store);
|
||||
|
||||
return allok ? MU_OK : MU_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
63
src/mu-cmd.h
63
src/mu-cmd.h
@ -33,8 +33,8 @@ G_BEGIN_DECLS
|
||||
*
|
||||
* @param opts configuration options
|
||||
*
|
||||
* @return MU_EXITCODE_OK (0) if the command succeeded,
|
||||
* MU_EXITCODE_ERROR otherwise
|
||||
* @return MU_OK (0) if the command succeeded,
|
||||
* some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_mkdir (MuConfig *opts);
|
||||
|
||||
@ -44,30 +44,32 @@ MuError mu_cmd_mkdir (MuConfig *opts);
|
||||
*
|
||||
* @param opts configuration options
|
||||
*
|
||||
* @return MU_EXITCODE_OK (0) if the command succeeded,
|
||||
* MU_EXITCODE_ERROR otherwise
|
||||
* @return MU_OK (0) if the command succeeded,
|
||||
* some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_view (MuConfig *opts);
|
||||
|
||||
|
||||
/**
|
||||
* execute the 'index' command
|
||||
*
|
||||
*
|
||||
* @param store store object to use
|
||||
* @param opts configuration options
|
||||
*
|
||||
* @return MU_EXITCODE_OK (0) if the command succeeded,
|
||||
* MU_EXITCODE_ERROR otherwise
|
||||
* @return MU_OK (0) if the command succeeded,
|
||||
* some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_index (MuConfig *opts);
|
||||
|
||||
|
||||
/**
|
||||
* execute the 'cleanup' command
|
||||
*
|
||||
*
|
||||
* @param store store object to use
|
||||
* @param opts configuration options
|
||||
*
|
||||
* @return MU_EXITCODE_OK (0) if the command succeeds,
|
||||
* MU_EXITCODE_ERROR otherwise
|
||||
* @return MU_OK (0) if the command succeeds,
|
||||
* some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_cleanup (MuConfig *opts);
|
||||
|
||||
@ -76,9 +78,9 @@ MuError mu_cmd_cleanup (MuConfig *opts);
|
||||
*
|
||||
* @param opts configuration options
|
||||
*
|
||||
* @return MU_EXITCODE_OK (0) if the command succeeds and
|
||||
* >MU_EXITCODE_OK (0) results, MU_EXITCODE_NO_MATCHES if the command
|
||||
* succeeds but there no matches, MU_EXITCODE_ERROR for all other errors
|
||||
* @return MU_OK (0) if the command succeeds and
|
||||
* >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 (MuConfig *opts);
|
||||
|
||||
@ -88,8 +90,8 @@ MuError mu_cmd_find (MuConfig *opts);
|
||||
*
|
||||
* @param opts configuration options
|
||||
*
|
||||
* @return MU_EXITCODE_OK (0) if the command succeeds,
|
||||
* MU_EXITCODE_ERROR otherwise
|
||||
* @return MU_OK (0) if the command succeeds,
|
||||
* some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_extract (MuConfig *opts);
|
||||
|
||||
@ -99,21 +101,18 @@ MuError mu_cmd_extract (MuConfig *opts);
|
||||
*
|
||||
* @param opts configuration options
|
||||
*
|
||||
* @return MU_EXITCODE_OK (0) if the command succeeds,
|
||||
* MU_EXITCODE_ERROR otherwise
|
||||
* @return MU_OK (0) if the command succeeds,
|
||||
* some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_mv (MuConfig *opts);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* execute the cfind command
|
||||
*
|
||||
* @param opts configuration options
|
||||
*
|
||||
* @return MU_EXITCODE_OK (0) if the command succeeds,
|
||||
* MU_EXITCODE_ERROR otherwise
|
||||
* @return MU_OK (0) if the command succeeds,
|
||||
* some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_cfind (MuConfig *opts);
|
||||
|
||||
@ -123,8 +122,8 @@ MuError mu_cmd_cfind (MuConfig *opts);
|
||||
*
|
||||
* @param opts configuration options
|
||||
*
|
||||
* @return MU_EXITCODE_OK (0) if the command succeeds,
|
||||
* MU_EXITCODE_ERROR otherwise
|
||||
* @return MU_OK (0) if the command succeeds,
|
||||
* some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_add (MuConfig *opts);
|
||||
|
||||
@ -133,11 +132,23 @@ MuError mu_cmd_add (MuConfig *opts);
|
||||
*
|
||||
* @param opts configuration options
|
||||
*
|
||||
* @return MU_EXITCODE_OK (0) if the command succeeds,
|
||||
* MU_EXITCODE_ERROR otherwise
|
||||
* @return MU_OK (0) if the command succeeds,
|
||||
* some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_remove (MuConfig *opts);
|
||||
|
||||
|
||||
/**
|
||||
* execute the server command
|
||||
*
|
||||
* @param opts configuration options
|
||||
*
|
||||
* @return MU_OK (0) if the command succeeds,
|
||||
* some error code otherwise
|
||||
*/
|
||||
MuError mu_cmd_server (MuConfig *opts);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /*__MU_CMD_H__*/
|
||||
|
||||
127
src/mu-index.c
127
src/mu-index.c
@ -1,22 +1,22 @@
|
||||
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/
|
||||
|
||||
/*
|
||||
/*
|
||||
** Copyright (C) 2008-2010 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
1** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation; either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program; if not, write to the Free Software Foundation,
|
||||
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**
|
||||
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
@ -46,40 +46,40 @@ struct _MuIndex {
|
||||
guint _max_filesize;
|
||||
};
|
||||
|
||||
MuIndex*
|
||||
MuIndex*
|
||||
mu_index_new (const char *xpath, const char* contacts_cache, GError **err)
|
||||
{
|
||||
MuIndex *index;
|
||||
|
||||
g_return_val_if_fail (xpath, NULL);
|
||||
|
||||
index = g_new0 (MuIndex, 1);
|
||||
|
||||
index->_store = mu_store_new (xpath, contacts_cache, err);
|
||||
index = g_new0 (MuIndex, 1);
|
||||
|
||||
index->_store = mu_store_new_writable (xpath, contacts_cache, err);
|
||||
if (!index->_store) {
|
||||
g_warning ("%s: failed to open xapian store (%s)",
|
||||
__FUNCTION__, xpath);
|
||||
__FUNCTION__, xpath);
|
||||
g_free (index);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set the default max file size */
|
||||
index->_max_filesize = MU_INDEX_MAX_FILE_SIZE;
|
||||
|
||||
|
||||
/* see we need to reindex the database; note, there is a small
|
||||
* race-condition here, between mu_index_new and
|
||||
* mu_index_run. Maybe do the check in mu_index_run
|
||||
* instead? */
|
||||
if (mu_util_xapian_is_empty (xpath))
|
||||
if (mu_store_database_is_empty (xpath))
|
||||
index->_needs_reindex = FALSE;
|
||||
else
|
||||
index->_needs_reindex =
|
||||
mu_util_xapian_needs_upgrade (xpath);
|
||||
|
||||
mu_store_database_needs_upgrade (xpath);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
mu_index_destroy (MuIndex *index)
|
||||
{
|
||||
if (!index)
|
||||
@ -116,7 +116,7 @@ needs_index (MuIndexCallbackData *data, const char *fullpath,
|
||||
/* unconditionally reindex */
|
||||
if (data->_reindex)
|
||||
return TRUE;
|
||||
|
||||
|
||||
/* it's not in the database yet */
|
||||
if (!mu_store_contains_message (data->_store, fullpath))
|
||||
return TRUE;
|
||||
@ -133,14 +133,14 @@ static MuError
|
||||
insert_or_update_maybe (const char* fullpath, const char* mdir,
|
||||
time_t filestamp, MuIndexCallbackData *data,
|
||||
gboolean *updated)
|
||||
{
|
||||
{
|
||||
MuMsg *msg;
|
||||
GError *err;
|
||||
|
||||
|
||||
*updated = FALSE;
|
||||
if (!needs_index (data, fullpath, filestamp))
|
||||
return MU_OK; /* nothing to do for this one */
|
||||
|
||||
|
||||
err = NULL;
|
||||
msg = mu_msg_new_from_file (fullpath, mdir, &err);
|
||||
if ((G_UNLIKELY(!msg))) {
|
||||
@ -148,18 +148,18 @@ insert_or_update_maybe (const char* fullpath, const char* mdir,
|
||||
__FUNCTION__, fullpath);
|
||||
return MU_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* we got a valid id; scan the message contents as well */
|
||||
if (G_UNLIKELY((!mu_store_store_msg (data->_store, msg, TRUE)))) {
|
||||
g_warning ("%s: storing content %s failed", __FUNCTION__,
|
||||
g_warning ("%s: storing content %s failed", __FUNCTION__,
|
||||
fullpath);
|
||||
return MU_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mu_msg_unref (msg);
|
||||
*updated = TRUE;
|
||||
|
||||
return MU_OK;
|
||||
return MU_OK;
|
||||
}
|
||||
|
||||
static MuError
|
||||
@ -169,9 +169,9 @@ run_msg_callback_maybe (MuIndexCallbackData *data)
|
||||
|
||||
if (!data || !data->_idx_msg_cb)
|
||||
return MU_OK;
|
||||
|
||||
|
||||
result = data->_idx_msg_cb (data->_stats, data->_user_data);
|
||||
if G_UNLIKELY((result != MU_OK && result != MU_STOP))
|
||||
if (G_UNLIKELY(result != MU_OK && result != MU_STOP))
|
||||
g_warning ("error in callback");
|
||||
|
||||
return result;
|
||||
@ -191,17 +191,17 @@ on_run_maildir_msg (const char* fullpath, const char* mdir,
|
||||
data->_max_filesize, fullpath);
|
||||
return MU_OK; /* not an error */
|
||||
}
|
||||
|
||||
|
||||
result = run_msg_callback_maybe (data);
|
||||
if (result != MU_OK)
|
||||
return result;
|
||||
|
||||
|
||||
/* see if we need to update/insert anything...
|
||||
* use the ctime, so any status change will be visible (perms,
|
||||
* filename etc.)*/
|
||||
result = insert_or_update_maybe (fullpath, mdir, statbuf->st_ctime,
|
||||
data, &updated);
|
||||
|
||||
|
||||
if (result == MU_OK && data && data->_stats) { /* update statistics */
|
||||
++data->_stats->_processed;
|
||||
updated ? ++data->_stats->_updated : ++data->_stats->_uptodate;
|
||||
@ -212,7 +212,7 @@ on_run_maildir_msg (const char* fullpath, const char* mdir,
|
||||
|
||||
|
||||
static MuError
|
||||
on_run_maildir_dir (const char* fullpath, gboolean enter,
|
||||
on_run_maildir_dir (const char* fullpath, gboolean enter,
|
||||
MuIndexCallbackData *data)
|
||||
{
|
||||
/* xapian stores a per-dir timestamp; we use this timestamp
|
||||
@ -231,9 +231,9 @@ on_run_maildir_dir (const char* fullpath, gboolean enter,
|
||||
g_debug ("leaving %s (ts=%u)",
|
||||
fullpath, (unsigned)data->_dirstamp);
|
||||
}
|
||||
|
||||
|
||||
if (data->_idx_dir_cb)
|
||||
return data->_idx_dir_cb (fullpath, enter,
|
||||
return data->_idx_dir_cb (fullpath, enter,
|
||||
data->_user_data);
|
||||
|
||||
return MU_OK;
|
||||
@ -249,37 +249,37 @@ check_path (const char* path)
|
||||
__FUNCTION__, path);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (access (path, R_OK) != 0) {
|
||||
g_warning ("%s: cannot open '%s': %s",
|
||||
g_warning ("%s: cannot open '%s': %s",
|
||||
__FUNCTION__, path, strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
init_cb_data (MuIndexCallbackData *cb_data, MuStore *xapian,
|
||||
gboolean reindex, guint max_filesize, MuIndexStats *stats,
|
||||
MuIndexMsgCallback msg_cb, MuIndexDirCallback dir_cb,
|
||||
MuIndexMsgCallback msg_cb, MuIndexDirCallback dir_cb,
|
||||
void *user_data)
|
||||
{
|
||||
cb_data->_idx_msg_cb = msg_cb;
|
||||
cb_data->_idx_dir_cb = dir_cb;
|
||||
|
||||
|
||||
cb_data->_user_data = user_data;
|
||||
cb_data->_store = xapian;
|
||||
|
||||
|
||||
cb_data->_reindex = reindex;
|
||||
cb_data->_dirstamp = 0;
|
||||
cb_data->_dirstamp = 0;
|
||||
cb_data->_max_filesize = max_filesize;
|
||||
|
||||
|
||||
cb_data->_stats = stats;
|
||||
if (cb_data->_stats)
|
||||
memset (cb_data->_stats, 0, sizeof(MuIndexStats));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
update_last_used_maildir (MuIndex *index, const char *path)
|
||||
{
|
||||
@ -294,7 +294,7 @@ mu_index_last_used_maildir (MuIndex *index)
|
||||
{
|
||||
g_return_val_if_fail (index, NULL);
|
||||
g_free (index->_last_used_maildir);
|
||||
|
||||
|
||||
return index->_last_used_maildir =
|
||||
mu_store_get_metadata (index->_store,
|
||||
MU_LAST_USED_MAILDIR_KEY);
|
||||
@ -324,48 +324,48 @@ mu_index_set_xbatch_size (MuIndex *index, guint xbatchsize)
|
||||
MuError
|
||||
mu_index_run (MuIndex *index, const char* path,
|
||||
gboolean reindex, MuIndexStats *stats,
|
||||
MuIndexMsgCallback msg_cb, MuIndexDirCallback dir_cb,
|
||||
MuIndexMsgCallback msg_cb, MuIndexDirCallback dir_cb,
|
||||
void *user_data)
|
||||
{
|
||||
MuIndexCallbackData cb_data;
|
||||
MuError rv;
|
||||
|
||||
|
||||
g_return_val_if_fail (index && index->_store, MU_ERROR);
|
||||
g_return_val_if_fail (msg_cb, MU_ERROR);
|
||||
|
||||
|
||||
if (!check_path (path))
|
||||
return MU_ERROR;
|
||||
|
||||
|
||||
if (!reindex && index->_needs_reindex) {
|
||||
g_warning ("database not up-to-date; needs full reindex");
|
||||
return MU_ERROR;
|
||||
}
|
||||
|
||||
|
||||
init_cb_data (&cb_data, index->_store, reindex,
|
||||
index->_max_filesize, stats,
|
||||
msg_cb, dir_cb, user_data);
|
||||
|
||||
update_last_used_maildir (index, path);
|
||||
|
||||
|
||||
rv = mu_maildir_walk (path,
|
||||
(MuMaildirWalkMsgCallback)on_run_maildir_msg,
|
||||
(MuMaildirWalkDirCallback)on_run_maildir_dir,
|
||||
&cb_data);
|
||||
|
||||
|
||||
mu_store_flush (index->_store);
|
||||
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static MuError
|
||||
on_stats_maildir_file (const char *fullpath, const char* mdir,
|
||||
struct stat *statbuf,
|
||||
struct stat *statbuf,
|
||||
MuIndexCallbackData *cb_data)
|
||||
{
|
||||
MuError result;
|
||||
|
||||
|
||||
if (cb_data && cb_data->_idx_msg_cb)
|
||||
result = cb_data->_idx_msg_cb (cb_data->_stats,
|
||||
result = cb_data->_idx_msg_cb (cb_data->_stats,
|
||||
cb_data->_user_data);
|
||||
else
|
||||
result = MU_OK;
|
||||
@ -374,7 +374,7 @@ on_stats_maildir_file (const char *fullpath, const char* mdir,
|
||||
if (cb_data->_stats)
|
||||
++cb_data->_stats->_processed;
|
||||
return MU_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return result; /* MU_STOP or MU_OK */
|
||||
}
|
||||
@ -386,16 +386,16 @@ mu_index_stats (MuIndex *index, const char* path,
|
||||
MuIndexDirCallback cb_dir, void *user_data)
|
||||
{
|
||||
MuIndexCallbackData cb_data;
|
||||
|
||||
|
||||
g_return_val_if_fail (index, MU_ERROR);
|
||||
g_return_val_if_fail (cb_msg, MU_ERROR);
|
||||
|
||||
|
||||
if (!check_path (path))
|
||||
return MU_ERROR;
|
||||
|
||||
if (stats)
|
||||
memset (stats, 0, sizeof(MuIndexStats));
|
||||
|
||||
|
||||
cb_data._idx_msg_cb = cb_msg;
|
||||
cb_data._idx_dir_cb = cb_dir;
|
||||
|
||||
@ -403,19 +403,18 @@ mu_index_stats (MuIndex *index, const char* path,
|
||||
cb_data._user_data = user_data;
|
||||
|
||||
cb_data._dirstamp = 0;
|
||||
|
||||
|
||||
return mu_maildir_walk (path,
|
||||
(MuMaildirWalkMsgCallback)on_stats_maildir_file,
|
||||
NULL,&cb_data);
|
||||
}
|
||||
|
||||
|
||||
struct _CleanupData {
|
||||
MuStore *_store;
|
||||
MuIndexStats *_stats;
|
||||
MuIndexCleanupDeleteCallback _cb;
|
||||
void *_user_data;
|
||||
|
||||
|
||||
};
|
||||
typedef struct _CleanupData CleanupData;
|
||||
|
||||
@ -434,7 +433,7 @@ foreach_doc_cb (const char* path, CleanupData *cudata)
|
||||
|
||||
if (cudata->_stats)
|
||||
++cudata->_stats->_processed;
|
||||
|
||||
|
||||
if (!cudata->_cb)
|
||||
return MU_OK;
|
||||
|
||||
@ -449,15 +448,15 @@ mu_index_cleanup (MuIndex *index, MuIndexStats *stats,
|
||||
{
|
||||
MuError rv;
|
||||
CleanupData cudata;
|
||||
|
||||
|
||||
g_return_val_if_fail (index, MU_ERROR);
|
||||
g_return_val_if_fail (cb, MU_ERROR);
|
||||
|
||||
|
||||
cudata._store = index->_store;
|
||||
cudata._stats = stats;
|
||||
cudata._cb = cb;
|
||||
cudata._user_data = user_data;
|
||||
|
||||
|
||||
rv = mu_store_foreach (index->_store,
|
||||
(MuStoreForeachFunc)foreach_doc_cb,
|
||||
&cudata);
|
||||
|
||||
@ -297,7 +297,7 @@ mu_msg_to_sexp (MuMsg *msg, const MuMsgIterThreadInfo *ti, gboolean dbonly)
|
||||
if (!dbonly)
|
||||
append_sexp_message_file_attr (gstr, msg);
|
||||
|
||||
g_string_append (gstr, ")\n;;eom\n");
|
||||
g_string_append (gstr, ")\n;;eox\n");
|
||||
|
||||
return g_string_free (gstr, FALSE);
|
||||
}
|
||||
|
||||
151
src/mu-msg.c
151
src/mu-msg.c
@ -6,16 +6,16 @@
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation; either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program; if not, write to the Free Software Foundation,
|
||||
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**
|
||||
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@ -47,13 +47,13 @@ static void
|
||||
gmime_init (void)
|
||||
{
|
||||
g_return_if_fail (!_gmime_initialized);
|
||||
|
||||
|
||||
#ifdef GMIME_ENABLE_RFC2047_WORKAROUNDS
|
||||
g_mime_init(GMIME_ENABLE_RFC2047_WORKAROUNDS);
|
||||
#else
|
||||
g_mime_init(0);
|
||||
#endif /* GMIME_ENABLE_RFC2047_WORKAROUNDS */
|
||||
|
||||
|
||||
_gmime_initialized = TRUE;
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ static void
|
||||
gmime_uninit (void)
|
||||
{
|
||||
g_return_if_fail (_gmime_initialized);
|
||||
|
||||
|
||||
g_mime_shutdown();
|
||||
_gmime_initialized = FALSE;
|
||||
}
|
||||
@ -71,17 +71,12 @@ static MuMsg*
|
||||
msg_new (void)
|
||||
{
|
||||
MuMsg *self;
|
||||
|
||||
if (G_UNLIKELY(!_gmime_initialized)) {
|
||||
gmime_init ();
|
||||
g_atexit (gmime_uninit);
|
||||
}
|
||||
|
||||
|
||||
self = g_slice_new0 (MuMsg);
|
||||
|
||||
self->_refcount = 1;
|
||||
self->_cache = mu_msg_cache_new ();
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -90,16 +85,21 @@ mu_msg_new_from_file (const char *path, const char *mdir, GError **err)
|
||||
{
|
||||
MuMsg *self;
|
||||
MuMsgFile *msgfile;
|
||||
|
||||
|
||||
g_return_val_if_fail (path, NULL);
|
||||
|
||||
|
||||
if (G_UNLIKELY(!_gmime_initialized)) {
|
||||
gmime_init ();
|
||||
g_atexit (gmime_uninit);
|
||||
}
|
||||
|
||||
msgfile = mu_msg_file_new (path, mdir, err);
|
||||
if (!msgfile)
|
||||
if (!msgfile)
|
||||
return NULL;
|
||||
|
||||
|
||||
self = msg_new ();
|
||||
self->_file = msgfile;
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -109,21 +109,26 @@ mu_msg_new_from_doc (XapianDocument *doc, GError **err)
|
||||
{
|
||||
MuMsg *self;
|
||||
MuMsgDoc *msgdoc;
|
||||
|
||||
|
||||
g_return_val_if_fail (doc, NULL);
|
||||
|
||||
|
||||
if (G_UNLIKELY(!_gmime_initialized)) {
|
||||
gmime_init ();
|
||||
g_atexit (gmime_uninit);
|
||||
}
|
||||
|
||||
msgdoc = mu_msg_doc_new (doc, err);
|
||||
if (!msgdoc)
|
||||
return NULL;
|
||||
|
||||
self = msg_new ();
|
||||
self->_doc = msgdoc;
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
static void
|
||||
mu_msg_destroy (MuMsg *self)
|
||||
{
|
||||
if (!self)
|
||||
@ -133,7 +138,7 @@ mu_msg_destroy (MuMsg *self)
|
||||
mu_msg_doc_destroy (self->_doc);
|
||||
|
||||
mu_msg_cache_destroy (self->_cache);
|
||||
|
||||
|
||||
g_slice_free (MuMsg, self);
|
||||
}
|
||||
|
||||
@ -144,7 +149,7 @@ mu_msg_ref (MuMsg *self)
|
||||
g_return_val_if_fail (self, NULL);
|
||||
|
||||
++self->_refcount;
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -153,8 +158,8 @@ mu_msg_unref (MuMsg *self)
|
||||
{
|
||||
g_return_if_fail (self);
|
||||
g_return_if_fail (self->_refcount >= 1);
|
||||
|
||||
if (--self->_refcount == 0)
|
||||
|
||||
if (--self->_refcount == 0)
|
||||
mu_msg_destroy (self);
|
||||
}
|
||||
|
||||
@ -167,7 +172,7 @@ get_path (MuMsg *self)
|
||||
const char *path;
|
||||
char *val;
|
||||
gboolean do_free;
|
||||
|
||||
|
||||
/* try to get the path from the cache */
|
||||
path = mu_msg_cache_str (self->_cache, MU_MSG_FIELD_ID_PATH);
|
||||
if (path)
|
||||
@ -180,14 +185,14 @@ get_path (MuMsg *self)
|
||||
val = mu_msg_doc_get_str_field (self->_doc,
|
||||
MU_MSG_FIELD_ID_PATH,
|
||||
&do_free);
|
||||
|
||||
|
||||
/* not in the cache yet? try to get it from the file backend,
|
||||
* in case we are using that */
|
||||
if (!val && self->_file)
|
||||
val = mu_msg_file_get_str_field (self->_file,
|
||||
MU_MSG_FIELD_ID_PATH,
|
||||
&do_free);
|
||||
|
||||
|
||||
/* this cannot happen unless there are bugs in mu */
|
||||
if (!val) {
|
||||
g_warning ("%s: cannot find path", __FUNCTION__);
|
||||
@ -211,7 +216,7 @@ get_msg_file (MuMsg *self)
|
||||
|
||||
if (!(path = get_path (self)))
|
||||
return NULL;
|
||||
|
||||
|
||||
err = NULL;
|
||||
mfile = mu_msg_file_new (path, NULL, &err);
|
||||
if (!mfile) {
|
||||
@ -220,7 +225,7 @@ get_msg_file (MuMsg *self)
|
||||
g_error_free (err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return mfile;
|
||||
}
|
||||
|
||||
@ -251,7 +256,7 @@ get_str_list_field (MuMsg *self, MuMsgFieldId mfid)
|
||||
val = mu_msg_file_get_str_list_field (self->_file, mfid,
|
||||
&do_free);
|
||||
}
|
||||
|
||||
|
||||
/* if we get a string that needs freeing, we tell the cache to
|
||||
* mark the string as such, so it will be freed when the cache
|
||||
* is freed (or when the value is overwritten) */
|
||||
@ -289,7 +294,7 @@ get_str_field (MuMsg *self, MuMsgFieldId mfid)
|
||||
g_warning ("%s: cannot retrieve field", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* if we get a string that needs freeing, we tell the cache to
|
||||
* mark the string as such, so it will be freed when the cache
|
||||
* is freed (or when the value is overwritten) */
|
||||
@ -301,10 +306,10 @@ static gint64
|
||||
get_num_field (MuMsg *self, MuMsgFieldId mfid)
|
||||
{
|
||||
guint64 val;
|
||||
|
||||
|
||||
if (mu_msg_cache_cached (self->_cache, mfid))
|
||||
return mu_msg_cache_num (self->_cache, mfid);
|
||||
|
||||
|
||||
/* if it's not in the cache but it is a value retrievable from
|
||||
* the doc backend, use that */
|
||||
val = -1;
|
||||
@ -341,7 +346,7 @@ mu_msg_get_header (MuMsg *self, const char *header)
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
const char*
|
||||
mu_msg_get_path (MuMsg *self)
|
||||
{
|
||||
g_return_val_if_fail (self, NULL);
|
||||
@ -349,21 +354,21 @@ mu_msg_get_path (MuMsg *self)
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
const char*
|
||||
mu_msg_get_subject (MuMsg *self)
|
||||
{
|
||||
g_return_val_if_fail (self, NULL);
|
||||
return get_str_field (self, MU_MSG_FIELD_ID_SUBJECT);
|
||||
}
|
||||
|
||||
const char*
|
||||
const char*
|
||||
mu_msg_get_msgid (MuMsg *self)
|
||||
{
|
||||
g_return_val_if_fail (self, NULL);
|
||||
return get_str_field (self, MU_MSG_FIELD_ID_MSGID);
|
||||
}
|
||||
|
||||
const char*
|
||||
const char*
|
||||
mu_msg_get_maildir (MuMsg *self)
|
||||
{
|
||||
g_return_val_if_fail (self, NULL);
|
||||
@ -371,7 +376,7 @@ mu_msg_get_maildir (MuMsg *self)
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
const char*
|
||||
mu_msg_get_from (MuMsg *self)
|
||||
{
|
||||
g_return_val_if_fail (self, NULL);
|
||||
@ -379,14 +384,14 @@ mu_msg_get_from (MuMsg *self)
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
const char*
|
||||
mu_msg_get_to (MuMsg *self)
|
||||
{
|
||||
g_return_val_if_fail (self, NULL);
|
||||
return get_str_field (self, MU_MSG_FIELD_ID_TO);
|
||||
}
|
||||
|
||||
const char*
|
||||
const char*
|
||||
mu_msg_get_cc (MuMsg *self)
|
||||
{
|
||||
g_return_val_if_fail (self, NULL);
|
||||
@ -394,7 +399,7 @@ mu_msg_get_cc (MuMsg *self)
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
const char*
|
||||
mu_msg_get_bcc (MuMsg *self)
|
||||
{
|
||||
g_return_val_if_fail (self, NULL);
|
||||
@ -504,7 +509,7 @@ mu_msg_contact_new (const char *name, const char *address,
|
||||
MuMsgContactType type)
|
||||
{
|
||||
MuMsgContact *self;
|
||||
|
||||
|
||||
g_return_val_if_fail (name, NULL);
|
||||
g_return_val_if_fail (address, NULL);
|
||||
g_return_val_if_fail (!mu_msg_contact_type_is_valid(type),
|
||||
@ -516,7 +521,7 @@ mu_msg_contact_new (const char *name, const char *address,
|
||||
self->address = g_strdup (address);
|
||||
self->type = type;
|
||||
|
||||
return self;
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@ -531,7 +536,7 @@ mu_msg_contact_destroy (MuMsgContact *self)
|
||||
g_free ((void*)self->address);
|
||||
g_slice_free (MuMsgContact, self);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static gboolean
|
||||
fill_contact (MuMsgContact *self, InternetAddress *addr,
|
||||
@ -539,10 +544,10 @@ fill_contact (MuMsgContact *self, InternetAddress *addr,
|
||||
{
|
||||
if (!addr)
|
||||
return FALSE;
|
||||
|
||||
|
||||
self->name = internet_address_get_name (addr);
|
||||
self->type = ctype;
|
||||
|
||||
self->type = ctype;
|
||||
|
||||
/* we only support internet mailbox addresses; if we don't
|
||||
* check, g_mime hits an assert
|
||||
*/
|
||||
@ -551,7 +556,7 @@ fill_contact (MuMsgContact *self, InternetAddress *addr,
|
||||
(INTERNET_ADDRESS_MAILBOX(addr));
|
||||
else
|
||||
self->address = NULL;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -561,16 +566,16 @@ address_list_foreach (InternetAddressList *addrlist, MuMsgContactType ctype,
|
||||
MuMsgContactForeachFunc func, gpointer user_data)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; addrlist && i != internet_address_list_length(addrlist);
|
||||
++i) {
|
||||
|
||||
|
||||
MuMsgContact contact;
|
||||
if (!fill_contact(&contact,
|
||||
internet_address_list_get_address (addrlist, i),
|
||||
ctype))
|
||||
continue;
|
||||
|
||||
|
||||
if (!(func)(&contact, user_data))
|
||||
break;
|
||||
}
|
||||
@ -582,10 +587,10 @@ addresses_foreach (const char* addrs, MuMsgContactType ctype,
|
||||
MuMsgContactForeachFunc func, gpointer user_data)
|
||||
{
|
||||
InternetAddressList *addrlist;
|
||||
|
||||
|
||||
if (!addrs)
|
||||
return;
|
||||
|
||||
|
||||
addrlist = internet_address_list_parse_string (addrs);
|
||||
if (addrlist) {
|
||||
address_list_foreach (addrlist, ctype, func, user_data);
|
||||
@ -595,11 +600,11 @@ addresses_foreach (const char* addrs, MuMsgContactType ctype,
|
||||
|
||||
|
||||
void
|
||||
msg_contact_foreach_file (MuMsg *msg, MuMsgContactForeachFunc func,
|
||||
msg_contact_foreach_file (MuMsg *msg, MuMsgContactForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
int i;
|
||||
struct {
|
||||
GMimeRecipientType _gmime_type;
|
||||
MuMsgContactType _type;
|
||||
} ctypes[] = {
|
||||
@ -611,7 +616,7 @@ msg_contact_foreach_file (MuMsg *msg, MuMsgContactForeachFunc func,
|
||||
/* sender */
|
||||
addresses_foreach (g_mime_message_get_sender (msg->_file->_mime_msg),
|
||||
MU_MSG_CONTACT_TYPE_FROM, func, user_data);
|
||||
|
||||
|
||||
/* get to, cc, bcc */
|
||||
for (i = 0; i != G_N_ELEMENTS(ctypes); ++i) {
|
||||
InternetAddressList *addrlist;
|
||||
@ -623,7 +628,7 @@ msg_contact_foreach_file (MuMsg *msg, MuMsgContactForeachFunc func,
|
||||
|
||||
|
||||
static void
|
||||
msg_contact_foreach_doc (MuMsg *msg, MuMsgContactForeachFunc func,
|
||||
msg_contact_foreach_doc (MuMsg *msg, MuMsgContactForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
addresses_foreach (mu_msg_get_from (msg),
|
||||
@ -638,7 +643,7 @@ msg_contact_foreach_doc (MuMsg *msg, MuMsgContactForeachFunc func,
|
||||
|
||||
|
||||
void
|
||||
mu_msg_contact_foreach (MuMsg *msg, MuMsgContactForeachFunc func,
|
||||
mu_msg_contact_foreach (MuMsg *msg, MuMsgContactForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (msg);
|
||||
@ -663,7 +668,7 @@ cmp_str (const char* s1, const char *s2)
|
||||
return -1;
|
||||
else if (!s2)
|
||||
return 1;
|
||||
|
||||
|
||||
return g_utf8_collate (s1, s2);
|
||||
}
|
||||
|
||||
@ -677,7 +682,7 @@ cmp_subject (const char* s1, const char *s2)
|
||||
return -1;
|
||||
else if (!s2)
|
||||
return 1;
|
||||
|
||||
|
||||
return g_utf8_collate (
|
||||
mu_str_subject_normalize (s1),
|
||||
mu_str_subject_normalize (s2));
|
||||
@ -690,19 +695,19 @@ mu_msg_cmp (MuMsg *m1, MuMsg *m2, MuMsgFieldId mfid)
|
||||
g_return_val_if_fail (m1, 0);
|
||||
g_return_val_if_fail (m2, 0);
|
||||
g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), 0);
|
||||
|
||||
if (mfid == MU_MSG_FIELD_ID_SUBJECT)
|
||||
|
||||
if (mfid == MU_MSG_FIELD_ID_SUBJECT)
|
||||
return cmp_subject (get_str_field (m1, mfid),
|
||||
get_str_field (m2, mfid));
|
||||
|
||||
if (mu_msg_field_is_string (mfid))
|
||||
|
||||
if (mu_msg_field_is_string (mfid))
|
||||
return cmp_str (get_str_field (m1, mfid),
|
||||
get_str_field (m2, mfid));
|
||||
|
||||
/* TODO: note, we cast (potentially > MAXINT to int) */
|
||||
if (mu_msg_field_is_numeric (mfid))
|
||||
if (mu_msg_field_is_numeric (mfid))
|
||||
return get_num_field(m1, mfid) - get_num_field(m2, mfid);
|
||||
|
||||
|
||||
return 0; /* TODO: handle lists */
|
||||
}
|
||||
|
||||
@ -711,7 +716,7 @@ gboolean
|
||||
mu_msg_is_readable (MuMsg *self)
|
||||
{
|
||||
g_return_val_if_fail (self, FALSE);
|
||||
|
||||
|
||||
return (access (get_str_field (self, MU_MSG_FIELD_ID_PATH), R_OK)
|
||||
== 0) ? TRUE : FALSE;
|
||||
}
|
||||
@ -726,7 +731,7 @@ mu_msg_move_to_maildir (MuMsg *self, const char* targetmdir,
|
||||
MuFlags flags, gboolean ignore_dups, GError **err)
|
||||
{
|
||||
char *newfullpath;
|
||||
|
||||
|
||||
g_return_val_if_fail (self, FALSE);
|
||||
|
||||
newfullpath = mu_maildir_move_message (mu_msg_get_path (self),
|
||||
@ -735,7 +740,7 @@ mu_msg_move_to_maildir (MuMsg *self, const char* targetmdir,
|
||||
if (newfullpath) /* update our path to new one... */
|
||||
mu_msg_cache_set_str (self->_cache, MU_MSG_FIELD_ID_PATH, newfullpath,
|
||||
TRUE); /* the cache will free the string */
|
||||
|
||||
|
||||
return newfullpath ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
|
||||
135
src/mu-query.cc
135
src/mu-query.cc
@ -1,20 +1,20 @@
|
||||
/*
|
||||
/*
|
||||
** Copyright (C) 2008-2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation; either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program; if not, write to the Free Software Foundation,
|
||||
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**
|
||||
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
@ -48,16 +48,16 @@ public:
|
||||
|
||||
if (!clear_prefix (begin))
|
||||
return Xapian::BAD_VALUENO;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
begin = to_sortable (begin, true);
|
||||
end = to_sortable (end, false);
|
||||
|
||||
if (begin > end)
|
||||
|
||||
if (begin > end)
|
||||
throw Xapian::QueryParserError
|
||||
("end time is before begin");
|
||||
|
||||
|
||||
return (Xapian::valueno)MU_MSG_FIELD_ID_DATE;
|
||||
}
|
||||
private:
|
||||
@ -65,18 +65,18 @@ private:
|
||||
|
||||
const char* str;
|
||||
time_t t;
|
||||
|
||||
|
||||
str = mu_date_interpret_s (s.c_str(), is_begin ? TRUE: FALSE);
|
||||
str = mu_date_complete_s (str, is_begin ? TRUE: FALSE);
|
||||
t = mu_date_str_to_time_t (str, TRUE /*local*/);
|
||||
str = mu_date_time_t_to_str (t, FALSE /*UTC*/);
|
||||
|
||||
|
||||
return s = std::string(str);
|
||||
}
|
||||
|
||||
|
||||
bool clear_prefix (std::string& begin) {
|
||||
|
||||
|
||||
const std::string colon (":");
|
||||
const std::string name (mu_msg_field_name
|
||||
(MU_MSG_FIELD_ID_DATE) + colon);
|
||||
@ -91,10 +91,10 @@ private:
|
||||
begin.erase (0, shortcut.length());
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -103,12 +103,12 @@ public:
|
||||
MuSizeRangeProcessor():
|
||||
Xapian::NumberValueRangeProcessor(MU_MSG_FIELD_ID_SIZE) {
|
||||
}
|
||||
|
||||
|
||||
Xapian::valueno operator()(std::string &begin, std::string &end) {
|
||||
|
||||
|
||||
if (!clear_prefix (begin))
|
||||
return Xapian::BAD_VALUENO;
|
||||
|
||||
|
||||
if (!substitute_size (begin) || !substitute_size (end))
|
||||
return Xapian::BAD_VALUENO;
|
||||
|
||||
@ -118,19 +118,19 @@ public:
|
||||
|
||||
begin = Xapian::sortable_serialise (atol(begin.c_str()));
|
||||
end = Xapian::sortable_serialise (atol(end.c_str()));
|
||||
|
||||
|
||||
return (Xapian::valueno)MU_MSG_FIELD_ID_SIZE;
|
||||
}
|
||||
private:
|
||||
bool clear_prefix (std::string& begin) {
|
||||
|
||||
|
||||
const std::string colon (":");
|
||||
const std::string name (mu_msg_field_name
|
||||
(MU_MSG_FIELD_ID_SIZE) + colon);
|
||||
const std::string shortcut (
|
||||
std::string(1, mu_msg_field_shortcut
|
||||
(MU_MSG_FIELD_ID_SIZE)) + colon);
|
||||
|
||||
|
||||
if (begin.find (name) == 0) {
|
||||
begin.erase (0, name.length());
|
||||
return true;
|
||||
@ -138,9 +138,9 @@ private:
|
||||
begin.erase (0, shortcut.length());
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool substitute_size (std::string& size) {
|
||||
gchar str[16];
|
||||
gint64 num = mu_str_size_parse_bkm(size.c_str());
|
||||
@ -157,19 +157,27 @@ private:
|
||||
static void add_prefix (MuMsgFieldId field, Xapian::QueryParser* qparser);
|
||||
|
||||
struct _MuQuery {
|
||||
_MuQuery (const char* dbpath):
|
||||
_db (Xapian::Database(dbpath)) {
|
||||
|
||||
_MuQuery (const char* dbpath) {
|
||||
init ((Xapian::Database(dbpath)));
|
||||
}
|
||||
|
||||
_MuQuery (Xapian::Database* db) {
|
||||
init (*db);
|
||||
}
|
||||
|
||||
void init (Xapian::Database db) {
|
||||
|
||||
_db = db;
|
||||
_qparser.set_database (_db);
|
||||
_qparser.set_default_op (Xapian::Query::OP_AND);
|
||||
|
||||
_qparser.add_valuerangeprocessor (&_date_range_processor);
|
||||
_qparser.add_valuerangeprocessor (&_size_range_processor);
|
||||
|
||||
|
||||
mu_msg_field_foreach ((MuMsgFieldForEachFunc)add_prefix,
|
||||
&_qparser);
|
||||
}
|
||||
|
||||
|
||||
Xapian::Database _db;
|
||||
Xapian::QueryParser _qparser;
|
||||
MuDateRangeProcessor _date_range_processor;
|
||||
@ -180,8 +188,8 @@ static const Xapian::Query
|
||||
get_query (MuQuery *mqx, const char* searchexpr, GError **err)
|
||||
{
|
||||
Xapian::Query query;
|
||||
char *preprocessed;
|
||||
|
||||
char *preprocessed;
|
||||
|
||||
preprocessed = mu_query_preprocess (searchexpr);
|
||||
|
||||
try {
|
||||
@ -194,7 +202,7 @@ get_query (MuQuery *mqx, const char* searchexpr, GError **err)
|
||||
Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE);
|
||||
g_free (preprocessed);
|
||||
return query;
|
||||
|
||||
|
||||
} catch (...) {
|
||||
/* some error occured */
|
||||
g_set_error (err, 0, MU_ERROR_XAPIAN_QUERY,
|
||||
@ -213,13 +221,13 @@ add_prefix (MuMsgFieldId mfid, Xapian::QueryParser* qparser)
|
||||
!mu_msg_field_xapian_term(mfid) &&
|
||||
!mu_msg_field_xapian_contact(mfid))
|
||||
return;
|
||||
|
||||
|
||||
try {
|
||||
const std::string pfx
|
||||
(1, mu_msg_field_xapian_prefix (mfid));
|
||||
const std::string shortcut
|
||||
(1, mu_msg_field_shortcut (mfid));
|
||||
|
||||
|
||||
if (mu_msg_field_uses_boolean_prefix (mfid)) {
|
||||
qparser->add_boolean_prefix
|
||||
(mu_msg_field_name(mfid), pfx);
|
||||
@ -229,8 +237,8 @@ add_prefix (MuMsgFieldId mfid, Xapian::QueryParser* qparser)
|
||||
(mu_msg_field_name(mfid), pfx);
|
||||
qparser->add_prefix (shortcut, pfx);
|
||||
}
|
||||
|
||||
if (!mu_msg_field_needs_prefix(mfid))
|
||||
|
||||
if (!mu_msg_field_needs_prefix(mfid))
|
||||
qparser->add_prefix ("", pfx);
|
||||
|
||||
} MU_XAPIAN_CATCH_BLOCK;
|
||||
@ -240,33 +248,58 @@ MuQuery*
|
||||
mu_query_new (const char* xpath, GError **err)
|
||||
{
|
||||
g_return_val_if_fail (xpath, NULL);
|
||||
|
||||
|
||||
if (!mu_util_check_dir (xpath, TRUE, FALSE)) {
|
||||
g_set_error (err, 0, MU_ERROR_XAPIAN_DIR_NOT_ACCESSIBLE,
|
||||
"'%s' is not a readable xapian dir", xpath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mu_util_xapian_needs_upgrade (xpath)) {
|
||||
|
||||
if (mu_store_database_needs_upgrade (xpath)) {
|
||||
g_set_error (err, 0, MU_ERROR_XAPIAN_NOT_UP_TO_DATE,
|
||||
"%s is not up-to-date, needs a full update",
|
||||
xpath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mu_util_xapian_is_empty (xpath))
|
||||
if (mu_store_database_is_empty (xpath))
|
||||
g_warning ("database %s is empty; nothing to do", xpath);
|
||||
|
||||
try {
|
||||
|
||||
return new MuQuery (xpath);
|
||||
|
||||
} MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN (err, MU_ERROR_XAPIAN, NULL);
|
||||
} MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN (err, MU_ERROR_XAPIAN, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
MuQuery*
|
||||
mu_query_new_from_store (MuStore *store, GError **err)
|
||||
{
|
||||
g_return_val_if_fail (store, NULL);
|
||||
|
||||
try {
|
||||
XapianDatabase *db;
|
||||
|
||||
db = mu_store_get_read_only_database(store);
|
||||
|
||||
return new MuQuery (reinterpret_cast<Xapian::Database*>(db));
|
||||
|
||||
} MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN (err, MU_ERROR_XAPIAN, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
MuQuery *mu_query_new_from_store (MuStore *store, GError **err)
|
||||
G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
mu_query_destroy (MuQuery *self)
|
||||
{
|
||||
@ -282,13 +315,13 @@ mu_query_preprocess (const char *query)
|
||||
|
||||
g_return_val_if_fail (query, NULL);
|
||||
my_query = g_strdup (query);
|
||||
|
||||
|
||||
/* remove accents and turn to lower-case */
|
||||
mu_str_normalize_in_place (my_query, TRUE);
|
||||
/* escape '@', single '_' and ':' if it's not following a
|
||||
* xapian-pfx with '_' */
|
||||
mu_str_ascii_xapian_escape_in_place (my_query);
|
||||
|
||||
|
||||
return my_query;
|
||||
}
|
||||
|
||||
@ -296,10 +329,10 @@ mu_query_preprocess (const char *query)
|
||||
MuMsgIter*
|
||||
mu_query_run (MuQuery *self, const char* searchexpr, gboolean threads,
|
||||
MuMsgFieldId sortfieldid, gboolean ascending,
|
||||
GError **err)
|
||||
GError **err)
|
||||
{
|
||||
g_return_val_if_fail (self, NULL);
|
||||
g_return_val_if_fail (searchexpr, NULL);
|
||||
g_return_val_if_fail (searchexpr, NULL);
|
||||
g_return_val_if_fail (mu_msg_field_id_is_valid (sortfieldid) ||
|
||||
sortfieldid == MU_MSG_FIELD_ID_NONE,
|
||||
NULL);
|
||||
@ -319,25 +352,25 @@ mu_query_run (MuQuery *self, const char* searchexpr, gboolean threads,
|
||||
|
||||
|
||||
enq.set_cutoff(0,0);
|
||||
|
||||
|
||||
return mu_msg_iter_new (
|
||||
(XapianEnquire*)&enq,
|
||||
self->_db.get_doccount(), threads,
|
||||
threads ? sortfieldid : MU_MSG_FIELD_ID_NONE);
|
||||
|
||||
|
||||
} MU_XAPIAN_CATCH_BLOCK_RETURN(NULL);
|
||||
}
|
||||
|
||||
char*
|
||||
mu_query_as_string (MuQuery *self, const char *searchexpr, GError **err)
|
||||
mu_query_as_string (MuQuery *self, const char *searchexpr, GError **err)
|
||||
{
|
||||
g_return_val_if_fail (self, NULL);
|
||||
g_return_val_if_fail (searchexpr, NULL);
|
||||
|
||||
|
||||
try {
|
||||
Xapian::Query query (get_query(self, searchexpr, err));
|
||||
Xapian::Query query (get_query(self, searchexpr, err));
|
||||
return g_strdup(query.get_description().c_str());
|
||||
|
||||
|
||||
} MU_XAPIAN_CATCH_BLOCK_RETURN(NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -21,8 +21,9 @@
|
||||
#define __MU_QUERY_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <mu-store.h>
|
||||
#include <mu-msg-iter.h>
|
||||
#include <mu-util.h> /* for MuResult, MuError */
|
||||
#include <mu-util.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -45,6 +46,25 @@ typedef struct _MuQuery MuQuery;
|
||||
MuQuery *mu_query_new (const char* path, GError **err)
|
||||
G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
|
||||
/**
|
||||
* create a new MuQuery instance using an existing MuStore
|
||||
*
|
||||
* @param store a valid MuStore object
|
||||
* @param err receives error information (if there is any); if
|
||||
* function returns non-NULL, err will _not_be set. err can be NULL
|
||||
* possble errors (err->code) are MU_ERROR_XAPIAN_DIR and
|
||||
* MU_ERROR_XAPIAN_NOT_UPTODATE
|
||||
*
|
||||
* @return a new MuQuery instance, or NULL in case of error.
|
||||
* when the instance is no longer needed, use mu_query_destroy
|
||||
* to free it
|
||||
*/
|
||||
MuQuery *mu_query_new_from_store (MuStore *store, GError **err)
|
||||
G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* destroy the MuQuery instance
|
||||
*
|
||||
|
||||
140
src/mu-util.h
140
src/mu-util.h
@ -33,7 +33,7 @@ G_BEGIN_DECLS
|
||||
* do system-specific initialization. should be called before anything
|
||||
* else. Initializes the locale and Gtype. Note: this function is
|
||||
* called by mu_runtime_init.
|
||||
*
|
||||
*
|
||||
* @return TRUE if is succeeds, FALSE otherwise
|
||||
*/
|
||||
gboolean mu_util_init_system (void);
|
||||
@ -43,7 +43,7 @@ gboolean mu_util_init_system (void);
|
||||
* path does not have to exist
|
||||
*
|
||||
* @param path path to expand
|
||||
*
|
||||
*
|
||||
* @return the expanded path as a newly allocated string, or NULL in
|
||||
* case of error
|
||||
*/
|
||||
@ -53,7 +53,7 @@ char* mu_util_dir_expand (const char* path)
|
||||
/**
|
||||
* guess the maildir; first try $MAILDIR; if it is unset or
|
||||
* non-existant, try ~/Maildir if both fail, return NULL
|
||||
*
|
||||
*
|
||||
* @return full path of the guessed Maildir, or NULL; must be freed (gfree)
|
||||
*/
|
||||
char* mu_util_guess_maildir (void)
|
||||
@ -64,7 +64,7 @@ char* mu_util_guess_maildir (void)
|
||||
* guess the place of the mu homedir (typically, ~/.mu). Note, this
|
||||
* directory does not necessarily exist. mu_util_check_dir can be use
|
||||
* to check that
|
||||
*
|
||||
*
|
||||
* @return the guessed mu homedir, which needs to be freed with g_free
|
||||
* when no longer needed.
|
||||
*/
|
||||
@ -74,11 +74,11 @@ gchar* mu_util_guess_mu_homedir (void)
|
||||
/**
|
||||
* if path exists, check that's a read/writeable dir; otherwise try to
|
||||
* create it (with perms 0700)
|
||||
*
|
||||
*
|
||||
* @param path path to the dir
|
||||
* @param mode to set for the dir (as per chmod(1))
|
||||
* @param nowarn, if TRUE, don't write warnings (if any) to stderr
|
||||
*
|
||||
*
|
||||
* @return TRUE if a read/writeable directory `path' exists after
|
||||
* leaving this function, FALSE otherwise
|
||||
*/
|
||||
@ -88,11 +88,11 @@ gboolean mu_util_create_dir_maybe (const gchar *path, mode_t mode, gboolean nowa
|
||||
/**
|
||||
* check whether path is a directory, and optionally, if it's readable
|
||||
* and/or writeable
|
||||
*
|
||||
*
|
||||
* @param path dir path
|
||||
* @param readable check for readability
|
||||
* @param writeable check for writability
|
||||
*
|
||||
*
|
||||
* @return TRUE if dir exist and has the specified properties
|
||||
*/
|
||||
gboolean mu_util_check_dir (const gchar* path, gboolean readable,
|
||||
@ -102,8 +102,8 @@ gboolean mu_util_check_dir (const gchar* path, gboolean readable,
|
||||
|
||||
/**
|
||||
* get our the cache directory, typically, /tmp/mu-<userid>/
|
||||
*
|
||||
* @return the cache directory; don't free
|
||||
*
|
||||
* @return the cache directory; don't free
|
||||
*/
|
||||
const char* mu_util_cache_dir (void) G_GNUC_CONST;
|
||||
|
||||
@ -112,11 +112,11 @@ const char* mu_util_cache_dir (void) G_GNUC_CONST;
|
||||
/**
|
||||
* create a writeable file and return its file descriptor (which
|
||||
* you'll need to close(2) when done with it.)
|
||||
*
|
||||
*
|
||||
* @param path the full path of the file to create
|
||||
* @param the mode to open (ie. 0644 or 0600 etc., see chmod(3)
|
||||
* @param overwrite should we allow for overwriting existing files?
|
||||
*
|
||||
*
|
||||
* @return a file descriptor, or -1 in case of error. If it's a file
|
||||
* system error, 'errno' may contain more info. use 'close()' when done
|
||||
* with the file descriptor
|
||||
@ -129,17 +129,17 @@ int mu_util_create_writeable_fd (const char* path, mode_t mode,
|
||||
/**
|
||||
* check if file is local, ie. on the local file system. this means
|
||||
* that it's either having a file URI, *or* that it's an existing file
|
||||
*
|
||||
*
|
||||
* @param path a path
|
||||
*
|
||||
*
|
||||
* @return TRUE if the file is local, FALSE otherwise
|
||||
*/
|
||||
gboolean mu_util_is_local_file (const char* path);
|
||||
|
||||
|
||||
/**
|
||||
* is the current locale utf-8 compatible?
|
||||
*
|
||||
* is the current locale utf-8 compatible?
|
||||
*
|
||||
* @return TRUE if it's utf8 compatible, FALSE otherwise
|
||||
*/
|
||||
gboolean mu_util_locale_is_utf8 (void) G_GNUC_CONST;
|
||||
@ -148,10 +148,10 @@ gboolean mu_util_locale_is_utf8 (void) G_GNUC_CONST;
|
||||
/**
|
||||
* write a string (assumed to be in utf8-format) to a stream,
|
||||
* converted to the current locale
|
||||
*
|
||||
*
|
||||
* @param str a string
|
||||
* @param stream a stream
|
||||
*
|
||||
*
|
||||
* @return TRUE if printing worked, FALSE otherwise
|
||||
*/
|
||||
gboolean mu_util_fputs_encoded (const char *str, FILE *stream);
|
||||
@ -159,9 +159,9 @@ gboolean mu_util_fputs_encoded (const char *str, FILE *stream);
|
||||
/**
|
||||
* print a formatted string (assumed to be in utf8-format) to stdout,
|
||||
* converted to the current locale
|
||||
*
|
||||
*
|
||||
* @param a standard printf() format string, followed by a parameter list
|
||||
*
|
||||
*
|
||||
* @return TRUE if printing worked, FALSE otherwise
|
||||
*/
|
||||
gboolean mu_util_print_encoded (const char *frm, ...) G_GNUC_PRINTF(1,2);
|
||||
@ -169,9 +169,9 @@ gboolean mu_util_print_encoded (const char *frm, ...) G_GNUC_PRINTF(1,2);
|
||||
/**
|
||||
* print a formatted string (assumed to be in utf8-format) to stderr,
|
||||
* converted to the current locale
|
||||
*
|
||||
*
|
||||
* @param a standard printf() format string, followed by a parameter list
|
||||
*
|
||||
*
|
||||
* @return TRUE if printing worked, FALSE otherwise
|
||||
*/
|
||||
gboolean mu_util_printerr_encoded (const char *frm, ...) G_GNUC_PRINTF(1,2);
|
||||
@ -181,82 +181,23 @@ gboolean mu_util_printerr_encoded (const char *frm, ...) G_GNUC_PRINTF(1,2);
|
||||
/**
|
||||
* try to 'play' (ie., open with it's associated program) a
|
||||
* file. depends on xdg-open to do the actual opening
|
||||
*
|
||||
*
|
||||
* @param path full path of the file to open
|
||||
* @param allow_local allow local files (ie. with file:// prefix or fs paths)
|
||||
* @param allow_remote allow URIs (ie., http, mailto)
|
||||
*
|
||||
*
|
||||
* @return TRUE if it succeeded, FALSE otherwise
|
||||
*/
|
||||
gboolean mu_util_play (const char *path,
|
||||
gboolean allow_local, gboolean allow_remote);
|
||||
|
||||
|
||||
/**
|
||||
" * get the version of the xapian database (ie., the version of the
|
||||
* 'schema' we are using). If this version != MU_XAPIAN_DB_VERSION,
|
||||
* it's means we need to a full reindex.
|
||||
*
|
||||
* @param xpath path to the xapian database
|
||||
*
|
||||
* @return the version of the database as a newly allocated string
|
||||
* (free with g_free); if there is no version yet, it will return NULL
|
||||
*/
|
||||
gchar* mu_util_xapian_dbversion (const gchar *xpath) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
|
||||
/**
|
||||
* check whether the database needs to be upgraded, e.g., when it was
|
||||
* created with a different version of mu
|
||||
*
|
||||
* @param xpath path to the database dir
|
||||
*
|
||||
* @return TRUE if the database needs upgrading, FALSE otherwise
|
||||
*/
|
||||
gboolean mu_util_xapian_needs_upgrade (const gchar *xpath);
|
||||
|
||||
|
||||
/**
|
||||
* check whether the database is empty (contains 0 documents); in
|
||||
* addition, a non-existing database is considered 'empty' too
|
||||
*
|
||||
* @param xpath path to the xapian database
|
||||
*
|
||||
* @return TRUE if the database is empty, FALSE otherwise
|
||||
*/
|
||||
gboolean mu_util_xapian_is_empty (const gchar *xpath);
|
||||
|
||||
|
||||
/**
|
||||
* clear the database, ie., remove all of the contents. This is a
|
||||
* destructive operation, but the database can be restored be doing a
|
||||
* full scan of the maildirs. Also, clear the contacts cache file
|
||||
*
|
||||
* @param xpath path to the database
|
||||
* @param ccache path to the contacts cache file
|
||||
*
|
||||
* @return TRUE if the clearing succeeded, FALSE otherwise.
|
||||
*/
|
||||
gboolean mu_util_xapian_clear (const gchar *xpath,
|
||||
const gchar *ccache);
|
||||
|
||||
|
||||
/**
|
||||
* check if the database is locked for writing
|
||||
*
|
||||
* @param xpath path to a xapian database
|
||||
*
|
||||
* @return TRUE if it is locked, FALSE otherwise (or in case of error)
|
||||
*/
|
||||
gboolean mu_util_xapian_is_locked (const gchar *xpath);
|
||||
|
||||
|
||||
/**
|
||||
* convert a string array in to a string, with the elements separated
|
||||
* by ' '
|
||||
*
|
||||
*
|
||||
* @param params a non-NULL, NULL-terminated string array
|
||||
*
|
||||
*
|
||||
* @return a newly allocated string
|
||||
*/
|
||||
gchar* mu_util_str_from_strv (const gchar **params)
|
||||
@ -292,9 +233,9 @@ enum {
|
||||
/**
|
||||
* get the d_type (as in direntry->d_type) for the file at path, using
|
||||
* lstat(3)
|
||||
*
|
||||
*
|
||||
* @param path full path
|
||||
*
|
||||
*
|
||||
* @return DT_REG, DT_DIR, DT_LNK, or DT_UNKNOWN (other values are not
|
||||
* supported currently )
|
||||
*/
|
||||
@ -303,20 +244,23 @@ unsigned char mu_util_get_dtype_with_lstat (const char *path);
|
||||
|
||||
/**
|
||||
* we need this when using Xapian::Document* from C
|
||||
*
|
||||
*
|
||||
*/
|
||||
typedef gpointer XapianDocument;
|
||||
|
||||
/**
|
||||
* we need this when using Xapian::Enquire* from C
|
||||
*
|
||||
*
|
||||
*/
|
||||
typedef gpointer XapianEnquire;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* don't repeat these catch blocks everywhere...
|
||||
*
|
||||
*
|
||||
*/
|
||||
#define MU_XAPIAN_CATCH_BLOCK \
|
||||
catch (const Xapian::Error &xerr) { \
|
||||
@ -396,13 +340,13 @@ typedef gpointer XapianEnquire;
|
||||
enum _MuError {
|
||||
/* no error at all! */
|
||||
MU_OK = 0,
|
||||
|
||||
|
||||
/* generic error */
|
||||
MU_ERROR = 1,
|
||||
MU_ERROR_IN_PARAMETERS = 2,
|
||||
MU_ERROR_INTERNAL = 3,
|
||||
MU_ERROR_INTERNAL = 3,
|
||||
MU_ERROR_NO_MATCHES = 4,
|
||||
|
||||
|
||||
/* general xapian related error */
|
||||
MU_ERROR_XAPIAN = 11,
|
||||
|
||||
@ -420,15 +364,15 @@ enum _MuError {
|
||||
MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK = 18,
|
||||
|
||||
/* GMime related errors */
|
||||
|
||||
|
||||
/* gmime parsing related error */
|
||||
MU_ERROR_GMIME = 30,
|
||||
|
||||
/* contacts related errors */
|
||||
MU_ERROR_CONTACTS = 50,
|
||||
MU_ERROR_CONTACTS_CANNOT_RETRIEVE = 51,
|
||||
|
||||
|
||||
|
||||
|
||||
/* File errors */
|
||||
/* generic file-related error */
|
||||
MU_ERROR_FILE = 70,
|
||||
@ -442,7 +386,7 @@ enum _MuError {
|
||||
MU_ERROR_FILE_READDIR_FAILED = 78,
|
||||
MU_ERROR_FILE_INVALID_SOURCE = 79,
|
||||
MU_ERROR_FILE_TARGET_EQUALS_SOURCE = 80,
|
||||
|
||||
|
||||
/* not really an error, used in callbacks */
|
||||
MU_STOP = 99,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user