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:
@ -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:";
|
||||
|
||||
@ -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
|
||||
*
|
||||
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -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
|
||||
*
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 */
|
||||
|
||||
|
||||
@ -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))
|
||||
|
||||
Reference in New Issue
Block a user