mu: implement init, info commands

'init' is for the inital database setup

'info' is for gettting information about the mu database.
This commit is contained in:
Dirk-Jan C. Binnema
2020-02-06 20:22:43 +02:00
parent 2575b2d0e3
commit f51846eefc
13 changed files with 363 additions and 355 deletions

View File

@ -251,51 +251,6 @@ cleanup_missing (MuIndex *midx, MuConfig *opts, MuIndexStats *stats,
return (rv == MU_OK || rv == MU_STOP) ? MU_OK: MU_G_ERROR_CODE(err);
}
static void
index_title (MuStore *store, MuConfig *opts)
{
const char *green, *def;
char **addrs;
int i;
time_t created;
struct tm *tstamp;
char tbuf[40];
green = opts->nocolor ? "" : MU_COLOR_GREEN;
def = opts->nocolor ? "" : MU_COLOR_DEFAULT;
g_print ("database : %s%s%s\n",
green, mu_store_database_path (store), def);
g_print ("schema-version : %s%s%s\n",
green, mu_store_schema_version(store), def);
created = mu_store_created (store);
tstamp = localtime (&created);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-y2k"
strftime (tbuf, sizeof(tbuf), "%c", tstamp);
#pragma GCC diagnostic pop
g_print ("created : %s%s%s\n", green, tbuf, def);
g_print ("maildir : %s%s%s\n",
green, mu_store_root_maildir (store), def);
g_print ("personal-addresses : ");
addrs = mu_store_personal_addresses (store);
for (i = 0; addrs[i]; ++i) {
if (i != 0)
g_print (" ");
g_print ("%s%s%s\n", green, addrs[i], def);
}
g_strfreev(addrs);
g_print ("\n");
}
static MuError
cmd_index (MuIndex *midx, MuConfig *opts, MuIndexStats *stats, GError **err)
{
@ -347,7 +302,6 @@ init_mu_index (MuStore *store, MuConfig *opts, GError **err)
return midx;
}
MuError
mu_cmd_index (MuStore *store, MuConfig *opts, GError **err)
{
@ -369,7 +323,7 @@ mu_cmd_index (MuStore *store, MuConfig *opts, GError **err)
install_sig_handler ();
if (!opts->quiet)
index_title (store, opts);
mu_store_print_info (store, opts->nocolor);
t = time (NULL);
rv = cmd_index (midx, opts, &stats, err);

View File

@ -1,6 +1,5 @@
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/
/*
** Copyright (C) 2010-2016 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** Copyright (C) 2010-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
**
** This program is free software; you can redistribute it and/or modify it
** under the terms of the GNU General Public License as published by the
@ -18,9 +17,7 @@
**
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif /*HAVE_CONFIG_H*/
#include <stdlib.h>
#include <stdio.h>
@ -243,8 +240,8 @@ view_params_valid (MuConfig *opts, GError **err)
}
MuError
mu_cmd_view (MuConfig *opts, GError **err)
static MuError
cmd_view (MuConfig *opts, GError **err)
{
int i;
gboolean rv;
@ -275,9 +272,8 @@ leave:
return MU_OK;
}
MuError
mu_cmd_mkdir (MuConfig *opts, GError **err)
static MuError
cmd_mkdir (MuConfig *opts, GError **err)
{
int i;
@ -378,8 +374,8 @@ add_path_func (MuStore *store, const char *path, GError **err)
}
MuError
mu_cmd_add (MuStore *store, MuConfig *opts, GError **err)
static MuError
cmd_add (MuStore *store, MuConfig *opts, GError **err)
{
g_return_val_if_fail (store, MU_ERROR_INTERNAL);
g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
@ -401,8 +397,8 @@ remove_path_func (MuStore *store, const char *path, GError **err)
return TRUE;
}
MuError
mu_cmd_remove (MuStore *store, MuConfig *opts, GError **err)
static MuError
cmd_remove (MuStore *store, MuConfig *opts, GError **err)
{
g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_REMOVE,
@ -428,8 +424,8 @@ tickle_func (MuStore *store, const char *path, GError **err)
}
MuError
mu_cmd_tickle (MuStore *store, MuConfig *opts, GError **err)
static MuError
cmd_tickle (MuStore *store, MuConfig *opts, GError **err)
{
g_return_val_if_fail (opts, MU_ERROR_INTERNAL);
g_return_val_if_fail (opts->cmd == MU_CONFIG_CMD_TICKLE,
@ -513,8 +509,8 @@ print_verdict (VData *vdata, gboolean color, gboolean verbose)
}
MuError
mu_cmd_verify (MuConfig *opts, GError **err)
static MuError
cmd_verify (MuConfig *opts, GError **err)
{
MuMsg *msg;
MuMsgOptions msgopts;
@ -555,6 +551,40 @@ mu_cmd_verify (MuConfig *opts, GError **err)
MU_OK : MU_ERROR;
}
static MuError
cmd_info (MuStore *store, MuConfig *opts, GError **err)
{
mu_store_print_info (store, opts->nocolor);
return MU_OK;
}
static MuError
cmd_init (MuConfig *opts, GError **err)
{
MuStore *store;
const char *path;
path = mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB);
store = mu_store_new_create (path,
opts->maildir,
(const char**)opts->my_addresses,
err);
if (!store)
return MU_G_ERROR_CODE(err);
if (!opts->quiet) {
mu_store_print_info (store, opts->nocolor);
g_print ("\nstore created.\n"
"now you can use the index command to index some messages.\n"
"see mu-index(1) for details\n");
}
mu_store_unref (store);
return MU_OK;
}
static void
show_usage (void)
@ -570,81 +600,40 @@ typedef MuError (*store_func) (MuStore *, MuConfig *, GError **err);
static MuError
with_readonly_store (store_func func, MuConfig *opts, GError **err)
with_store (store_func func, MuConfig *opts, gboolean read_only, GError **err)
{
MuError merr;
MuStore *store;
const char *path;
if (opts->rebuild) {
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR,
"cannot rebuild a read-only database");
return MU_G_ERROR_CODE(err);
}
path = mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB);
store = mu_store_new_readable (path, err);
if (!store)
return MU_G_ERROR_CODE(err);
merr = func (store, opts, err);
mu_store_unref (store);
return merr;
}
static MuStore*
get_store (MuConfig *opts, gboolean read_only, GError **err)
{
if (opts->rebuild && read_only) {
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR,
"cannot rebuild a read-only database");
return NULL;
}
if (read_only)
return mu_store_new_readable (
mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), err);
store = mu_store_new_readable (path, err);
else
store = mu_store_new_writable (path, err);
if (!opts->rebuild)
return mu_store_new_writable
(mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB), err);
if (!opts->maildir) {
g_set_error (err, MU_ERROR_DOMAIN,
MU_ERROR_IN_PARAMETERS,
"missing --maildir parameter");
return NULL;
}
return mu_store_new_create (mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB),
opts->maildir,
(const char**)opts->my_addresses,
err);
}
static MuError
with_store (store_func func, MuConfig *opts, gboolean read_only,
GError **err)
{
MuStore *store;
MuError merr;
store = get_store (opts, read_only, err);
if (!store)
return MU_G_ERROR_CODE(err);
merr = func (store, opts, err);
mu_store_unref (store);
return merr;
}
static MuError
with_readonly_store (store_func func, MuConfig *opts, GError **err)
{
return with_store (func, opts, TRUE, err);
}
static MuError
with_writable_store (store_func func, MuConfig *opts, GError **err)
{
return with_store (func, opts, FALSE, err);
}
static gboolean
check_params (MuConfig *opts, GError **err)
{
@ -675,7 +664,6 @@ set_log_options (MuConfig *opts)
logopts |= MU_LOG_OPTIONS_DEBUG;
}
MuError
mu_cmd_execute (MuConfig *opts, GError **err)
{
@ -689,34 +677,44 @@ mu_cmd_execute (MuConfig *opts, GError **err)
set_log_options (opts);
switch (opts->cmd) {
/* already handled in mu-config.c */
case MU_CONFIG_CMD_HELP: return MU_OK;
case MU_CONFIG_CMD_MKDIR: merr = mu_cmd_mkdir (opts, err); break;
/* no store needed */
case MU_CONFIG_CMD_MKDIR: merr = cmd_mkdir (opts, err); break;
case MU_CONFIG_CMD_SCRIPT: merr = mu_cmd_script (opts, err); break;
case MU_CONFIG_CMD_VIEW: merr = mu_cmd_view (opts, err); break;
case MU_CONFIG_CMD_VERIFY: merr = mu_cmd_verify (opts, err); break;
case MU_CONFIG_CMD_VIEW: merr = cmd_view (opts, err); break;
case MU_CONFIG_CMD_VERIFY: merr = cmd_verify (opts, err); break;
case MU_CONFIG_CMD_EXTRACT: merr = mu_cmd_extract (opts, err); break;
/* read-only store */
case MU_CONFIG_CMD_CFIND:
merr = with_readonly_store (mu_cmd_cfind, opts, err); break;
case MU_CONFIG_CMD_FIND:
merr = with_readonly_store (mu_cmd_find, opts, err); break;
case MU_CONFIG_CMD_INFO:
merr = with_readonly_store (cmd_info, opts, err); break;
/* writable store */
case MU_CONFIG_CMD_INDEX:
merr = with_store (mu_cmd_index, opts, FALSE, err); break;
case MU_CONFIG_CMD_ADD:
merr = with_store (mu_cmd_add, opts, FALSE, err); break;
merr = with_writable_store (cmd_add, opts, err); break;
case MU_CONFIG_CMD_REMOVE:
merr = with_store (mu_cmd_remove, opts, FALSE, err); break;
merr = with_writable_store (cmd_remove, opts, err); break;
case MU_CONFIG_CMD_TICKLE:
merr = with_store (mu_cmd_tickle, opts, FALSE, err); break;
merr = with_writable_store (cmd_tickle, opts, err); break;
case MU_CONFIG_CMD_INDEX:
merr = with_writable_store (mu_cmd_index, opts, err); break;
/* commands instantiate store themselves */
case MU_CONFIG_CMD_INIT:
merr = cmd_init (opts,err); break;
case MU_CONFIG_CMD_SERVER:
if (opts->commands)
merr = mu_cmd_server (NULL, opts, err);
else
merr = with_store (mu_cmd_server, opts, FALSE, err);
break;
merr = mu_cmd_server (opts, err); break;
default:
merr = MU_ERROR_IN_PARAMETERS; break;
}

View File

@ -1,7 +1,5 @@
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/
/*
** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** Copyright (C) 2008-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
**
** This program is free software; you can redistribute it and/or modify it
** under the terms of the GNU General Public License as published by the
@ -28,43 +26,6 @@
G_BEGIN_DECLS
/**
* execute the 'mkdir' command
*
* @param opts configuration options
* @param err receives error information, or NULL
*
* @return MU_OK (0) if the command succeeded,
* some error code otherwise
*/
MuError mu_cmd_mkdir (MuConfig *opts, GError **err);
/**
* execute the 'view' command
*
* @param opts configuration options
* @param err receives error information, or NULL
*
* @return MU_OK (0) if the command succeeded,
* some error code otherwise
*/
MuError mu_cmd_view (MuConfig *opts, GError **err);
/**
* execute the 'index' command
*
* @param store store object to use
* @param opts configuration options
* @param err receives error information, or NULL
*
* @return MU_OK (0) if the command succeeded,
* some error code otherwise
*/
MuError mu_cmd_index (MuStore *store, MuConfig *opt, GError **err);
/**
* execute the 'find' command
*
@ -91,18 +52,6 @@ MuError mu_cmd_find (MuStore *store, MuConfig *opts, GError **err);
MuError mu_cmd_extract (MuConfig *opts, GError **err);
/**
* execute the 'mv' command
*
* @param opts configuration options
* @param err receives error information, or NULL
*
* @return MU_OK (0) if the command succeeds,
* some error code otherwise
*/
MuError mu_cmd_mv (MuConfig *opts, GError **err);
/**
* execute the 'script' command
*
@ -126,67 +75,6 @@ MuError mu_cmd_script (MuConfig *opts, GError **err);
*/
MuError mu_cmd_cfind (MuStore *store, MuConfig *opts, GError **err);
/**
* execute the add command
*
* @param store store object to use
* @param opts configuration options
* @param err receives error information, or NULL
*
* @return MU_OK (0) if the command succeeds,
* some error code otherwise
*/
MuError mu_cmd_add (MuStore *store, MuConfig *opts, GError **err);
/**
* execute the remove command
*
* @param store store object to use
* @param opts configuration options
* @param err receives error information, or NULL
*
* @return MU_OK (0) if the command succeeds,
* some error code otherwise
*/
MuError mu_cmd_remove (MuStore *store, MuConfig *opts, GError **err);
/**
* execute the tickle command
*
* @param store store object to use
* @param opts configuration options
* @param err receives error information, or NULL
*
* @return MU_OK (0) if the command succeeds,
* some error code otherwise
*/
MuError mu_cmd_tickle (MuStore *store, MuConfig *opts, GError **err);
/**
* execute the server command
* @param store store object to use
* @param opts configuration options
*
* @return MU_OK (0) if the command succeeds,
* some error code otherwise
*/
MuError mu_cmd_server (MuStore *store, MuConfig *opts, GError**/*unused*/);
MuError mu_cmd_server2 (MuStore *store, MuConfig *opts, GError**/*unused*/);
/**
* execute the verify command (to verify signatures)
* @param store store object to use
* @param opts configuration options
* @param err receives error information, or NULL
*
* @return MU_OK (0) if the command succeeds,
* some error code otherwise
*/
MuError mu_cmd_verify (MuConfig *opts, GError **err);
/**
* execute some mu command, based on 'opts'
*
@ -197,6 +85,27 @@ MuError mu_cmd_verify (MuConfig *opts, GError **err);
*/
MuError mu_cmd_execute (MuConfig *opts, GError **err);
/**
* execute the 'index' command
*
* @param store store object to use
* @param opts configuration options
* @param err receives error information, or NULL
*
* @return MU_OK (0) if the command succeeded,
* some error code otherwise
*/
MuError mu_cmd_index (MuStore *store, MuConfig *opt, GError **err);
/**
* execute the server command
* @param opts configuration options
* @param err receives error information, or NULL
*
* @return MU_OK (0) if the command succeeds, some error code otherwise
*/
MuError mu_cmd_server (MuConfig *opts, GError **err);
G_END_DECLS
#endif /*__MU_CMD_H__*/

View File

@ -63,20 +63,25 @@ get_output_format (const char *formatstr)
}
#define expand_dir(D) \
if ((D)) { \
char *exp; \
exp = mu_util_dir_expand((D)); \
if (exp) { \
g_free((D)); \
(D) = exp; \
} \
}
static void
set_group_mu_defaults (void)
{
/* If muhome is not set, we use the XDG Base Directory Specification
* locations. */
if (MU_CONFIG.muhome) {
gchar *exp;
exp = mu_util_dir_expand(MU_CONFIG.muhome);
if (exp) {
g_free(MU_CONFIG.muhome);
MU_CONFIG.muhome = exp;
}
}
if (MU_CONFIG.muhome)
expand_dir(MU_CONFIG.muhome);
/* check for the MU_NOCOLOR or NO_COLOR env vars; but in any case don't
* use colors unless we're writing to a tty */
@ -118,35 +123,39 @@ config_options_group_mu (void)
return og;
}
#define expand_dir(D) \
if ((D)) { \
char *exp; \
exp = mu_util_dir_expand((D)); \
if (exp) { \
g_free((D)); \
(D) = exp; \
} \
}
static void
set_group_index_defaults (void)
set_group_init_defaults (void)
{
if (!MU_CONFIG.maildir)
MU_CONFIG.maildir = mu_util_guess_maildir ();
MU_CONFIG.maildir = mu_util_guess_maildir();
expand_dir (MU_CONFIG.maildir);
}
static GOptionGroup*
config_options_group_init (void)
{
GOptionGroup *og;
GOptionEntry entries[] = {
{"maildir", 'm', 0, G_OPTION_ARG_FILENAME, &MU_CONFIG.maildir,
"top of the maildir", "<maildir>"},
{"my-address", 0, 0, G_OPTION_ARG_STRING_ARRAY,
&MU_CONFIG.my_addresses, "my e-mail address; can be used multiple times",
"<address>"},
};
og = g_option_group_new("init", "Options for the 'index' command",
"", NULL, NULL);
g_option_group_add_entries(og, entries);
return og;
}
static GOptionGroup*
config_options_group_index (void)
{
GOptionGroup *og;
GOptionEntry entries[] = {
{"maildir", 'm', 0, G_OPTION_ARG_FILENAME, &MU_CONFIG.maildir,
"top of the maildir", "<maildir>"},
{"rebuild", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.rebuild,
"rebuild the database from scratch (false)", NULL},
{"lazy-check", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.lazycheck,
"only check dir-timestamps (false)", NULL},
{"my-address", 0, 0, G_OPTION_ARG_STRING_ARRAY,
@ -155,9 +164,6 @@ config_options_group_index (void)
"<address>"},
{"nocleanup", 0, 0, G_OPTION_ARG_NONE, &MU_CONFIG.nocleanup,
"don't clean up the database after indexing (false)", NULL},
{"max-msg-size", 0, 0, G_OPTION_ARG_INT,
&MU_CONFIG.max_msg_size,
"set the maximum size for message files", "<size>"},
{NULL, 0, 0, 0, NULL, NULL, NULL}
};
@ -267,7 +273,6 @@ config_options_group_mkdir (void)
return og;
}
static void
set_group_cfind_defaults (void)
{
@ -277,7 +282,6 @@ set_group_cfind_defaults (void)
MU_CONFIG.format = get_output_format (MU_CONFIG.formatstr);
}
static GOptionGroup *
config_options_group_cfind (void)
{
@ -300,8 +304,6 @@ config_options_group_cfind (void)
return og;
}
static GOptionGroup *
config_options_group_script (void)
{
@ -320,9 +322,6 @@ config_options_group_script (void)
return og;
}
static void
set_group_view_defaults (void)
{
@ -351,7 +350,6 @@ crypto_option_entries (void)
return entries;
}
static GOptionGroup *
config_options_group_view (void)
{
@ -377,8 +375,6 @@ config_options_group_view (void)
return og;
}
static void
set_group_extract_defaults (void)
{
@ -389,7 +385,6 @@ set_group_extract_defaults (void)
}
static GOptionGroup*
config_options_group_extract (void)
{
@ -471,6 +466,8 @@ cmd_from_string (const char *str)
{ "find", MU_CONFIG_CMD_FIND },
{ "help", MU_CONFIG_CMD_HELP },
{ "index", MU_CONFIG_CMD_INDEX },
{ "info", MU_CONFIG_CMD_INFO },
{ "init", MU_CONFIG_CMD_INIT },
{ "mfind", MU_CONFIG_CMD_MFIND },
{ "mkdir", MU_CONFIG_CMD_MKDIR },
{ "remove", MU_CONFIG_CMD_REMOVE },
@ -549,6 +546,8 @@ get_option_group (MuConfigCmd cmd)
return config_options_group_find();
case MU_CONFIG_CMD_INDEX:
return config_options_group_index();
case MU_CONFIG_CMD_INIT:
return config_options_group_init();
case MU_CONFIG_CMD_MKDIR:
return config_options_group_mkdir();
case MU_CONFIG_CMD_SERVER:
@ -723,7 +722,7 @@ mu_config_init (int *argcp, char ***argvp, GError **err)
/* fill in the defaults if user did not specify */
set_group_mu_defaults();
set_group_index_defaults();
set_group_init_defaults();
set_group_find_defaults();
set_group_cfind_defaults();
set_group_view_defaults();

View File

@ -69,6 +69,8 @@ typedef enum {
MU_CONFIG_CMD_FIND,
MU_CONFIG_CMD_HELP,
MU_CONFIG_CMD_INDEX,
MU_CONFIG_CMD_INFO,
MU_CONFIG_CMD_INIT,
MU_CONFIG_CMD_MFIND,
MU_CONFIG_CMD_MKDIR,
MU_CONFIG_CMD_REMOVE,
@ -106,16 +108,18 @@ struct _MuConfig {
* in some output */
gboolean verbose; /* verbose output */
/* options for init */
gchar *maildir; /* where the mails are */
char** my_addresses; /* 'my e-mail address', for mu
* cfind; can be use multiple
* times */
/* options for indexing */
gchar *maildir; /* where the mails are */
gboolean nocleanup; /* don't cleanup del'd mails from db */
gboolean rebuild; /* empty the database before indexing */
gboolean lazycheck; /* don't check dirs with up-to-date
* timestamps */
int max_msg_size; /* maximum size for message files */
char** my_addresses; /* 'my e-mail address', for mu
* cfind; can be use multiple
* times */
/* options for querying 'find' (and view-> 'summary') */
gchar *fields; /* fields to show in output */

View File

@ -1,7 +1,5 @@
/* -*-mode: c++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8-*- */
/*
** Copyright (C) 2008-2019 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** Copyright (C) 2008-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
**
** This program is free software; you can redistribute it and/or modify it
** under the terms of the GNU General Public License as published by the
@ -37,7 +35,7 @@ show_version (void)
{
const char* blurb =
"mu (mail indexer/searcher) version " VERSION "\n"
"Copyright (C) 2008-2019 Dirk-Jan C. Binnema\n"
"Copyright (C) 2008-2020 Dirk-Jan C. Binnema\n"
"License GPLv3+: GNU GPL version 3 or later "
"<http://gnu.org/licenses/gpl.html>.\n"
"This is free software: you are free to change "
@ -51,13 +49,9 @@ show_version (void)
static void
handle_error (MuConfig *conf, MuError merr, GError **err)
{
const char *path;
if (!(err && *err))
return;
path = mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB);
switch ((*err)->code) {
case MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK:
g_printerr ("maybe mu is already running?\n");
@ -76,15 +70,12 @@ handle_error (MuConfig *conf, MuError merr, GError **err)
"'mu script' for the scripts\n");
break;
case MU_ERROR_XAPIAN_CANNOT_OPEN:
g_printerr("Failed to open database @ %s, \n"
"Please (re)build the database, i.e., with\n"
"\tmu index --rebuild\n", path);
g_printerr("Please (re)init mu with 'mu init' "
"see mu-init(1) for details");
return;
case MU_ERROR_XAPIAN_SCHEMA_MISMATCH:
g_printerr("Failed to open database @ %s, \n"
"because the schema version does not match mu's.\n\n"
"Please rebuild the database, i.e., with\n"
"\tmu index --rebuild\n", path);
g_printerr("Please (re)init mu with 'mu init' "
"see mu-init(1) for details");
return;
default:
break; /* nothing to do */