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;
|
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 {
|
namespace {
|
||||||
constexpr std::string_view path_key = "path:";
|
constexpr std::string_view path_key = "path:";
|
||||||
constexpr std::string_view message_id_key = "message-id:";
|
constexpr std::string_view message_id_key = "message-id:";
|
||||||
|
|||||||
@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
namespace Mu {
|
namespace Mu {
|
||||||
|
|
||||||
|
class Store;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cache keeps track of what labels are being used. This can be used
|
* The cache keeps track of what labels are being used. This can be used
|
||||||
* for completion etc. and `mu label list`
|
* for completion etc. and `mu label list`
|
||||||
@ -143,6 +145,17 @@ public:
|
|||||||
return map;
|
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"?
|
* Is the cache "dirty"?
|
||||||
*
|
*
|
||||||
@ -159,8 +172,6 @@ private:
|
|||||||
mutable bool dirty_{};
|
mutable bool dirty_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class Store;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export labels to a file
|
* Export labels to a file
|
||||||
*
|
*
|
||||||
|
|||||||
@ -694,6 +694,14 @@ Store::clear_labels(Message& message)
|
|||||||
return Ok(std::move(updates));
|
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
|
LabelsCache::Map
|
||||||
Store::label_map() const
|
Store::label_map() const
|
||||||
{
|
{
|
||||||
|
|||||||
@ -373,6 +373,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
Result<Labels::DeltaLabelVec> clear_labels(Message& message);
|
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.
|
* Get a copy of the map of labels in use.
|
||||||
*
|
*
|
||||||
@ -382,6 +392,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
LabelsCache::Map label_map() const;
|
LabelsCache::Map label_map() const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prototype for the ForEachMessageFunc
|
* Prototype for the ForEachMessageFunc
|
||||||
*
|
*
|
||||||
|
|||||||
@ -71,6 +71,15 @@ when using a shell.
|
|||||||
* LIST OPTIONS
|
* LIST OPTIONS
|
||||||
|
|
||||||
The *list* command lists all the labels that are currently in use in the store.
|
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
|
* EXPORT OPTIONS
|
||||||
|
|
||||||
|
|||||||
@ -113,11 +113,16 @@ label_clear(Mu::Store& store, const Options& opts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Result<void>
|
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)
|
if (opts.verbose)
|
||||||
mu_println("{}: {}", label, n);
|
mu_println("{}: {}", label, n);
|
||||||
else
|
else
|
||||||
|
|||||||
@ -528,6 +528,8 @@ sub_label(CLI::App& sub, Options& opts)
|
|||||||
|
|
||||||
// list
|
// list
|
||||||
[[maybe_unused]] auto list = sub.add_subcommand("list", "list labels in the store");
|
[[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);
|
add_muhome_option(*list, opts);
|
||||||
|
|
||||||
// export
|
// export
|
||||||
|
|||||||
@ -209,7 +209,9 @@ struct Options {
|
|||||||
bool dry_run{}; /**< Merely print the messages that would be
|
bool dry_run{}; /**< Merely print the messages that would be
|
||||||
* labeled without doing so */
|
* labeled without doing so */
|
||||||
StringVec delta_labels; /**< labels to add (+) or remove (-) */
|
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 */
|
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.
|
the @code{mu4e-headers-fields} and @code{mu4e-view-fields}, respectively.
|
||||||
|
|
||||||
To change the labels for some message, you specify a @emph{label expression},
|
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
|
which consists of a space-separated sequence of labels, each prefixed with
|
||||||
with a @t{+} to add the label or @t{-} to remove it.
|
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
|
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:
|
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
|
+urgent -boring
|
||||||
@end example
|
@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,
|
You can search for labels using the @t{label:} field. For instance,
|
||||||
@t{label:urgent} retrieves all messages labeled @t{urgent}.
|
@t{label:urgent} retrieves all messages labeled @t{urgent}.
|
||||||
|
|
||||||
It is important to note that the labels are only stored in the database (the
|
@emph{Important}: the labels are only stored in the database (the message files
|
||||||
message files are not changed). This means that you loose this information when
|
are not changed). This means that you would @emph{loose} this information when
|
||||||
you remove the database and recrate it; it is however possible to @emph{export}
|
you remove the database and recreate it, @emph{unless} you @emph{export} the
|
||||||
the labels and re-@emph{import} them later; see the @t{mu-label} man-page for
|
labels before removin the database and re-@emph{import} them after re-creating
|
||||||
further details.
|
and re-indexing it; see the @t{mu-label} man-page for further details.
|
||||||
|
|
||||||
@subsection Doing @emph{something}
|
@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
|
@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
|
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
|
avoid. An alternative to tagging is @emph{labeling}, @xref{Applying and clearing
|
||||||
labels}
|
labels}}, you could add:
|
||||||
|
|
||||||
} both in the message view and headers view, you could add:
|
|
||||||
@lisp
|
@lisp
|
||||||
(add-to-list 'mu4e-headers-actions
|
(add-to-list 'mu4e-headers-actions
|
||||||
'("Tag message" . mu4e-action-retag-message))
|
'("Tag message" . mu4e-action-retag-message))
|
||||||
|
|||||||
Reference in New Issue
Block a user