server: pass root-maildir, personal-addresses, dbpath to mu4e

Tell mu4e about the parameters, so users do not need to explicitly set
them.
This commit is contained in:
Dirk-Jan C. Binnema
2020-02-06 20:26:12 +02:00
parent aa10da0a63
commit dea4789e0e

View File

@ -91,35 +91,6 @@ install_sig_handler (void)
} }
struct Context {
Context() {}
Context (MuStore *storearg): store{storearg} {
if (!store)
return;
GError *gerr{};
query = mu_query_new (store, &gerr);
if (!query)
throw Error(Error::Code::Store, &gerr, "failed to create query");
}
~Context() {
if (query)
mu_query_destroy(query);
if (store)
mu_store_flush(store);
}
Context(const Context&) = delete;
MuStore *store{};
MuQuery *query{};
bool do_quit{};
CommandMap command_map;
};
/* /*
* Markers for/after the length cookie that precedes the expression we write to * Markers for/after the length cookie that precedes the expression we write to
* output. We use octal 376, 377 (ie, 0xfe, 0xff) as they will never occur in * output. We use octal 376, 377 (ie, 0xfe, 0xff) as they will never occur in
@ -201,7 +172,7 @@ print_error (MuError errcode, const char* frm, ...)
g_vasprintf (&msg, frm, ap); g_vasprintf (&msg, frm, ap);
va_end (ap); va_end (ap);
print_expr ("(:error %u :message %s)", errcode, quoted(msg).c_str()); print_expr ("(:error %u :message %s)", errcode, quote(msg).c_str());
g_free (msg); g_free (msg);
return errcode; return errcode;
@ -235,6 +206,55 @@ print_sexps (MuMsgIter *iter, unsigned maxnum)
} }
struct Context {
Context(){}
Context (MuConfig *opts) {
const auto dbpath{mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB)};
GError *gerr{};
store = mu_store_new_writable (dbpath, NULL);
if (!store) {
if (gerr) {
if ((MuError)gerr->code == MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK)
print_error(MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK,
"mu database already locked; "
"some other mu running?");
else
print_error((MuError)gerr->code,
"cannot open database @ %s:%s; "
"pleasy try 'mu init", dbpath,
gerr->message ? gerr->message : "something went wrong");
} else
print_error(MU_ERROR,
"cannot open database @ %s; pleasy try 'mu init'", dbpath);
throw Mu::Error (Error::Code::Store, &gerr/*consumed*/,
"failed to open database @ %s; please try 'mu init'", dbpath);
}
query = mu_query_new (store, &gerr);
if (!query)
throw Error(Error::Code::Store, &gerr, "failed to create query");
}
~Context() {
if (query)
mu_query_destroy(query);
if (store) {
mu_store_flush(store);
mu_store_unref(store);
}
}
Context(const Context&) = delete;
MuStore *store{};
MuQuery *query{};
bool do_quit{};
CommandMap command_map;
};
static MuMsgOptions static MuMsgOptions
message_options (const Parameters& params) message_options (const Parameters& params)
{ {
@ -266,7 +286,7 @@ add_handler (Context& context, const Parameters& params)
throw Error(Error::Code::Store, &gerr, "failed to add message at %s", throw Error(Error::Code::Store, &gerr, "failed to add message at %s",
path.c_str()); path.c_str());
print_expr ("(:info add :path %s :docid %u)", quoted(path).c_str(), docid); print_expr ("(:info add :path %s :docid %u)", quote(path).c_str(), docid);
auto msg{mu_store_get_msg(context.store, docid, &gerr)}; auto msg{mu_store_get_msg(context.store, docid, &gerr)};
if (!msg) if (!msg)
@ -304,7 +324,7 @@ each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo)
throw Error (Error::Code::File, &gerr, "failed to save part"); throw Error (Error::Code::File, &gerr, "failed to save part");
att = g_strdup_printf ("(:file-name %s :mime-type \"%s/%s\")", att = g_strdup_printf ("(:file-name %s :mime-type \"%s/%s\")",
quoted(cachefile).c_str(), part->type, part->subtype); quote(cachefile).c_str(), part->type, part->subtype);
pinfo->attlist = g_slist_append (pinfo->attlist, att); pinfo->attlist = g_slist_append (pinfo->attlist, att);
g_free (cachefile); g_free (cachefile);
@ -439,7 +459,7 @@ each_contact_sexp (const char* full_address,
return; return;
g_string_append_printf (sdata->gstr, "(%s . %zu)\n", g_string_append_printf (sdata->gstr, "(%s . %zu)\n",
quoted(full_address).c_str(), sdata->rank); quote(full_address).c_str(), sdata->rank);
} }
/** /**
@ -512,7 +532,7 @@ save_part (MuMsg *msg, unsigned docid, unsigned index,
path.c_str(), index, &gerr)) path.c_str(), index, &gerr))
throw Error{Error::Code::File, &gerr, "failed to save part"}; throw Error{Error::Code::File, &gerr, "failed to save part"};
print_expr ("(:info save :message %s)", quoted(path + " has been saved").c_str()); print_expr ("(:info save :message %s)", quote(path + " has been saved").c_str());
} }
@ -537,7 +557,7 @@ open_part (MuMsg *msg, unsigned docid, unsigned index, MuMsgOptions opts)
} }
print_expr ("(:info open :message %s)", print_expr ("(:info open :message %s)",
quoted(std::string{targetpath} + " has been opened").c_str()); quote(std::string{targetpath} + " has been opened").c_str());
g_free (targetpath); g_free (targetpath);
} }
@ -562,7 +582,7 @@ temp_part (MuMsg *msg, unsigned docid, unsigned index,
throw Error{Error::Code::File, &gerr, "saving failed"}; throw Error{Error::Code::File, &gerr, "saving failed"};
} }
const auto qpath{quoted(path)}; const auto qpath{quote(path)};
g_free(path); g_free(path);
if (!param.empty()) if (!param.empty())
@ -571,7 +591,7 @@ temp_part (MuMsg *msg, unsigned docid, unsigned index,
" :docid %u" " :docid %u"
" :param %s" " :param %s"
")", ")",
qpath.c_str(), what.c_str(), docid, quoted(param).c_str()); qpath.c_str(), what.c_str(), docid, quote(param).c_str());
else else
print_expr ("(:temp %s :what \"%s\" :docid %u)", print_expr ("(:temp %s :what \"%s\" :docid %u)",
qpath.c_str(), what.c_str(), docid); qpath.c_str(), what.c_str(), docid);
@ -992,8 +1012,6 @@ move_handler (Context& context, const Parameters& params)
mu_msg_unref(msg); mu_msg_unref(msg);
} }
static void static void
ping_handler (Context& context, const Parameters& params) ping_handler (Context& context, const Parameters& params)
{ {
@ -1003,7 +1021,6 @@ ping_handler (Context& context, const Parameters& params)
throw Error{Error::Code::Store, &gerr, "failed to read store"}; throw Error{Error::Code::Store, &gerr, "failed to read store"};
const auto queries = get_string_vec (params, "queries"); const auto queries = get_string_vec (params, "queries");
const auto qresults= [&]() -> std::string { const auto qresults= [&]() -> std::string {
if (queries.empty()) if (queries.empty())
return {}; return {};
@ -1013,18 +1030,36 @@ ping_handler (Context& context, const Parameters& params)
const auto count{mu_query_count_run (context.query, q.c_str())}; const auto count{mu_query_count_run (context.query, q.c_str())};
const auto unreadq{format("(%s) AND flag:unread", q.c_str())}; const auto unreadq{format("(%s) AND flag:unread", q.c_str())};
const auto unread{mu_query_count_run (context.query, unreadq.c_str())}; const auto unread{mu_query_count_run (context.query, unreadq.c_str())};
res += format("(:query %s :count %zu :unread %zu)", quoted(q).c_str(), count, unread); res += format("(:query %s :count %zu :unread %zu)", quote(q).c_str(), count, unread);
} }
return res + ")"; return res + ")";
}(); }();
print_expr ("(:pong \"" PACKAGE_NAME "\" " const auto personal = [&]() ->std::string {
":props (" auto addrs{mu_store_personal_addresses (context.store)};
std::string res;
if (addrs && g_strv_length(addrs) != 0) {
res = ":personal-addresses (";
for (int i = 0; addrs[i]; ++i)
res += quote(addrs[i]) + ' ';
res += ")";
}
g_strfreev(addrs);
return res;
}();
print_expr ("(:pong \"mu\" :props ("
":version \"" VERSION "\" " ":version \"" VERSION "\" "
"%s " "%s "
":doccount %u))", ":database-path %s "
qresults.c_str(), ":root-maildir %s "
storecount); ":doccount %u "
"%s))",
personal.c_str(),
quote(mu_store_database_path(context.store)).c_str(),
quote(mu_store_root_maildir(context.store)).c_str(),
storecount,
qresults.c_str());
} }
static void static void
@ -1062,7 +1097,7 @@ sent_handler (Context& context, const Parameters& params)
if (docid == MU_STORE_INVALID_DOCID) if (docid == MU_STORE_INVALID_DOCID)
throw Error{Error::Code::Store, &gerr, "failed to add path"}; throw Error{Error::Code::Store, &gerr, "failed to add path"};
print_expr ("(:sent t :path %s :docid %u)", quoted(path).c_str(), docid); print_expr ("(:sent t :path %s :docid %u)", quote(path).c_str(), docid);
} }
@ -1273,27 +1308,27 @@ read_line (Context& context)
MuError MuError
mu_cmd_server (MuStore *store, MuConfig *opts/*unused*/, GError **err) try mu_cmd_server (MuConfig *opts, GError **err) try
{ {
if (!store && !opts->commands)
throw Error{Error::Code::Internal, "missing store"};
Context context{store};
context.command_map = make_command_map (context);
if (opts->commands) { if (opts->commands) {
invoke(context.command_map, Sexp::parse("(help :full t)")); Context ctx{};
auto cmap = make_command_map(ctx);
invoke(cmap, Sexp::parse("(help :full t)"));
return MU_OK; return MU_OK;
} }
Context context{opts};
context.command_map = make_command_map (context);
install_sig_handler(); install_sig_handler();
std::cout << ";; Welcome to the " << PACKAGE_STRING << " command-server\n" std::cout << ";; Welcome to the " << PACKAGE_STRING << " command-server\n"
<< ";; Use (help) to get a list of commands, (quit) to quit.\n"; << ";; Use (help) to get a list of commands, (quit) to quit.\n";
while (!MuTerminate && !context.do_quit) { while (!MuTerminate && !context.do_quit) {
std::string line;
try { try {
const auto line{read_line(context)}; line = read_line(context);
if (line.find_first_not_of(" \t") == std::string::npos) if (line.find_first_not_of(" \t") == std::string::npos)
continue; // skip whitespace-only lines continue; // skip whitespace-only lines
@ -1301,7 +1336,8 @@ mu_cmd_server (MuStore *store, MuConfig *opts/*unused*/, GError **err) try
} catch (const Error& er) { } catch (const Error& er) {
std::cerr << ";; error: " << er.what() << "\n"; std::cerr << ";; error: " << er.what() << "\n";
print_error ((MuError)er.code(), "%s", er.what()); print_error ((MuError)er.code(), "%s (line was:'%s')",
er.what(), line.c_str());
} }
} }