labels: allow restoring cache-map

E.g. with unexpected termination for mu it is possible that the
labels-cache (i.e., the one that is used for auto-completion) gets disconnected
from reality.

Add a --restore option to `mu label list` to restore the actual labels from the
labels seen in the store.
This commit is contained in:
Dirk-Jan C. Binnema
2025-09-02 21:08:54 +03:00
committed by Seth Ladygo
parent 76031d93d1
commit 124b371850
9 changed files with 83 additions and 17 deletions

View File

@ -23,6 +23,25 @@
using namespace Mu;
Result<void>
Mu::LabelsCache::restore(const Store& store)
{
const auto res{store.run_query("")};
if (!res)
return Err(Error{Error::Code::Query,
"failed to run query: {}",
*res.error().what()});
label_map_.clear();
for (auto&& item: *res) {
if (auto &&msg{item.message()}; msg) {
for (const auto& label: msg->labels())
increase(label);
}
}
return Ok();
}
namespace {
constexpr std::string_view path_key = "path:";
constexpr std::string_view message_id_key = "message-id:";

View File

@ -30,6 +30,8 @@
namespace Mu {
class Store;
/**
* The cache keeps track of what labels are being used. This can be used
* for completion etc. and `mu label list`
@ -143,6 +145,17 @@ public:
return map;
}
/**
* Restore the labels-cache from the labels seen in the store.
*
* @param store a store
*
* @return Ok() or some error
*/
Result<void> restore(const Store& store);
/**
* Is the cache "dirty"?
*
@ -159,8 +172,6 @@ private:
mutable bool dirty_{};
};
class Store;
/**
* Export labels to a file
*

View File

@ -694,6 +694,14 @@ Store::clear_labels(Message& message)
return Ok(std::move(updates));
}
Result<void>
Store::restore_label_map()
{
std::unique_lock lock{priv_->lock_};
return priv_->labels_cache_.restore(*this);
}
LabelsCache::Map
Store::label_map() const
{

View File

@ -373,6 +373,16 @@ public:
*/
Result<Labels::DeltaLabelVec> clear_labels(Message& message);
/**
* Restore label-map from store
*
* Restore the labels list in the store, i.e., restore the cached list of labels which is
* used for e.g. auto-completion in mu4e from the labels in the store.
*
* @return Ok or some error.
*/
Result<void> restore_label_map();
/**
* Get a copy of the map of labels in use.
*
@ -382,6 +392,8 @@ public:
*/
LabelsCache::Map label_map() const;
/**
* Prototype for the ForEachMessageFunc
*

View File

@ -71,6 +71,15 @@ when using a shell.
* LIST OPTIONS
The *list* command lists all the labels that are currently in use in the store.
This is the same information used for auto-completion in *mu4e*.
With the (global, directly after *mu) *--verbose* option, this also includes the
counts.
** --restore
attempt to restore the list from the labels in the store.
It is possible that the list to get outdated, *--restore* fixes this.
* EXPORT OPTIONS

View File

@ -113,11 +113,16 @@ label_clear(Mu::Store& store, const Options& opts)
}
static Result<void>
label_list(const Mu::Store& store, const Options& opts)
label_list(Mu::Store& store, const Options& opts)
{
const auto label_map{store.label_map()};
if (opts.label.restore) {
if (!opts.quiet)
mu_println("labels: restoring list from store...");
if (const auto res = store.restore_label_map(); !res)
return res;
}
for (const auto& [label, n]: label_map)
for (const auto& [label, n]: store.label_map())
if (opts.verbose)
mu_println("{}: {}", label, n);
else

View File

@ -528,6 +528,8 @@ sub_label(CLI::App& sub, Options& opts)
// list
[[maybe_unused]] auto list = sub.add_subcommand("list", "list labels in the store");
list->add_flag("--restore", opts.label.restore,
"Restore the label-list from the labels in store");
add_muhome_option(*list, opts);
// export

View File

@ -209,7 +209,9 @@ struct Options {
bool dry_run{}; /**< Merely print the messages that would be
* labeled without doing so */
StringVec delta_labels; /**< labels to add (+) or remove (-) */
bool read_only{}; /** do not require writable store */
bool read_only{}; /**< do not require writable store */
bool restore{}; /**< restore the labels list */
OptString file; /** file for import/export */

View File

@ -2524,8 +2524,8 @@ field. To see them in your headers / message views, you need to add the field to
the @code{mu4e-headers-fields} and @code{mu4e-view-fields}, respectively.
To change the labels for some message, you specify a @emph{label expression},
which consists of a space-separated sequence of labels, each prefixed either
with a @t{+} to add the label or @t{-} to remove it.
which consists of a space-separated sequence of labels, each prefixed with
either a @t{+} to add the label, or @t{-} to remove it.
For instance, to remove the @t{boring} label and add @t{urgent} from the message
at point or the messages in region, press @kbd{l} and enter:
@ -2533,16 +2533,16 @@ at point or the messages in region, press @kbd{l} and enter:
+urgent -boring
@end example
For @emph{clearing all labels}, you mark with @kbd{L} ('unlabel').
For clearing @emph{all} labels, you can mark with @kbd{L} ('unlabel').
You can search for labels using the @t{label:} field. For instance,
@t{label:urgent} retrieves all messages labeled @t{urgent}.
It is important to note that the labels are only stored in the database (the
message files are not changed). This means that you loose this information when
you remove the database and recrate it; it is however possible to @emph{export}
the labels and re-@emph{import} them later; see the @t{mu-label} man-page for
further details.
@emph{Important}: the labels are only stored in the database (the message files
are not changed). This means that you would @emph{loose} this information when
you remove the database and recreate it, @emph{unless} you @emph{export} the
labels before removin the database and re-@emph{import} them after re-creating
and re-indexing it; see the @t{mu-label} man-page for further details.
@subsection Doing @emph{something}
@ -3185,9 +3185,7 @@ It is easy to add such actions to your configuration; for instance, to enable
@emph{tagging}@footnote{@t{mu4e} does not offer tagging by default since it
mutates the message files, something that @t{mu}/@t{mu4e} generally try to
avoid. An alternative to tagging is @emph{labeling}, @xref{Applying and clearing
labels}
} both in the message view and headers view, you could add:
labels}}, you could add:
@lisp
(add-to-list 'mu4e-headers-actions
'("Tag message" . mu4e-action-retag-message))