mirror of https://github.com/djcb/mu.git
message: better deal with test messages
Allow for specifying path / maildir for tests messages Improve fake_msg_id
This commit is contained in:
parent
00c7fc897d
commit
8ede2a8354
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** Copyright (C) 2022 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
** Copyright (C) 2022 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the GNU General Public License as published by the
|
||||
|
@ -66,7 +66,7 @@ struct Message::Private {
|
|||
|
||||
static void fill_document(Message::Private& priv);
|
||||
|
||||
Message::Message(const std::string& path, Option<const std::string&> mdir):
|
||||
Message::Message(const std::string& path, const std::string& mdir):
|
||||
priv_{std::make_unique<Private>()}
|
||||
{
|
||||
if (!g_path_is_absolute(path.c_str()))
|
||||
|
@ -91,20 +91,29 @@ Message::Message(const std::string& path, Option<const std::string&> mdir):
|
|||
|
||||
priv_->doc.add(Field::Id::Path,
|
||||
Mu::from_gchars(g_canonicalize_filename(path.c_str(), NULL)));
|
||||
priv_->doc.add(Field::Id::Maildir, mdir);
|
||||
if (!mdir.empty())
|
||||
priv_->doc.add(Field::Id::Maildir, mdir);
|
||||
priv_->doc.add(Field::Id::Size, static_cast<int64_t>(statbuf.st_size));
|
||||
|
||||
// rest of the fields
|
||||
fill_document(*priv_);
|
||||
}
|
||||
|
||||
Message::Message(const std::string& text):
|
||||
Message::Message(const std::string& text, const std::string& path,
|
||||
const std::string& mdir):
|
||||
priv_{std::make_unique<Private>()}
|
||||
{
|
||||
if (!path.empty())
|
||||
priv_->doc.add(Field::Id::Path,
|
||||
Mu::from_gchars(
|
||||
g_canonicalize_filename(path.c_str(), NULL)));
|
||||
if (!mdir.empty())
|
||||
priv_->doc.add(Field::Id::Maildir, mdir);
|
||||
|
||||
priv_->doc.add(Field::Id::Size, static_cast<int64_t>(text.size()));
|
||||
|
||||
init_gmime();
|
||||
if (auto msg{MimeMessage::make_from_string(text)}; !msg)
|
||||
if (auto msg{MimeMessage::make_from_text(text)}; !msg)
|
||||
throw msg.error();
|
||||
else
|
||||
priv_->mime_msg = std::move(msg.value());
|
||||
|
@ -318,17 +327,21 @@ static void
|
|||
process_message(const MimeMessage& mime_msg, const std::string& path,
|
||||
Message::Private& info)
|
||||
{
|
||||
info.flags = flags_from_path(path).value_or(Flags::None);
|
||||
|
||||
/* pseudo-flag --> unread means either NEW or NOT SEEN, just
|
||||
* for searching convenience */
|
||||
if (any_of(info.flags & Flags::New) || none_of(info.flags & Flags::Seen))
|
||||
info.flags |= Flags::Unread;
|
||||
/* only have file-flags when there's a path. */
|
||||
if (!path.empty()) {
|
||||
info.flags = flags_from_path(path).value_or(Flags::None);
|
||||
/* pseudo-flag --> unread means either NEW or NOT SEEN, just
|
||||
* for searching convenience */
|
||||
if (any_of(info.flags & Flags::New) || none_of(info.flags & Flags::Seen))
|
||||
info.flags |= Flags::Unread;
|
||||
}
|
||||
|
||||
// parts
|
||||
mime_msg.for_each([&](auto&& parent, auto&& part) {
|
||||
|
||||
if (part.is_part() || part.is_message_part())
|
||||
if (part.is_part() ||
|
||||
part.is_message_part() ||
|
||||
part.is_multipart_signed())
|
||||
info.parts.emplace_back(part);
|
||||
|
||||
if (part.is_part())
|
||||
|
@ -388,20 +401,24 @@ calculate_sha256(const std::string& path)
|
|||
return Ok(g_checksum_get_string(checksum));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a fake-message-id for a message without one.
|
||||
*
|
||||
* @param path message path
|
||||
*
|
||||
* @return a fake message-id
|
||||
*/
|
||||
static std::string
|
||||
fake_message_id(const std::string path)
|
||||
fake_message_id(const std::string& path)
|
||||
{
|
||||
constexpr auto mu_suffix{"@mu.id"};
|
||||
|
||||
if (path.empty())
|
||||
return format("12345@%s", mu_suffix);
|
||||
else if (const auto sha256_res{calculate_sha256(path)}; !sha256_res) {
|
||||
g_warning("failed to get sha-256: %s", sha256_res.error().what());
|
||||
// fallback... not a very good message-id, but should
|
||||
// not happen in practice.
|
||||
// not a very good message-id, only for testing.
|
||||
if (path.empty() || ::access(path.c_str(), R_OK) != 0)
|
||||
return format("%08x%s", g_str_hash(path.c_str()), mu_suffix);
|
||||
} else
|
||||
if (const auto sha256_res{calculate_sha256(path)}; !sha256_res)
|
||||
return format("%08x%s", g_str_hash(path.c_str()), mu_suffix);
|
||||
else
|
||||
return format("%s%s", sha256_res.value().c_str(), mu_suffix);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,15 +52,13 @@ public:
|
|||
* @param path path to message
|
||||
* @param mdir the maildir for this message; i.e, if the path is
|
||||
* ~/Maildir/foo/bar/cur/msg, the maildir would be foo/bar; you can
|
||||
* pass NULL for this parameter, in which case some maildir-specific
|
||||
* pass Nothing for this parameter, in which case some maildir-specific
|
||||
* information is not available.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @return a message or an error
|
||||
*/
|
||||
static Result<Message> make_from_path(const std::string& path,
|
||||
Option<const std::string&> mdir={}) try {
|
||||
const std::string& mdir={}) try {
|
||||
return Ok(Message{path, mdir});
|
||||
} catch (Error& err) {
|
||||
return Err(err);
|
||||
|
@ -88,15 +86,21 @@ public:
|
|||
* Construct a message from a string. This is mostly useful for testing.
|
||||
*
|
||||
* @param text message text
|
||||
* @param path path to message - optional; path does not have to exist.
|
||||
* this is useful for testing.
|
||||
* @param mdir the maildir for this message; optional, useful for testing.
|
||||
*
|
||||
* @return a message or an error
|
||||
*/
|
||||
static Result<Message> make_from_string(const std::string& text) try {
|
||||
return Ok(Message{text});
|
||||
static Result<Message> make_from_text(const std::string& text,
|
||||
const std::string& path={},
|
||||
const std::string& mdir={}) try {
|
||||
return Ok(Message{text, path, mdir});
|
||||
} catch (Error& err) {
|
||||
return Err(err);
|
||||
} catch (...) {
|
||||
return Err(Mu::Error(Error::Code::Message, "failed to create message"));
|
||||
return Err(Mu::Error(Error::Code::Message,
|
||||
"failed to create message from text"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -166,7 +170,11 @@ public:
|
|||
* Get the Message-Id of this message
|
||||
*
|
||||
* @return the Message-Id of this message (without the enclosing <>), or
|
||||
* a fake message-id for messages that don't have them
|
||||
* a fake message-id for messages that don't have them.
|
||||
*
|
||||
* For file-backed message, this fake message-id is based on a hash of the
|
||||
* message contents. For non-file-backed (test) messages, some other value
|
||||
* is concocted.
|
||||
*/
|
||||
std::string message_id() const { return document().string_value(Field::Id::MessageId);}
|
||||
|
||||
|
@ -188,7 +196,7 @@ public:
|
|||
::time_t date() const { return static_cast<time_t>(document().integer_value(Field::Id::Date)); }
|
||||
|
||||
/**
|
||||
* get the flags for this message
|
||||
* get the flags for this message.
|
||||
*
|
||||
* @return the file/content flags
|
||||
*/
|
||||
|
@ -322,8 +330,9 @@ public:
|
|||
|
||||
struct Private;
|
||||
private:
|
||||
Message(const std::string& path, Option<const std::string&> mdir);
|
||||
Message(const std::string& str);
|
||||
Message(const std::string& path, const std::string& mdir);
|
||||
Message(const std::string& str, const std::string& path,
|
||||
const std::string& mdir);
|
||||
Message(Document& doc);
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue