update cfind, server for new contacts-cache

Use the new APIs.
This commit is contained in:
djcb 2019-04-28 13:58:34 +03:00
parent 8193cc3e4c
commit e9a0939f8f
7 changed files with 1266 additions and 1262 deletions

View File

@ -1,4 +1,4 @@
.TH MU CFIND 1 "May 2013" "User Manuals" .TH MU CFIND 1 "April 2019" "User Manuals"
.SH NAME .SH NAME
@ -38,10 +38,9 @@ would find all contacts with a gmail-address, while
lists all contacts with Mary in either name or e-mail address. lists all contacts with Mary in either name or e-mail address.
If you do not specify a search expression, \fBmu cfind\fR returns the full If you do not specify a search expression, \fBmu cfind\fR returns the full list
list of contacts. Note, \fBmu cfind\fR does not use the of contacts. Note, \fBmu cfind\fR uses a cache with the e-mail information,
database, but uses a cache file with e-mail addresses, which is populated which is populated during the indexing process.
during the indexing process.
The regular expressions are Perl-compatible (as per the PCRE-library used by The regular expressions are Perl-compatible (as per the PCRE-library used by
GRegex). GRegex).
@ -65,25 +64,24 @@ sets the output format to the given value. The following are available:
.fi .fi
(*) CSV is not really standardized, but \fBmu cfind\fR follows some common (*) CSV is not fully standardized, but \fBmu cfind\fR follows some common
practices: any double-quote is replaced by a double-double quote (thus, practices: any double-quote is replaced by a double-double quote (thus, "hello"
"hello" become ""hello"", and fields with commas are put in become ""hello"", and fields with commas are put in double-quotes. Normally,
double-quotes. Normally, this should only apply to name fields. this should only apply to name fields.
.TP .TP
\fB\-\-personal\fR only show addresses seen in messages where one of 'my' \fB\-\-personal\fR only show addresses seen in messages where one of 'my' e-mail
e-mail addresses was seen in one of the address fields; this is to exclude addresses was seen in one of the address fields; this is to exclude addresses
addresses only seen in mailing-list messages. See the \fB\-\-my-address\fR only seen in mailing-list messages. See the \fB\-\-my-address\fR parameter in
parameter in \fBmu index\fR. \fBmu index\fR.
.TP .TP
\fB\-\-after=\fR\fI<timestamp>\fR only show addresses last seen after \fB\-\-after=\fR\fI<timestamp>\fR only show addresses last seen after
\fI<timestamp>\fR. \fI<timestamp>\fR is a UNIX \fBtime_t\fR value, the number \fI<timestamp>\fR. \fI<timestamp>\fR is a UNIX \fBtime_t\fR value, the number of
of seconds since 1970-01-01 (in UTC). seconds since 1970-01-01 (in UTC).
From the command line, you can use the \fBdate\fR command to get this From the command line, you can use the \fBdate\fR command to get this value. For
value. For example, only consider addresses last seen after 2009-06-01, you example, only consider addresses last seen after 2009-06-01, you could specify
could specify
.nf .nf
--after=`date +%s --date='2009-06-01'` --after=`date +%s --date='2009-06-01'`
.fi .fi
@ -103,15 +101,15 @@ contact was found. Anything else leads to a non-zero return value:
.SH INTEGRATION WITH MUTT .SH INTEGRATION WITH MUTT
You can use \fBmu cfind\fR as an external address book server for You can use \fBmu cfind\fR as an external address book server for \fBmutt\fR.
\fBmutt\fR. For this to work, add the following to your \fImuttrc\fR: For this to work, add the following to your \fImuttrc\fR:
.nf .nf
set query_command = "mu cfind --format=mutt-ab '%s'" set query_command = "mu cfind --format=mutt-ab '%s'"
.fi .fi
Now, in mutt, you can easily search for e-mail addresses using the Now, in mutt, you can search for e-mail addresses using the \fBquery\fR-command,
\fBquery\fR-command, which is (by default) accessible by pressing \fBQ\fR. which is (by default) accessible by pressing \fBQ\fR.
.SH ENCODING .SH ENCODING
@ -121,8 +119,7 @@ output-file, so emacs/bbdb can handle things correctly, without guessing.
.SH BUGS .SH BUGS
Please report bugs if you find them at Please report bugs if you find them at \fBhttps://github.com/djcb/mu/issues\fR.
\fBhttps://github.com/djcb/mu/issues\fR.
.SH AUTHOR .SH AUTHOR

View File

@ -1,25 +1,22 @@
/* /*
** Copyright (C) 2011-2016 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ** Copyright (C) 2011-2019 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** **
** This program is free software; you can redistribute it and/or modify it ** This program is free software; you can redistribute it and/or modify it under
** under the terms of the GNU General Public License as published by the ** the terms of the GNU General Public License as published by the Free Software
** Free Software Foundation; either version 3, or (at your option) any ** Foundation; either version 3, or (at your option) any later version.
** later version.
** **
** This program is distributed in the hope that it will be useful, ** This program is distributed in the hope that it will be useful, but WITHOUT
** but WITHOUT ANY WARRANTY; without even the implied warranty of ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
** GNU General Public License for more details. ** details.
** **
** You should have received a copy of the GNU General Public License ** You should have received a copy of the GNU General Public License along with
** along with this program; if not, write to the Free Software Foundation, ** this program; if not, write to the Free Software Foundation, Inc., 51
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
** **
*/ */
#if HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif /*HAVE_CONFIG_H*/
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -219,6 +216,7 @@ static void
each_contact_mutt_alias (const char *email, const char *name, each_contact_mutt_alias (const char *email, const char *name,
GHashTable *nicks) GHashTable *nicks)
{ {
gchar *nick; gchar *nick;
if (!name) if (!name)
@ -309,13 +307,17 @@ typedef struct {
MuConfigFormat format; MuConfigFormat format;
gboolean color, personal; gboolean color, personal;
time_t after; time_t after;
GRegex *rx;
GHashTable *nicks; GHashTable *nicks;
size_t n;
} ECData; } ECData;
static void static void
each_contact (const char *email, const char *name, gboolean personal, each_contact (const char *full_address,
time_t tstamp, unsigned freq, ECData *ecdata) const char *email, const char *name, gboolean personal,
time_t last_seen, size_t freq, gint64 tstamp,
ECData *ecdata)
{ {
if (ecdata->personal && !personal) if (ecdata->personal && !personal)
return; return;
@ -323,6 +325,13 @@ each_contact (const char *email, const char *name, gboolean personal,
if (tstamp < ecdata->after) if (tstamp < ecdata->after)
return; return;
if (ecdata->rx &&
!g_regex_match (ecdata->rx, email, 0, NULL) &&
!g_regex_match (ecdata->rx, name ? name : "", 0, NULL))
return;
++ecdata->n;
switch (ecdata->format) { switch (ecdata->format) {
case MU_CONFIG_FORMAT_MUTT_ALIAS: case MU_CONFIG_FORMAT_MUTT_ALIAS:
each_contact_mutt_alias (email, name, ecdata->nicks); each_contact_mutt_alias (email, name, ecdata->nicks);
@ -338,11 +347,24 @@ each_contact (const char *email, const char *name, gboolean personal,
each_contact_org_contact (email, name); each_contact_org_contact (email, name);
break; break;
case MU_CONFIG_FORMAT_BBDB: case MU_CONFIG_FORMAT_BBDB:
each_contact_bbdb (email, name, tstamp); each_contact_bbdb (email, name, last_seen);
break; break;
case MU_CONFIG_FORMAT_CSV: case MU_CONFIG_FORMAT_CSV:
each_contact_csv (email, name); each_contact_csv (email, name);
break; break;
case MU_CONFIG_FORMAT_DEBUG: {
char datebuf[32];
strftime(datebuf, sizeof(datebuf), "%F %T",
gmtime(&last_seen));
g_print ("%s\n\tname: %s\n\t%s\n\tpersonal: %s\n\tfreq: %zu\n"
"\tlast-seen: %s\n",
email,
name ? name : "<none>",
full_address,
personal ? "yes" : "no",
freq,
datebuf);
} break;
default: default:
print_plain (email, name, ecdata->color); print_plain (email, name, ecdata->color);
} }
@ -350,41 +372,45 @@ each_contact (const char *email, const char *name, gboolean personal,
static MuError static MuError
run_cmd_cfind (const char* pattern, run_cmd_cfind (MuStore *store,
gboolean personal, time_t after, const char* pattern,
gboolean personal,
time_t after,
MuConfigFormat format, MuConfigFormat format,
gboolean color, GError **err) gboolean color,
GError **err)
{ {
gboolean rv; gboolean rv;
MuContacts *contacts; MuContacts *contacts;
size_t num;
ECData ecdata; ECData ecdata;
memset(&ecdata, 0, sizeof(ecdata));
if (pattern) {
ecdata.rx = g_regex_new (pattern,
G_REGEX_CASELESS|G_REGEX_OPTIMIZE,
0, err);
if (!ecdata.rx)
return MU_ERROR_CONTACTS;
}
ecdata.personal = personal; ecdata.personal = personal;
ecdata.n = 0;
ecdata.after = after; ecdata.after = after;
ecdata.format = format; ecdata.format = format;
ecdata.color = color; ecdata.color = color;
ecdata.nicks = g_hash_table_new_full (g_str_hash, g_str_equal, ecdata.nicks = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL); g_free, NULL);
contacts = mu_contacts_new
(mu_runtime_path(MU_RUNTIME_PATH_CONTACTS));
if (!contacts) {
g_set_error (err, MU_ERROR_DOMAIN,
MU_ERROR_CONTACTS_CANNOT_RETRIEVE,
"could not retrieve contacts");
return MU_ERROR_CONTACTS_CANNOT_RETRIEVE;
}
print_header (format); print_header (format);
rv = mu_contacts_foreach (contacts, rv = mu_contacts_foreach (mu_store_contacts(store),
(MuContactsForeachFunc)each_contact, (MuContactsForeachFunc)each_contact, &ecdata);
&ecdata, pattern, &num);
g_hash_table_unref (ecdata.nicks); g_hash_table_unref (ecdata.nicks);
mu_contacts_destroy (contacts);
if (ecdata.rx)
g_regex_unref (ecdata.rx);
if (num == 0) { if (ecdata.n == 0) {
g_warning ("no matching contacts found"); g_warning ("no matching contacts found");
return MU_ERROR_NO_MATCHES; return MU_ERROR_NO_MATCHES;
} }
@ -403,6 +429,7 @@ cfind_params_valid (MuConfig *opts)
case MU_CONFIG_FORMAT_BBDB: case MU_CONFIG_FORMAT_BBDB:
case MU_CONFIG_FORMAT_CSV: case MU_CONFIG_FORMAT_CSV:
case MU_CONFIG_FORMAT_ORG_CONTACT: case MU_CONFIG_FORMAT_ORG_CONTACT:
case MU_CONFIG_FORMAT_DEBUG:
break; break;
default: default:
g_warning ("invalid output format %s", g_warning ("invalid output format %s",
@ -419,10 +446,10 @@ cfind_params_valid (MuConfig *opts)
return TRUE; return TRUE;
} }
MuError MuError
mu_cmd_cfind (MuConfig *opts, GError **err) mu_cmd_cfind (MuStore *store, MuConfig *opts, GError **err)
{ {
g_return_val_if_fail (store, MU_ERROR_INTERNAL);
g_return_val_if_fail (opts, MU_ERROR_INTERNAL); g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_CFIND, g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_CFIND,
MU_ERROR_INTERNAL); MU_ERROR_INTERNAL);
@ -433,7 +460,8 @@ mu_cmd_cfind (MuConfig *opts, GError **err)
return MU_ERROR_IN_PARAMETERS; return MU_ERROR_IN_PARAMETERS;
} }
return run_cmd_cfind (opts->params[1], return run_cmd_cfind (store,
opts->params[1],
opts->personal, opts->personal,
opts->after, opts->after,
opts->format, opts->format,

View File

@ -1,6 +1,5 @@
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/
/* /*
** Copyright (C) 2011-2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ** Copyright (C) 2011-2019 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** **
** This program is free software; you can redistribute it and/or modify it ** This program is free software; you can redistribute it and/or modify it
** under the terms of the GNU General Public License as published by the ** under the terms of the GNU General Public License as published by the
@ -88,9 +87,9 @@ install_sig_handler (void)
/* /*
* Markers for/after the lenght cookie that precedes the expression we * Markers for/after the length cookie that precedes the expression we write to
* write to output. We use octal 376, 377 (ie, 0xfe, 0xff) as they * output. We use octal 376, 377 (ie, 0xfe, 0xff) as they will never occur in
* will never occur in utf8 */ * utf8 */
#define COOKIE_PRE '\376' #define COOKIE_PRE '\376'
@ -365,20 +364,18 @@ typedef struct _ServerContext ServerContext;
/* implementation for the commands -- for each command <x>, there is a /* implementation for the commands -- for each command <x>, there is a
* dedicated function cmd_<x>. These function all are of the type CmdFunc * dedicated function cmd_<x>. These function all are of the type CmdFunc
* *
* these functions return errors only if they don't handle them * these functions return errors only if they don't handle them themselves,
* themselves, where 'handling' is defined as 'report it using * where 'handling' is defined as 'report it using print_and_clear_g_error'
* print_and_clear_g_error'
* *
* if function return non-MU_OK, the repl will print the error instead * if function return non-MU_OK, the repl will print the error instead
*/ */
typedef MuError (*CmdFunc) (ServerContext*,GHashTable*,GError**); typedef MuError (*CmdFunc) (ServerContext*,GHashTable*,GError**);
/* 'add' adds a message to the database, and takes two parameters: /* 'add' adds a message to the database, and takes two parameters: 'path', which
* 'path', which is the full path to the message, and 'maildir', which * is the full path to the message, and 'maildir', which is the maildir this
* is the maildir this message lives in (e.g. "/inbox"). response with * message lives in (e.g. "/inbox"). response with an (:info ...) message with
* an (:info ...) message with information about the newly added * information about the newly added message (details: see code below)
* message (details: see code below)
*/ */
static MuError static MuError
cmd_add (ServerContext *ctx, GHashTable *args, GError **err) cmd_add (ServerContext *ctx, GHashTable *args, GError **err)
@ -575,23 +572,32 @@ cmd_compose (ServerContext *ctx, GHashTable *args, GError **err)
struct _SexpData { struct _SexpData {
GString *gstr; GString *gstr;
gboolean personal; gboolean personal;
time_t after; time_t last_seen;
gint64 tstamp;
size_t rank;
}; };
typedef struct _SexpData SexpData; typedef struct _SexpData SexpData;
static void static void
each_contact_sexp (const char *email, const char *name, gboolean personal, each_contact_sexp (const char* full_address,
time_t tstamp, unsigned freq, SexpData *sdata) const char *email, const char *name, gboolean personal,
time_t last_seen, unsigned freq,
gint64 tstamp, SexpData *sdata)
{ {
char *escmail, *escname; char *escaddr;
sdata->rank++;
/* since the last time we got some contacts */
if (sdata->tstamp > tstamp)
return;
/* (maybe) only include 'personal' contacts */ /* (maybe) only include 'personal' contacts */
if (sdata->personal && !personal) if (sdata->personal && !personal)
return; return;
/* only include newer-than-x contacts */ /* only include newer-than-x contacts */
if (tstamp < sdata->after) if (sdata->last_seen > last_seen)
return; return;
/* only include *real* e-mail addresses (ignore local /* only include *real* e-mail addresses (ignore local
@ -599,20 +605,12 @@ each_contact_sexp (const char *email, const char *name, gboolean personal,
if (!email || !strstr (email, "@")) if (!email || !strstr (email, "@"))
return; return;
escmail = mu_str_escape_c_literal (email, TRUE); escaddr = mu_str_escape_c_literal (full_address, TRUE);
escname = name ? mu_str_escape_c_literal (name, TRUE) : NULL;
g_string_append_printf ( g_string_append_printf (sdata->gstr, "(%s . %zu)\n",
sdata->gstr, escaddr, sdata->rank);
"(:mail %s :name %s :tstamp %u :freq %u :personal %s)\n",
escmail,
escname ? escname : "nil",
(unsigned)tstamp,
freq,
sdata->personal ? "t" : "nil");
g_free (escname); g_free (escaddr);
g_free (escmail);
} }
@ -620,27 +618,37 @@ each_contact_sexp (const char *email, const char *name, gboolean personal,
* get all contacts as an s-expression * get all contacts as an s-expression
* *
* @param self contacts object * @param self contacts object
* @param personal_only whether to restrict the list to 'personal' email addresses * @param personal_only whether to restrict the list to 'personal' email
* addresses
* *
* @return the sexp * @return the sexp
*/ */
static char* static char*
contacts_to_sexp (MuContacts *contacts, gboolean personal, time_t after) contacts_to_sexp (MuContacts *contacts, gboolean personal,
time_t last_seen, gint64 tstamp)
{ {
SexpData sdata; SexpData sdata;
gint64 cutoff;
g_return_val_if_fail (contacts, NULL); g_return_val_if_fail (contacts, NULL);
memset (&sdata, 0, sizeof(SexpData));
sdata.personal = personal; sdata.personal = personal;
sdata.after = after; sdata.last_seen = last_seen;
sdata.tstamp = tstamp;
sdata.rank = 0;
/* make a guess for the initial size */ /* make a guess for the initial size */
sdata.gstr = g_string_sized_new (mu_contacts_count(contacts) * 128); sdata.gstr = g_string_sized_new (mu_contacts_count(contacts) * 128);
sdata.gstr = g_string_append (sdata.gstr, "(:contacts ("); g_string_append (sdata.gstr, "(:contacts (");
cutoff = g_get_monotonic_time();
mu_contacts_foreach (contacts, mu_contacts_foreach (contacts,
(MuContactsForeachFunc)each_contact_sexp, (MuContactsForeachFunc)each_contact_sexp, &sdata);
&sdata, NULL, NULL); /* pass a string, elisp doesn't like 64-bit nums */
sdata.gstr = g_string_append (sdata.gstr, "))"); g_string_append_printf (sdata.gstr,
") :tstamp \"%" G_GINT64_FORMAT "\")", cutoff);
return g_string_free (sdata.gstr, FALSE); return g_string_free (sdata.gstr, FALSE);
} }
@ -654,25 +662,28 @@ cmd_contacts (ServerContext *ctx, GHashTable *args, GError **err)
gboolean personal; gboolean personal;
time_t after; time_t after;
const char *str; const char *str;
gint64 tstamp;
personal = get_bool_from_args (args, "personal", TRUE, NULL); personal = get_bool_from_args (args, "personal", TRUE, NULL);
str = get_string_from_args (args, "after", TRUE, NULL); str = get_string_from_args (args, "after", TRUE, NULL);
after = str ? (time_t)atoi(str) : 0; after = str ? (time_t)atoi(str) : 0;
contacts = mu_contacts_new // only get contacts updated since tstamp.
(mu_runtime_path (MU_RUNTIME_PATH_CONTACTS)); str = get_string_from_args (args, "tstamp", TRUE, NULL);
tstamp = str ? g_ascii_strtoll (str, NULL, 10) : 0;
contacts = mu_store_contacts(ctx->store);
if (!contacts) { if (!contacts) {
print_error (MU_ERROR_INTERNAL, print_error (MU_ERROR_INTERNAL,
"failed to open contacts cache"); "failed to get contacts cache");
return MU_OK; return MU_OK;
} }
/* dump the contacts cache as a giant sexp */ /* dump the contacts cache as a giant sexp */
sexp = contacts_to_sexp (contacts, personal, after); sexp = contacts_to_sexp (contacts, personal, after, tstamp);
print_expr ("%s\n", sexp); print_expr ("%s\n", sexp);
g_free (sexp); g_free (sexp);
mu_contacts_destroy (contacts);
return MU_OK; return MU_OK;
} }
@ -693,7 +704,8 @@ print_sexps (MuMsgIter *iter, unsigned maxnum)
char *sexp; char *sexp;
const MuMsgIterThreadInfo* ti; const MuMsgIterThreadInfo* ti;
ti = mu_msg_iter_get_thread_info (iter); ti = mu_msg_iter_get_thread_info (iter);
sexp = mu_msg_to_sexp (msg, mu_msg_iter_get_docid (iter), sexp = mu_msg_to_sexp (msg,
mu_msg_iter_get_docid (iter),
ti, MU_MSG_OPTION_HEADERS_ONLY); ti, MU_MSG_OPTION_HEADERS_ONLY);
print_expr ("%s", sexp); print_expr ("%s", sexp);
g_free (sexp); g_free (sexp);
@ -974,45 +986,6 @@ cmd_find (ServerContext *ctx, GHashTable *args, GError **err)
return MU_OK; return MU_OK;
} }
/* static gpointer */
/* start_guile (GuileData *data) */
/* { */
/* g_print ("starting guile"); */
/* sleep (10); */
/* } */
#ifdef BUILD_GUILE
static MuError
cmd_guile (ServerContext *ctx, GHashTable *args, GError **err)
{
const char *eval;
eval = get_string_from_args (args, "eval", TRUE, NULL);
if (!eval) {
print_error (MU_ERROR_IN_PARAMETERS, "guile: expected: 'eval'");
return MU_OK;
}
return MU_OK;
}
#else /*!BUILD_GUILE*/
static MuError
cmd_guile (ServerContext *ctx, GHashTable *args, GError **err)
{
print_error (MU_ERROR_INTERNAL,
"this mu does not have guile support");
return MU_OK;
}
#endif /*BUILD_GUILE*/
static MuError static MuError
index_msg_cb (MuIndexStats *stats, void *user_data) index_msg_cb (MuIndexStats *stats, void *user_data)
{ {
@ -1106,7 +1079,7 @@ cmd_index (ServerContext *ctx, GHashTable *args, GError **err)
MuIndex *index; MuIndex *index;
const char *argpath; const char *argpath;
char *path; char *path;
gboolean cleanup, lazy_check; gboolean cleanup, lazy_check, contacts;
index = NULL; index = NULL;
@ -1122,8 +1095,11 @@ cmd_index (ServerContext *ctx, GHashTable *args, GError **err)
cleanup = get_bool_from_args (args, "cleanup", TRUE, NULL); cleanup = get_bool_from_args (args, "cleanup", TRUE, NULL);
lazy_check = get_bool_from_args (args, "lazy-check", TRUE, NULL); lazy_check = get_bool_from_args (args, "lazy-check", TRUE, NULL);
lazy_check = get_bool_from_args (args, "contacts", TRUE, NULL);
index_and_maybe_cleanup (index, path, cleanup, lazy_check, err); index_and_maybe_cleanup (index, path,
cleanup, lazy_check,
err);
leave: leave:
g_free (path); g_free (path);
@ -1575,7 +1551,6 @@ handle_args (ServerContext *ctx, GHashTable *args, GError **err)
{ "contacts", cmd_contacts }, { "contacts", cmd_contacts },
{ "extract", cmd_extract }, { "extract", cmd_extract },
{ "find", cmd_find }, { "find", cmd_find },
{ "guile", cmd_guile },
{ "index", cmd_index }, { "index", cmd_index },
{ "mkdir", cmd_mkdir }, { "mkdir", cmd_mkdir },
{ "move", cmd_move }, { "move", cmd_move },

View File

@ -644,13 +644,14 @@ mu_cmd_execute (MuConfig *opts, GError **err)
/* already handled in mu-config.c */ /* already handled in mu-config.c */
case MU_CONFIG_CMD_HELP: return MU_OK; case MU_CONFIG_CMD_HELP: return MU_OK;
case MU_CONFIG_CMD_CFIND: merr = mu_cmd_cfind (opts, err); break;
case MU_CONFIG_CMD_MKDIR: merr = mu_cmd_mkdir (opts, err); break; case MU_CONFIG_CMD_MKDIR: merr = mu_cmd_mkdir (opts, err); break;
case MU_CONFIG_CMD_SCRIPT: merr = mu_cmd_script (opts, err); break; case MU_CONFIG_CMD_SCRIPT: merr = mu_cmd_script (opts, err); break;
case MU_CONFIG_CMD_VIEW: merr = mu_cmd_view (opts, err); break; case MU_CONFIG_CMD_VIEW: merr = mu_cmd_view (opts, err); break;
case MU_CONFIG_CMD_VERIFY: merr = mu_cmd_verify (opts, err); break; case MU_CONFIG_CMD_VERIFY: merr = mu_cmd_verify (opts, err); break;
case MU_CONFIG_CMD_EXTRACT: merr = mu_cmd_extract (opts, err); break; case MU_CONFIG_CMD_EXTRACT: merr = mu_cmd_extract (opts, err); break;
case MU_CONFIG_CMD_CFIND:
merr = with_store (mu_cmd_cfind, opts, TRUE, err); break;
case MU_CONFIG_CMD_FIND: case MU_CONFIG_CMD_FIND:
merr = with_store (mu_cmd_find, opts, TRUE, err); break; merr = with_store (mu_cmd_find, opts, TRUE, err); break;
case MU_CONFIG_CMD_INDEX: case MU_CONFIG_CMD_INDEX:

View File

@ -118,13 +118,14 @@ MuError mu_cmd_script (MuConfig *opts, GError **err);
/** /**
* execute the cfind command * execute the cfind command
* *
* @param store store object to use
* @param opts configuration options * @param opts configuration options
* @param err receives error information, or NULL * @param err receives error information, or NULL
* *
* @return MU_OK (0) if the command succeeds, * @return MU_OK (0) if the command succeeds,
* some error code otherwise * some error code otherwise
*/ */
MuError mu_cmd_cfind (MuConfig *opts, GError **err); MuError mu_cmd_cfind (MuStore *store, MuConfig *opts, GError **err);
/** /**

View File

@ -54,7 +54,8 @@ get_output_format (const char *formatstr)
{"json", MU_CONFIG_FORMAT_JSON}, {"json", MU_CONFIG_FORMAT_JSON},
{"xml", MU_CONFIG_FORMAT_XML}, {"xml", MU_CONFIG_FORMAT_XML},
{"xquery", MU_CONFIG_FORMAT_XQUERY}, {"xquery", MU_CONFIG_FORMAT_XQUERY},
{"mquery", MU_CONFIG_FORMAT_MQUERY} {"mquery", MU_CONFIG_FORMAT_MQUERY},
{"debug", MU_CONFIG_FORMAT_DEBUG}
}; };
for (i = 0; i != G_N_ELEMENTS(formats); i++) for (i = 0; i != G_N_ELEMENTS(formats); i++)

View File

@ -47,6 +47,7 @@ enum _MuConfigFormat {
MU_CONFIG_FORMAT_CSV, /* comma-sep'd values */ MU_CONFIG_FORMAT_CSV, /* comma-sep'd values */
MU_CONFIG_FORMAT_ORG_CONTACT, /* org-contact */ MU_CONFIG_FORMAT_ORG_CONTACT, /* org-contact */
MU_CONFIG_FORMAT_BBDB, /* BBDB */ MU_CONFIG_FORMAT_BBDB, /* BBDB */
MU_CONFIG_FORMAT_DEBUG,
/* for find, view */ /* for find, view */
MU_CONFIG_FORMAT_SEXP, /* output sexps (emacs) */ MU_CONFIG_FORMAT_SEXP, /* output sexps (emacs) */