mu-server: update for move_message API update

This commit is contained in:
Dirk-Jan C. Binnema
2022-12-03 16:45:41 +02:00
parent da7c3b0c9a
commit b71751a185

View File

@ -109,17 +109,17 @@ private:
Store::Id docid, Store::Id docid,
const Option<QueryMatch&> qm) const; const Option<QueryMatch&> qm) const;
Sexp move_docid(Store::Id docid, Option<std::string> flagstr, void move_docid(Store::Id docid, Option<std::string> flagstr,
bool new_name, bool no_view); bool new_name, bool no_view);
Sexp perform_move(Store::Id docid, void perform_move(Store::Id docid,
const Message& msg, const Message& msg,
const std::string& maildirarg, const std::string& maildirarg,
Flags flags, Flags flags,
bool new_name, bool new_name,
bool no_view); bool no_view);
bool view_mark_as_read(Store::Id docid, const Message& msg, bool rename); void view_mark_as_read(Store::Id docid, Message&& msg, bool rename);
Store& store_; Store& store_;
Server::Output output_; Server::Output output_;
@ -797,7 +797,7 @@ Server::Private::mkdir_handler(const Command& cmd)
":message", format("%s has been created", path.c_str()))); ":message", format("%s has been created", path.c_str())));
} }
Sexp void
Server::Private::perform_move(Store::Id docid, Server::Private::perform_move(Store::Id docid,
const Message& msg, const Message& msg,
const std::string& maildirarg, const std::string& maildirarg,
@ -813,20 +813,26 @@ Server::Private::perform_move(Store::Id docid,
} else /* are we moving to a different mdir, or is it just flags? */ } else /* are we moving to a different mdir, or is it just flags? */
different_mdir = maildir != msg.maildir(); different_mdir = maildir != msg.maildir();
const auto new_msg = store().move_message(docid, maildir, flags, new_name); Store::MoveOptions move_opts{Store::MoveOptions::DupFlags};
if (!new_msg) if (new_name)
throw new_msg.error(); move_opts |= Store::MoveOptions::ChangeName;
Sexp seq; /* note: we get back _all_ the messages that changed; the first is the
seq.put_props(":update", build_message_sexp(new_msg.value(), docid, {})); * primary mover; the rest (if present) are any dups affected */
const auto idmsgvec{store().move_message(docid, maildir, flags, move_opts)};
if (!idmsgvec)
throw idmsgvec.error();
for (auto&&[id, msg]: *idmsgvec) {
Sexp sexp{":update"_sym, build_message_sexp(idmsgvec->at(0).second, id, {})};
/* note, the :move t thing is a hint to the frontend that it /* note, the :move t thing is a hint to the frontend that it
* could remove the particular header */ * could remove the particular header */
if (different_mdir) if (different_mdir)
seq.put_props(":move", Sexp::t()); sexp.put_props(":move", Sexp::t());
if (!no_view) if (!no_view && id == docid)
seq.put_props(":maybe-view", Sexp::t()); sexp.put_props(":maybe-view", Sexp::t());
output_sexp(std::move(sexp));
return seq; }
} }
@ -847,7 +853,7 @@ calculate_message_flags(const Message& msg, Option<std::string> flagopt)
return flags.value(); return flags.value();
} }
Sexp void
Server::Private::move_docid(Store::Id docid, Server::Private::move_docid(Store::Id docid,
Option<std::string> flagopt, Option<std::string> flagopt,
bool new_name, bool new_name,
@ -861,9 +867,7 @@ Server::Private::move_docid(Store::Id docid,
throw Error{Error::Code::Store, "failed to get message from store"}; throw Error{Error::Code::Store, "failed to get message from store"};
const auto flags = calculate_message_flags(msg.value(), flagopt); const auto flags = calculate_message_flags(msg.value(), flagopt);
auto lst = perform_move(docid, *msg, "", flags, new_name, no_view); perform_move(docid, *msg, "", flags, new_name, no_view);
return lst;
} }
/* /*
@ -871,9 +875,6 @@ Server::Private::move_docid(Store::Id docid,
* flags. parameters are *either* a 'docid:' or 'msgid:' pointing to * flags. parameters are *either* a 'docid:' or 'msgid:' pointing to
* the message, a 'maildir:' for the target maildir, and a 'flags:' * the message, a 'maildir:' for the target maildir, and a 'flags:'
* parameter for the new flags. * parameter for the new flags.
*
* returns an (:update <new-msg-sexp>)
*
*/ */
void void
Server::Private::move_handler(const Command& cmd) Server::Private::move_handler(const Command& cmd)
@ -890,8 +891,7 @@ Server::Private::move_handler(const Command& cmd)
"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, move_docid(docid, flagopt, rename, no_view);
rename, no_view));
return; return;
} }
auto docid{docids.at(0)}; auto docid{docids.at(0)};
@ -907,7 +907,7 @@ Server::Private::move_handler(const Command& cmd)
* we received (ie., flagstr), if any, plus the existing message * we received (ie., flagstr), if any, plus the existing message
* flags. */ * flags. */
const auto flags = calculate_message_flags(msg, flagopt); const auto flags = calculate_message_flags(msg, flagopt);
output_sexp(perform_move(docid, msg, maildir, flags, rename, no_view)); perform_move(docid, msg, maildir, flags, rename, no_view);
} }
void void
@ -982,43 +982,32 @@ Server::Private::sent_handler(const Command& cmd)
":docid", docid.value())); ":docid", docid.value()));
} }
bool void
Server::Private::view_mark_as_read(Store::Id docid, const Message& msg, bool rename) Server::Private::view_mark_as_read(Store::Id docid, Message&& msg, bool rename)
{ {
/* move some message if the flags changes; and send either a :view (main message
* or :update (the rest))*/
auto maybe_move = [&](Store::Id msg_docid, Flags old_flags,
bool do_rename, bool do_view)->bool {
const auto newflags{flags_from_delta_expr("+S-u-N", old_flags)}; auto move_res = std::invoke([&]()->Result<Store::IdMessageVec> {
if (!newflags || old_flags == *newflags) const auto newflags{flags_from_delta_expr("+S-u-N", msg.flags())};
return false; if (!newflags || msg.flags() == *newflags) {
/* case 1: message was already read; do nothing */
auto updated_msg = store().move_message(msg_docid, {}, newflags, do_rename); Store::IdMessageVec idmvec;
if (!updated_msg) idmvec.emplace_back(docid, std::move(msg));
throw updated_msg.error(); return idmvec;
} else {
output_sexp(Sexp().put_props(do_view ? ":view" : ":update", /* case 2: move message (and possibly dups) */
build_message_sexp(*updated_msg, docid, {}))); Store::MoveOptions move_opts{Store::MoveOptions::DupFlags};
return true; if (rename)
}; move_opts |= Store::MoveOptions::ChangeName;
return store().move_message(docid, {}, newflags, move_opts);
/* now get _al_ the message-ids for the given message-id,
* since, we want to apply the read-status to _all_. */
/* first the main message */
bool moved = maybe_move(docid, msg.flags(), rename, true/*:view*/);
/* now any other message with the same message-id */
for (auto&& rel_docid: docids_for_msgid(store_, msg.message_id())) {
/* ignore main one since we already handled it. */
if (rel_docid == docid)
continue;
if (auto msg{store().find_message(docid)}; msg)
maybe_move(rel_docid, msg->flags(), rename, false/*:update*/);
} }
});
return moved; if (!move_res)
throw move_res.error();
for (auto&& [id, msg]: move_res.value())
output_sexp(Sexp{id == docid ? ":view"_sym : ":update"_sym,
build_message_sexp(msg, id, {})});
} }
void void
@ -1038,10 +1027,12 @@ Server::Private::view_handler(const Command& cmd)
.or_else([]{throw Error{Error::Code::Store, .or_else([]{throw Error{Error::Code::Store,
"failed to find message for view"};}).value(); "failed to find message for view"};}).value();
/* if the message is marked-as-read, the response is handled there; /* if the message should not be marked-as-read, we're done. */
* otherwise, we do so here. */ if (!mark_as_read)
if (!mark_as_read || !view_mark_as_read(docid, msg, rename))
output_sexp(Sexp().put_props(":view", build_message_sexp(msg, docid, {}))); output_sexp(Sexp().put_props(":view", build_message_sexp(msg, docid, {})));
else
view_mark_as_read(docid, std::move(msg), rename);
/* otherwise, mark message and and possible dups as read */
} }
Server::Server(Store& store, Server::Output output) Server::Server(Store& store, Server::Output output)