mu-server: turn off renaming for 'view' now

It seems to confuse mbsync, see issue #2214.
This commit is contained in:
Dirk-Jan C. Binnema 2022-02-25 23:03:48 +02:00
parent cfc68732e7
commit 1966dcb795
1 changed files with 92 additions and 89 deletions

View File

@ -116,19 +116,19 @@ struct Server::Private {
private: private:
// helpers // helpers
Sexp build_message_sexp(MuMsg* msg, Sexp build_message_sexp(MuMsg* msg,
unsigned docid, unsigned docid,
const Option<QueryMatch&> qm, const Option<QueryMatch&> qm,
MuMsgOptions opts) const; MuMsgOptions opts) const;
Sexp::List move_docid(Store::Id docid, std::optional<std::string> flagstr, Sexp::List move_docid(Store::Id docid, std::optional<std::string> flagstr,
bool new_name, bool no_view); bool new_name, bool no_view);
Sexp::List perform_move(Store::Id docid, Sexp::List perform_move(Store::Id docid,
MuMsg* msg, MuMsg* msg,
const std::string& maildirarg, const std::string& maildirarg,
MessageFlags flags, MessageFlags flags,
bool new_name, bool new_name,
bool no_view); bool no_view);
bool maybe_mark_as_read(MuMsg* msg, Store::Id docid, bool rename); bool maybe_mark_as_read(MuMsg* msg, Store::Id docid, bool rename);
bool maybe_mark_msgid_as_read(const char* msgid, bool rename); bool maybe_mark_msgid_as_read(const char* msgid, bool rename);
@ -184,9 +184,9 @@ build_metadata(const QueryMatch& qmatch)
*/ */
Sexp Sexp
Server::Private::build_message_sexp(MuMsg* msg, Server::Private::build_message_sexp(MuMsg* msg,
unsigned docid, unsigned docid,
const Option<QueryMatch&> qm, const Option<QueryMatch&> qm,
MuMsgOptions opts) const MuMsgOptions opts) const
{ {
auto msgsexp{Mu::msg_to_sexp_list(msg, docid, opts)}; auto msgsexp{Mu::msg_to_sexp_list(msg, docid, opts)};
if (qm) if (qm)
@ -214,13 +214,13 @@ Server::Private::make_command_map()
CommandInfo{ CommandInfo{
ArgMap{ ArgMap{
{":type", {":type",
ArgInfo{Type::Symbol, ArgInfo{Type::Symbol,
true, true,
"type of composition: reply/forward/edit/resend/new"}}, "type of composition: reply/forward/edit/resend/new"}},
{":docid", {":docid",
ArgInfo{Type::Number, false, "document id of parent-message, if any"}}, ArgInfo{Type::Number, false, "document id of parent-message, if any"}},
{":decrypt", {":decrypt",
ArgInfo{Type::Symbol, false, "whether to decrypt encrypted parts (if any)"}}}, ArgInfo{Type::Symbol, false, "whether to decrypt encrypted parts (if any)"}}},
"compose a new message", "compose a new message",
[&](const auto& params) { compose_handler(params); }}); [&](const auto& params) { compose_handler(params); }});
@ -228,30 +228,30 @@ Server::Private::make_command_map()
"contacts", "contacts",
CommandInfo{ CommandInfo{
ArgMap{{":personal", ArgInfo{Type::Symbol, false, "only personal contacts"}}, ArgMap{{":personal", ArgInfo{Type::Symbol, false, "only personal contacts"}},
{":after", {":after",
ArgInfo{Type::String, false, "only contacts seen after time_t string"}}, ArgInfo{Type::String, false, "only contacts seen after time_t string"}},
{":tstamp", ArgInfo{Type::String, false, "return changes since tstamp"}}}, {":tstamp", ArgInfo{Type::String, false, "return changes since tstamp"}}},
"get contact information", "get contact information",
[&](const auto& params) { contacts_handler(params); }}); [&](const auto& params) { contacts_handler(params); }});
cmap.emplace( cmap.emplace(
"find", "find",
CommandInfo{ CommandInfo{
ArgMap{{":query", ArgInfo{Type::String, true, "search expression"}}, ArgMap{{":query", ArgInfo{Type::String, true, "search expression"}},
{":threads", {":threads",
ArgInfo{Type::Symbol, false, "whether to include threading information"}}, ArgInfo{Type::Symbol, false, "whether to include threading information"}},
{":sortfield", ArgInfo{Type::Symbol, false, "the field to sort results by"}}, {":sortfield", ArgInfo{Type::Symbol, false, "the field to sort results by"}},
{":descending", {":descending",
ArgInfo{Type::Symbol, false, "whether to sort in descending order"}}, ArgInfo{Type::Symbol, false, "whether to sort in descending order"}},
{":batch-size", ArgInfo{Type::Number, false, "batch size for result"}}, {":batch-size", ArgInfo{Type::Number, false, "batch size for result"}},
{":maxnum", ArgInfo{Type::Number, false, "maximum number of result (hint)"}}, {":maxnum", ArgInfo{Type::Number, false, "maximum number of result (hint)"}},
{":skip-dups", {":skip-dups",
ArgInfo{Type::Symbol, ArgInfo{Type::Symbol,
false, false,
"whether to skip messages with duplicate message-ids"}}, "whether to skip messages with duplicate message-ids"}},
{":include-related", {":include-related",
ArgInfo{Type::Symbol, ArgInfo{Type::Symbol,
false, false,
"whether to include other message related to matching ones"}}}, "whether to include other message related to matching ones"}}},
"query the database for messages", "query the database for messages",
[&](const auto& params) { find_handler(params); }}); [&](const auto& params) { find_handler(params); }});
@ -259,21 +259,21 @@ Server::Private::make_command_map()
"help", "help",
CommandInfo{ CommandInfo{
ArgMap{{":command", ArgInfo{Type::Symbol, false, "command to get information for"}}, ArgMap{{":command", ArgInfo{Type::Symbol, false, "command to get information for"}},
{":full", ArgInfo{Type::Symbol, false, "show full descriptions"}}}, {":full", ArgInfo{Type::Symbol, false, "show full descriptions"}}},
"get information about one or all commands", "get information about one or all commands",
[&](const auto& params) { help_handler(params); }}); [&](const auto& params) { help_handler(params); }});
cmap.emplace( cmap.emplace(
"index", "index",
CommandInfo{ CommandInfo{
ArgMap{{":my-addresses", ArgInfo{Type::List, false, "list of 'my' addresses"}}, ArgMap{{":my-addresses", ArgInfo{Type::List, false, "list of 'my' addresses"}},
{":cleanup", {":cleanup",
ArgInfo{Type::Symbol, ArgInfo{Type::Symbol,
false, false,
"whether to remove stale messages from the store"}}, "whether to remove stale messages from the store"}},
{":lazy-check", {":lazy-check",
ArgInfo{Type::Symbol, ArgInfo{Type::Symbol,
false, false,
"whether to avoid indexing up-to-date directories"}}}, "whether to avoid indexing up-to-date directories"}}},
"scan maildir for new/updated/removed messages", "scan maildir for new/updated/removed messages",
[&](const auto& params) { index_handler(params); }}); [&](const auto& params) { index_handler(params); }});
@ -287,7 +287,7 @@ Server::Private::make_command_map()
{":maildir", ArgInfo{Type::String, false, "the target maildir"}}, {":maildir", ArgInfo{Type::String, false, "the target maildir"}},
{":rename", ArgInfo{Type::Symbol, false, "change filename when moving"}}, {":rename", ArgInfo{Type::Symbol, false, "change filename when moving"}},
{":no-view", {":no-view",
ArgInfo{Type::Symbol, false, "if set, do not hint at updating the view"}}, ArgInfo{Type::Symbol, false, "if set, do not hint at updating the view"}},
}, },
"move messages and/or change their flags", "move messages and/or change their flags",
@ -304,11 +304,11 @@ Server::Private::make_command_map()
CommandInfo{ CommandInfo{
ArgMap{ ArgMap{
{":queries", {":queries",
ArgInfo{Type::List, false, "queries for which to get read/unread numbers"}}, ArgInfo{Type::List, false, "queries for which to get read/unread numbers"}},
{":skip-dups", {":skip-dups",
ArgInfo{Type::Symbol, ArgInfo{Type::Symbol,
false, false,
"whether to exclude messages with duplicate message-ids"}}, "whether to exclude messages with duplicate message-ids"}},
}, },
"ping the mu-server and get information in response", "ping the mu-server and get information in response",
[&](const auto& params) { ping_handler(params); }}); [&](const auto& params) { ping_handler(params); }});
@ -321,15 +321,15 @@ Server::Private::make_command_map()
"remove", "remove",
CommandInfo{ CommandInfo{
ArgMap{{":docid", ArgMap{{":docid",
ArgInfo{Type::Number, true, "document-id for the message to remove"}}}, ArgInfo{Type::Number, true, "document-id for the message to remove"}}},
"remove a message from filesystem and database", "remove a message from filesystem and database",
[&](const auto& params) { remove_handler(params); }}); [&](const auto& params) { remove_handler(params); }});
cmap.emplace( cmap.emplace(
"sent", "sent",
CommandInfo{ArgMap{{":path", ArgInfo{Type::String, true, "path to the message file"}}}, CommandInfo{ArgMap{{":path", ArgInfo{Type::String, true, "path to the message file"}}},
"tell mu about a message that was sent", "tell mu about a message that was sent",
[&](const auto& params) { sent_handler(params); }}); [&](const auto& params) { sent_handler(params); }});
cmap.emplace( cmap.emplace(
"view", "view",
@ -338,11 +338,11 @@ Server::Private::make_command_map()
{":msgid", ArgInfo{Type::String, false, "message-id"}}, {":msgid", ArgInfo{Type::String, false, "message-id"}},
{":path", ArgInfo{Type::String, false, "message filesystem path"}}, {":path", ArgInfo{Type::String, false, "message filesystem path"}},
{":mark-as-read", {":mark-as-read",
ArgInfo{Type::Symbol, false, "mark message as read (if not already)"}}, ArgInfo{Type::Symbol, false, "mark message as read (if not already)"}},
{":rename", ArgInfo{Type::Symbol, false, "change filename when moving"}}, {":rename", ArgInfo{Type::Symbol, false, "change filename when moving"}},
}, },
"view a message. exactly one of docid/msgid/path must be specified", "view a message. exactly one of docid/msgid/path must be specified",
[&](const auto& params) { view_handler(params); }}); [&](const auto& params) { view_handler(params); }});
return cmap; return cmap;
} }
@ -422,9 +422,9 @@ Server::Private::add_handler(const Parameters& params)
auto msg{store().find_message(docid)}; auto msg{store().find_message(docid)};
if (!msg) if (!msg)
throw Error(Error::Code::Store, throw Error(Error::Code::Store,
"failed to get message at %s (docid=%u)", "failed to get message at %s (docid=%u)",
path.c_str(), path.c_str(),
docid); docid);
Sexp::List update; Sexp::List update;
update.add_prop(":update", build_message_sexp(msg, docid, {}, MU_MSG_OPTION_VERIFY)); update.add_prop(":update", build_message_sexp(msg, docid, {}, MU_MSG_OPTION_VERIFY));
@ -447,9 +447,9 @@ each_part(MuMsg* msg, MuMsgPart* part, PartInfo* pinfo)
GError* gerr{}; GError* gerr{};
char* cachefile = char* cachefile =
mu_msg_part_save_temp(msg, mu_msg_part_save_temp(msg,
(MuMsgOptions)(pinfo->opts | MU_MSG_OPTION_OVERWRITE), (MuMsgOptions)(pinfo->opts | MU_MSG_OPTION_OVERWRITE),
part->index, part->index,
&gerr); &gerr);
if (!cachefile) if (!cachefile)
throw Error(Error::Code::File, &gerr, "failed to save part"); throw Error(Error::Code::File, &gerr, "failed to save part");
@ -495,14 +495,14 @@ Server::Private::compose_handler(const Parameters& params)
mu_msg_part_foreach(msg, opts, (MuMsgPartForeachFunc)each_part, &pinfo); mu_msg_part_foreach(msg, opts, (MuMsgPartForeachFunc)each_part, &pinfo);
if (!pinfo.attseq.empty()) if (!pinfo.attseq.empty())
comp_lst.add_prop(":include", comp_lst.add_prop(":include",
Sexp::make_list(std::move(pinfo.attseq))); Sexp::make_list(std::move(pinfo.attseq)));
} }
mu_msg_unref(msg); mu_msg_unref(msg);
} else if (ctype != "new") } else if (ctype != "new")
throw Error(Error::Code::InvalidArgument, throw Error(Error::Code::InvalidArgument,
"invalid compose type '%s'", "invalid compose type '%s'",
ctype.c_str()); ctype.c_str());
output_sexp(std::move(comp_lst)); output_sexp(std::move(comp_lst));
} }
@ -546,7 +546,7 @@ Server::Private::contacts_handler(const Parameters& params)
Sexp::List seq; Sexp::List seq;
seq.add_prop(":contacts", Sexp::make_list(std::move(contacts))); seq.add_prop(":contacts", Sexp::make_list(std::move(contacts)));
seq.add_prop(":tstamp", seq.add_prop(":tstamp",
Sexp::make_string(format("%" G_GINT64_FORMAT, g_get_monotonic_time()))); Sexp::make_string(format("%" G_GINT64_FORMAT, g_get_monotonic_time())));
/* dump the contacts cache as a giant sexp */ /* dump the contacts cache as a giant sexp */
output_sexp(std::move(seq)); output_sexp(std::move(seq));
} }
@ -573,8 +573,8 @@ docids_for_msgid(const Store& store, const std::string& msgid, size_t max = 100)
throw Error(Error::Code::Store, &gerr, "failed to run msgid-query"); throw Error(Error::Code::Store, &gerr, "failed to run msgid-query");
else if (res->empty()) else if (res->empty())
throw Error(Error::Code::NotFound, throw Error(Error::Code::NotFound,
"could not find message(s) for msgid %s", "could not find message(s) for msgid %s",
msgid.c_str()); msgid.c_str());
std::vector<Store::Id> docids{}; std::vector<Store::Id> docids{};
for (auto&& mi : *res) for (auto&& mi : *res)
@ -614,7 +614,7 @@ determine_docids(const Store& store, const Parameters& params)
if ((docid == 0) == msgid.empty()) if ((docid == 0) == msgid.empty())
throw Error(Error::Code::InvalidArgument, throw Error(Error::Code::InvalidArgument,
"precisely one of docid and msgid must be specified"); "precisely one of docid and msgid must be specified");
if (docid != 0) if (docid != 0)
return {static_cast<Store::Id>(docid)}; return {static_cast<Store::Id>(docid)};
@ -677,8 +677,8 @@ Server::Private::find_handler(const Parameters& params)
sort_field = mu_msg_field_id_from_name(sortfieldstr.c_str() + 1, FALSE); // skip ':' sort_field = mu_msg_field_id_from_name(sortfieldstr.c_str() + 1, FALSE); // skip ':'
if (sort_field == MU_MSG_FIELD_ID_NONE) if (sort_field == MU_MSG_FIELD_ID_NONE)
throw Error{Error::Code::InvalidArgument, throw Error{Error::Code::InvalidArgument,
"invalid sort field %s", "invalid sort field %s",
sortfieldstr.c_str()}; sortfieldstr.c_str()};
} }
if (batch_size < 1) if (batch_size < 1)
throw Error{Error::Code::InvalidArgument, "invalid batch-size %d", batch_size}; throw Error{Error::Code::InvalidArgument, "invalid batch-size %d", batch_size};
@ -754,8 +754,8 @@ Server::Private::help_handler(const Parameters& params)
const auto& arg{info.args.find(argname)}; const auto& arg{info.args.find(argname)};
std::cout << ";; " std::cout << ";; "
<< format("%-17s : %-24s ", << format("%-17s : %-24s ",
arg->first.c_str(), arg->first.c_str(),
to_string(arg->second).c_str()); to_string(arg->second).c_str());
std::cout << " " << arg->second.docstring << "\n"; std::cout << " " << arg->second.docstring << "\n";
} }
std::cout << ";;\n"; std::cout << ";;\n";
@ -816,11 +816,11 @@ Server::Private::mkdir_handler(const Parameters& params)
Sexp::List Sexp::List
Server::Private::perform_move(Store::Id docid, Server::Private::perform_move(Store::Id docid,
MuMsg* msg, MuMsg* msg,
const std::string& maildirarg, const std::string& maildirarg,
MessageFlags flags, MessageFlags flags,
bool new_name, bool new_name,
bool no_view) bool no_view)
{ {
bool different_mdir{}; bool different_mdir{};
auto maildir{maildirarg}; auto maildir{maildirarg};
@ -857,7 +857,7 @@ Server::Private::perform_move(Store::Id docid,
static MessageFlags static MessageFlags
calculate_message_flags(MuMsg* msg, std::optional<std::string> flagopt) calculate_message_flags(MuMsg* msg, std::optional<std::string> flagopt)
{ {
const auto flags = std::invoke([&]()->std::optional<MessageFlags>{ const auto flags = std::invoke([&]()->std::optional<MessageFlags>{
auto msgflags{mu_msg_get_flags(msg)}; auto msgflags{mu_msg_get_flags(msg)};
if (!flagopt) if (!flagopt)
@ -875,9 +875,9 @@ calculate_message_flags(MuMsg* msg, std::optional<std::string> flagopt)
Sexp::List Sexp::List
Server::Private::move_docid(Store::Id docid, Server::Private::move_docid(Store::Id docid,
std::optional<std::string> flagopt, std::optional<std::string> flagopt,
bool new_name, bool new_name,
bool no_view) bool no_view)
{ {
if (docid == Store::InvalidId) if (docid == Store::InvalidId)
throw Error{Error::Code::InvalidArgument, "invalid docid"}; throw Error{Error::Code::InvalidArgument, "invalid docid"};
@ -920,7 +920,7 @@ Server::Private::move_handler(const Parameters& params)
if (docids.size() > 1) { if (docids.size() > 1) {
if (!maildir.empty()) // ie. duplicate message-ids. if (!maildir.empty()) // ie. duplicate message-ids.
throw Mu::Error{Error::Code::Store, throw Mu::Error{Error::Code::Store,
"can't move multiple messages at the same time"}; "can't move multiple messages at the same time"};
// multi. // multi.
for (auto&& docid : docids) for (auto&& docid : docids)
output_sexp(move_docid(docid, flagopt, output_sexp(move_docid(docid, flagopt,
@ -1008,9 +1008,9 @@ Server::Private::remove_handler(const Parameters& params)
if (::unlink(path.c_str()) != 0 && errno != ENOENT) if (::unlink(path.c_str()) != 0 && errno != ENOENT)
throw Error(Error::Code::File, throw Error(Error::Code::File,
"could not delete %s: %s", "could not delete %s: %s",
path.c_str(), path.c_str(),
g_strerror(errno)); g_strerror(errno));
if (!store().remove_message(path)) if (!store().remove_message(path))
g_warning("failed to remove message @ %s (%d) from store", path.c_str(), docid); g_warning("failed to remove message @ %s (%d) from store", path.c_str(), docid);
@ -1052,11 +1052,11 @@ Server::Private::maybe_mark_as_read(MuMsg* msg, Store::Id docid, bool rename)
GError* gerr{}; GError* gerr{};
if (!mu_msg_move_to_maildir(msg, if (!mu_msg_move_to_maildir(msg,
store().properties().root_maildir, store().properties().root_maildir,
mu_msg_get_maildir(msg), mu_msg_get_maildir(msg),
*newflags, *newflags,
true, true,
rename, rename,
&gerr)) &gerr))
throw Error{Error::Code::File, &gerr, "failed to move message"}; throw Error{Error::Code::File, &gerr, "failed to move message"};
/* after mu_msg_move_to_maildir, path will be the *new* path, and flags and maildir /* after mu_msg_move_to_maildir, path will be the *new* path, and flags and maildir
@ -1100,7 +1100,10 @@ void
Server::Private::view_handler(const Parameters& params) Server::Private::view_handler(const Parameters& params)
{ {
const auto mark_as_read{get_bool_or(params, ":mark-as-read")}; const auto mark_as_read{get_bool_or(params, ":mark-as-read")};
const auto rename{get_bool_or(params, ":rename")}; /* for now, do _not_ rename, as it seems to confuse mbsync */
const auto rename{false};
//const auto rename{get_bool_or(params, ":rename")};
const auto docids{determine_docids(store(), params)}; const auto docids{determine_docids(store(), params)};
if (docids.empty()) if (docids.empty())