From bf2f4ce57da439c902fa1b843870d09e20d55225 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Wed, 27 Aug 2025 19:24:04 +0300 Subject: [PATCH] server: add label handler For handling mu4e label update requests. --- lib/mu-server.cc | 51 ++++++++++++++++++++++++++++++++++++++++++++++-- lib/mu-store.hh | 2 +- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/lib/mu-server.cc b/lib/mu-server.cc index 81cdc77c..f5f455fa 100644 --- a/lib/mu-server.cc +++ b/lib/mu-server.cc @@ -40,6 +40,7 @@ #include "mu-query.hh" #include "mu-query-parser.hh" #include "mu-store.hh" +#include "message/mu-labels.hh" #include "utils/mu-utils.hh" #include "utils/mu-utils-file.hh" @@ -72,7 +73,7 @@ struct OutputStream { * @param cdr name of the output (e.g., "contacts") * * @return - */ +` */ OutputStream(): out_{std::ostringstream{}} {} /** @@ -177,6 +178,7 @@ struct Server::Private { void find_handler(const Command& cmd); void help_handler(const Command& cmd); void index_handler(const Command& cmd); + void label_handler(const Command& cmd); void move_handler(const Command& cmd); void mkdir_handler(const Command& cmd); void ping_handler(const Command& cmd); @@ -359,6 +361,18 @@ Server::Private::make_command_map() "whether to avoid indexing up-to-date directories"}}}, "scan maildir for new/updated/removed messages", [&](const auto& params) { index_handler(params); }}); + cmap.emplace( + "label", + CommandInfo{ + ArgMap{ + {":docid", ArgInfo{Type::Number, true, "document-id"}}, + {":labels", ArgInfo{Type::String, true, + "label delta expressions (SPC-separated)"}}, + {":no-view", + ArgInfo{Type::Symbol, false, "if set, do not hint at updating the view"}}, + }, + "move messages and/or change their flags", + [&](const auto& params) { label_handler(params); }}); cmap.emplace( "mkdir", CommandInfo{ @@ -877,6 +891,39 @@ Server::Private::index_handler(const Command& cmd) do_index(conf); } +void +Server::Private::label_handler(const Command& cmd) +{ + const auto labels{*cmd.string_arg(":labels")}; + const auto docid{*cmd.number_arg(":docid")}; + const auto no_view{cmd.boolean_arg(":noupdate")}; + + auto msg = store().find_message(docid) + .or_else([&]{throw Error{Error::Code::InvalidArgument, + "cannot find message {}", docid};}).value(); + + // special case: '-*' means "clear all labels" + if (labels == "-*") { + mu_debug("clear all labels from {} ({})", docid, join(msg.labels(), " ")); + if (const auto res = store().clear_labels(msg); !res) + throw res.error(); + } else { + const auto delta_labels = Labels::parse_delta_labels(labels, " "); + if (!delta_labels) + throw delta_labels.error(); + + mu_debug("apply {} to {} ({})", labels, docid, join(msg.labels(), " ")); + if (const auto res = store().update_labels(msg, *delta_labels); !res) + throw res.error(); + } + + auto sexpstr = "(:update " + msg_sexp_str(msg, docid, {}); + if (!no_view) + sexpstr += " :maybe-view t"; + sexpstr += ')'; + output(std::move(sexpstr)); +} + void Server::Private::mkdir_handler(const Command& cmd) { @@ -990,7 +1037,7 @@ Server::Private::move_handler(const Command& cmd) const auto flagopt{cmd.string_arg(":flags")}; const auto rename{cmd.boolean_arg(":rename")}; const auto no_view{cmd.boolean_arg(":noupdate")}; - const auto docids{determine_docids(store_, cmd)}; + const auto docids{determine_docids(store(), cmd)}; if (docids.empty()) { if (!!cmd.string_arg(":msgid")) { diff --git a/lib/mu-store.hh b/lib/mu-store.hh index 341da2a7..6c1fd5b0 100644 --- a/lib/mu-store.hh +++ b/lib/mu-store.hh @@ -356,7 +356,7 @@ public: * * @param message some message * - * @retgurn Ok or some error + * @return Ok or some error */ Result clear_labels(Message& message);