update to use fmt-based apis

Not complete, but a first big stab converting users of Mu::Error and
various g_warning & friends, format to the new libfmt-based APIs.
This commit is contained in:
Dirk-Jan C. Binnema 2023-07-05 23:10:13 +03:00
parent 742ca33740
commit 4920b56671
46 changed files with 435 additions and 449 deletions

View File

@ -1,5 +1,5 @@
/*
** Copyright (C) 2011-2021 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** Copyright (C) 2011-2023 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
@ -16,17 +16,17 @@
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**
*/
#include <config.h>
#include "mu-guile-message.hh"
#include <libguile.h>
#include "message/mu-message.hh"
#include "utils/mu-utils.hh"
#include <config.h>
#include <glib-object.h>
#include <memory>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wredundant-decls"
#pragma GCC diagnostic ignored "-Wvolatile"
#include <libguile.h>
#pragma GCC diagnostic pop

View File

@ -1,5 +1,5 @@
/*
** Copyright (C) 2011-2022 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** Copyright (C) 2011-2023 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
@ -16,18 +16,13 @@
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**
*/
#include <config.h>
#include "mu-guile.hh"
#include <config.h>
#include <locale.h>
#include <glib-object.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wredundant-decls"
#include <libguile.h>
#pragma GCC diagnostic pop
#include <mu-store.hh>
#include <mu-query.hh>
@ -81,30 +76,30 @@ mu_guile_init_instance(const std::string& muhome) try {
const auto path{runtime_path(RuntimePath::XapianDb, muhome)};
auto store = Store::make(path);
if (!store) {
g_critical("error creating store @ %s: %s", path.c_str(),
store.error().what());
mu_critical("error creating store @ %s: %s", path,
store.error().what());
throw store.error();
} else
StoreSingleton.emplace(std::move(store.value()));
g_debug("mu-guile: opened store @ %s (n=%zu); maildir: %s",
StoreSingleton->path().c_str(),
mu_debug("mu-guile: opened store @ {} (n={}); maildir: {}",
StoreSingleton->path(),
StoreSingleton->size(),
StoreSingleton->root_maildir().c_str());
StoreSingleton->root_maildir());
return true;
} catch (const Xapian::Error& xerr) {
g_critical("%s: xapian error '%s'", __func__, xerr.get_msg().c_str());
mu_critical("{}: xapian error '{}'", __func__, xerr.get_msg());
return false;
} catch (const std::runtime_error& re) {
g_critical("%s: error: %s", __func__, re.what());
mu_critical("{}: error: {}", __func__, re.what());
return false;
} catch (const std::exception& e) {
g_critical("%s: caught exception: %s", __func__, e.what());
mu_critical("{}: caught exception: {}", __func__, e.what());
return false;
} catch (...) {
g_critical("%s: caught exception", __func__);
mu_critical("{}: caught exception", __func__);
return false;
}
@ -118,7 +113,7 @@ Mu::Store&
mu_guile_store()
{
if (!StoreSingleton)
g_error("mu guile not initialized");
mu_error("mu guile not initialized");
return StoreSingleton.value();
}

View File

@ -21,9 +21,14 @@
#define __MU_GUILE_H__
#include <glib.h>
#include <libguile.h>
#include <mu-query.hh>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wredundant-decls"
#pragma GCC diagnostic ignored "-Wvolatile"
#include <libguile.h>
#pragma GCC diagnostic pop
/**
* get the singleton Store instance
*/

View File

@ -67,7 +67,7 @@ struct IndexState {
return state_.load() != rhs;
}
void change_to(State new_state) {
g_debug("changing indexer state %s->%s", name((State)state_),
mu_debug("changing indexer state {}->{}", name((State)state_),
name((State)new_state));
state_.store(new_state);
}
@ -84,9 +84,9 @@ struct Indexer::Private {
return handler(path, statbuf, info);
}},
max_message_size_{store_.config().get<Mu::Config::Id::MaxMessageSize>()} {
g_message("created indexer for %s -> %s (batch-size: %zu)",
store.root_maildir().c_str(),
store.path().c_str(), store.config().get<Mu::Config::Id::BatchSize>());
mu_message("created indexer for {} -> {} (batch-size: {})",
store.root_maildir(), store.path(),
store.config().get<Mu::Config::Id::BatchSize>());
}
~Private() {
@ -148,16 +148,16 @@ Indexer::Private::handler(const std::string& fullpath, struct stat* statbuf,
dirstamp_ = store_.dirstamp(fullpath);
if (conf_.lazy_check && dirstamp_ >= statbuf->st_ctime &&
htype == Scanner::HandleType::EnterNewCur) {
g_debug("skip %s (seems up-to-date: %s >= %s)", fullpath.c_str(),
time_to_string("%FT%T", dirstamp_).c_str(),
time_to_string("%FT%T", statbuf->st_ctime).c_str());
mu_debug("skip {} (seems up-to-date: {} >= {})", fullpath,
time_to_string("%FT%T", dirstamp_),
time_to_string("%FT%T", statbuf->st_ctime));
return false;
}
// don't index dirs with '.noindex'
auto noindex = ::access((fullpath + "/.noindex").c_str(), F_OK) == 0;
if (noindex) {
g_debug("skip %s (has .noindex)", fullpath.c_str());
mu_debug("skip {} (has .noindex)", fullpath);
return false; // don't descend into this dir.
}
@ -166,12 +166,12 @@ Indexer::Private::handler(const std::string& fullpath, struct stat* statbuf,
if (!conf_.ignore_noupdate) {
auto noupdate = ::access((fullpath + "/.noupdate").c_str(), F_OK) == 0;
if (noupdate) {
g_debug("skip %s (has .noupdate)", fullpath.c_str());
mu_debug("skip {} (has .noupdate)", fullpath);
return false;
}
}
g_debug("checked %s", fullpath.c_str());
mu_debug("checked {}", fullpath);
return true;
}
case Scanner::HandleType::LeaveDir: {
@ -183,17 +183,14 @@ Indexer::Private::handler(const std::string& fullpath, struct stat* statbuf,
++progress_.checked;
if ((size_t)statbuf->st_size > max_message_size_) {
g_debug("skip %s (too big: %" G_GINT64_FORMAT " bytes)", fullpath.c_str(),
(gint64)statbuf->st_size);
mu_debug("skip {} (too big: {} bytes)", fullpath, statbuf->st_size);
return false;
}
// if the message is not in the db yet, or not up-to-date, queue
// it for updating/inserting.
if (statbuf->st_ctime <= dirstamp_ && store_.contains_message(fullpath)) {
// g_debug ("skip %s: already up-to-date");
if (statbuf->st_ctime <= dirstamp_ && store_.contains_message(fullpath))
return false;
}
// push the remaining messages to our "todo" queue for
// (re)parsing and adding/updating to the database.
@ -213,7 +210,7 @@ Indexer::Private::maybe_start_worker()
if (todos_.size() > workers_.size() && workers_.size() < max_workers_) {
workers_.emplace_back(std::thread([this] { item_worker(); }));
g_debug("added worker %zu", workers_.size());
mu_debug("added worker {}", workers_.size());
}
}
@ -231,14 +228,12 @@ Indexer::Private::add_message(const std::string& path)
*/
auto msg{Message::make_from_path(path)};
if (!msg) {
g_warning("failed to create message from %s: %s",
path.c_str(), msg.error().what());
mu_warning("failed to create message from {}: {}", path, msg.error().what());
return false;
}
auto res = store_.add_message(msg.value(), true /*use-transaction*/);
if (!res) {
g_warning("failed to add message @ %s: %s",
path.c_str(), res.error().what());
mu_warning("failed to add message @ {}: {}", path, res.error().what());
return false;
}
@ -250,7 +245,7 @@ Indexer::Private::item_worker()
{
WorkItem item;
g_debug("started worker");
mu_debug("started worker");
while (state_ == IndexState::Scanning) {
if (!todos_.pop(item, 250ms))
@ -269,8 +264,7 @@ Indexer::Private::item_worker()
break;
}
} catch (const Mu::Error& er) {
g_warning("error adding message @ %s: %s",
item.full_path.c_str(), er.what());
mu_warning("error adding message @ {}: {}", item.full_path, er.what());
}
maybe_start_worker();
@ -281,15 +275,15 @@ Indexer::Private::item_worker()
bool
Indexer::Private::cleanup()
{
g_debug("starting cleanup");
mu_debug("starting cleanup");
size_t n{};
std::vector<Store::Id> orphans; // store messages without files.
store_.for_each_message_path([&](Store::Id id, const std::string& path) {
++n;
if (::access(path.c_str(), R_OK) != 0) {
g_debug("cannot read %s (id=%u); queueing for removal from store",
path.c_str(), id);
mu_debug("cannot read {} (id={}); queuing for removal from store",
path, id);
orphans.emplace_back(id);
}
@ -297,9 +291,9 @@ Indexer::Private::cleanup()
});
if (orphans.empty())
g_debug("nothing to clean up");
mu_debug("nothing to clean up");
else {
g_debug("removing up %zu stale message(s) from store", orphans.size());
mu_debug("removing {} stale message(s) from store", orphans.size());
store_.remove_messages(orphans);
progress_.removed += orphans.size();
}
@ -313,13 +307,13 @@ Indexer::Private::scan_worker()
progress_.reset();
if (conf_.scan) {
g_debug("starting scanner");
mu_debug("starting scanner");
if (!scanner_.start()) { // blocks.
g_warning("failed to start scanner");
mu_warning("failed to start scanner");
state_.change_to(IndexState::Idle);
return;
}
g_debug("scanner finished with %zu file(s) in queue", todos_.size());
mu_debug("scanner finished with {} file(s) in queue", todos_.size());
}
// now there may still be messages in the work queue...
@ -331,7 +325,7 @@ Indexer::Private::scan_worker()
std::lock_guard lock{w_lock_};
return workers_.size();
});
g_debug("process %zu remaining message(s) with %zu worker(s)",
mu_debug("process {} remaining message(s) with {} worker(s)",
todos_.size(), workers_size);
while (!todos_.empty())
std::this_thread::sleep_for(100ms);
@ -343,11 +337,10 @@ Indexer::Private::scan_worker()
w.join();
if (conf_.cleanup) {
g_debug("starting cleanup");
mu_debug("starting cleanup");
state_.change_to(IndexState::Cleaning);
cleanup();
g_debug("cleanup finished");
mu_debug("cleanup finished");
}
completed_ = ::time({});
@ -369,9 +362,9 @@ Indexer::Private::start(const Indexer::Config& conf)
} else
max_workers_ = conf.max_threads;
g_debug("starting indexer with <= %zu worker thread(s)", max_workers_);
g_debug("indexing: %s; clean-up: %s", conf_.scan ? "yes" : "no",
conf_.cleanup ? "yes" : "no");
mu_debug("starting indexer with <= {} worker thread(s)", max_workers_);
mu_debug("indexing: {}; clean-up: {}", conf_.scan ? "yes" : "no",
conf_.cleanup ? "yes" : "no");
state_.change_to(IndexState::Scanning);
/* kick off the first worker, which will spawn more if needed. */
@ -379,7 +372,7 @@ Indexer::Private::start(const Indexer::Config& conf)
/* kick the disk-scanner thread */
scanner_worker_ = std::thread([this] { scan_worker(); });
g_debug("started indexer");
mu_debug("started indexer");
return true;
}
@ -413,7 +406,7 @@ Indexer::start(const Indexer::Config& conf)
{
const auto mdir{priv_->store_.root_maildir()};
if (G_UNLIKELY(access(mdir.c_str(), R_OK) != 0)) {
g_critical("'%s' is not readable: %s", mdir.c_str(), g_strerror(errno));
mu_critical("'{}' is not readable: {}", mdir, g_strerror(errno));
return false;
}
@ -432,7 +425,7 @@ Indexer::stop()
if (!is_running())
return true;
g_debug("stopping indexer");
mu_debug("stopping indexer");
return priv_->stop();
}

View File

@ -96,14 +96,14 @@ Scanner::Private::process_dentry(const std::string& path, struct dirent *dentry,
if (is_dotdir(d_name) || std::strcmp(d_name, "tmp") == 0)
return true; // ignore.
if (do_ignore(d_name)) {
g_debug("skip %s/%s (ignore)", path.c_str(), d_name);
mu_debug("skip {}/{} (ignore)", path, d_name);
return true; // ignore
}
const auto fullpath{join_paths(path, d_name)};
struct stat statbuf {};
if (::stat(fullpath.c_str(), &statbuf) != 0) {
g_warning("failed to stat %s: %s", fullpath.c_str(), g_strerror(errno));
mu_warning("failed to stat {}: {}", fullpath, g_strerror(errno));
return false;
}
@ -123,7 +123,7 @@ Scanner::Private::process_dentry(const std::string& path, struct dirent *dentry,
} else if (S_ISREG(statbuf.st_mode) && is_maildir)
return handler_(fullpath, &statbuf, Scanner::HandleType::File);
g_debug("skip %s (neither maildir-file nor directory)", fullpath.c_str());
mu_debug("skip {} (neither maildir-file nor directory)", fullpath);
return true;
}
@ -136,7 +136,7 @@ Scanner::Private::process_dir(const std::string& path, bool is_maildir)
const auto dir = opendir(path.c_str());
if (G_UNLIKELY(!dir)) {
g_warning("failed to scan dir %s: %s", path.c_str(), g_strerror(errno));
mu_warning("failed to scan dir {}: {}", path, g_strerror(errno));
return false;
}
@ -153,7 +153,7 @@ Scanner::Private::process_dir(const std::string& path, bool is_maildir)
}
if (errno != 0) {
g_warning("failed to read %s: %s", path.c_str(), g_strerror(errno));
mu_warning("failed to read {}: {}", path, g_strerror(errno));
continue;
}
@ -169,30 +169,29 @@ Scanner::Private::start()
{
const auto& path{root_dir_};
if (G_UNLIKELY(path.length() > PATH_MAX)) {
g_warning("path too long");
mu_warning("path too long");
return false;
}
const auto mode{F_OK | R_OK};
if (G_UNLIKELY(access(path.c_str(), mode) != 0)) {
g_warning("'%s' is not readable: %s", path.c_str(), g_strerror(errno));
mu_warning("'{}' is not readable: {}", path, g_strerror(errno));
return false;
}
struct stat statbuf {
};
struct stat statbuf {};
if (G_UNLIKELY(stat(path.c_str(), &statbuf) != 0)) {
g_warning("'%s' is not stat'able: %s", path.c_str(), g_strerror(errno));
mu_warning("'{}' is not stat'able: {}", path, g_strerror(errno));
return false;
}
if (G_UNLIKELY(!S_ISDIR(statbuf.st_mode))) {
g_warning("'%s' is not a directory", path.c_str());
mu_warning("'{}' is not a directory", path);
return false;
}
running_ = true;
g_debug("starting scan @ %s", root_dir_.c_str());
mu_debug("starting scan @ {}", root_dir_);
auto basename{g_path_get_basename(root_dir_.c_str())};
const auto is_maildir =
@ -202,8 +201,7 @@ Scanner::Private::start()
const auto start{std::chrono::steady_clock::now()};
process_dir(root_dir_, is_maildir);
const auto elapsed = std::chrono::steady_clock::now() - start;
g_debug("finished scan of %s in %" G_GINT64_FORMAT " ms", root_dir_.c_str(),
to_ms(elapsed));
mu_debug("finished scan of {} in {} ms", root_dir_, to_ms(elapsed));
running_ = false;
return true;
@ -215,7 +213,7 @@ Scanner::Private::stop()
if (!running_)
return true; // nothing to do
g_debug("stopping scan");
mu_debug("stopping scan");
running_ = false;
return true;

View File

@ -208,7 +208,7 @@ Document::contacts_value(Field::Id id) const noexcept
const auto ctype{contact_type_from_field_id(id)};
if (G_UNLIKELY(!ctype)) {
g_critical("invalid field-id for contact-type: <%zu>",
mu_critical("invalid field-id for contact-type: <{}>",
static_cast<size_t>(id));
return {};
}
@ -217,7 +217,7 @@ Document::contacts_value(Field::Id id) const noexcept
const auto pos = s.find(SepaChar2);
if (G_UNLIKELY(pos == std::string::npos)) {
g_critical("invalid contact data '%s'", s.c_str());
mu_critical("invalid contact data '{}'", s);
break;
}
@ -348,7 +348,7 @@ Document::remove(Field::Id field_id)
try {
xdoc_.remove_term(term);
} catch(const Xapian::InvalidArgumentError& xe) {
g_critical("failed to remove '%s'", term.c_str());
mu_critical("failed to remove '{}'", term);
}
}
});

View File

@ -77,8 +77,7 @@ validate_field_shortcuts()
#ifdef BUILD_TESTS
if (shortcut != 0) {
if (++no_dups[static_cast<size_t>(shortcut-'a')] > 1) {
g_critical("shortcut '%c' is duplicated",
shortcut);
mu_critical("shortcut '{}' is duplicated", shortcut);
return false;
}
}
@ -105,7 +104,7 @@ validate_field_flags()
++flagnum;
if (flagnum > 1) {
//g_warning("invalid field %*.s", STR_V(field.name));
//mu_warning("invalid field {}", field.name);
return false;
}
}

View File

@ -27,21 +27,19 @@ Mu::maildir_from_path(const std::string& path, const std::string& root)
const auto pos = path.find(root);
if (pos != 0 || path[root.length()] != '/')
return Err(Error{Error::Code::InvalidArgument,
"root '%s' is not a root for path '%s'",
root.c_str(), path.c_str()});
"root '{}' is not a root for path '{}'", root, path});
auto mdir{path.substr(root.length())};
auto slash{mdir.rfind('/')};
if (G_UNLIKELY(slash == std::string::npos) || slash < 4)
return Err(Error{Error::Code::InvalidArgument,
"invalid path: %s", path.c_str()});
"invalid path: {}", path});
mdir.erase(slash);
auto subdir = mdir.data() + slash - 4;
if (G_UNLIKELY(strncmp(subdir, "/cur", 4) != 0 && strncmp(subdir, "/new", 4)))
return Err(Error::Code::InvalidArgument,
"cannot find '/new' or '/cur' - invalid path: %s",
path.c_str());
"cannot find '/new' or '/cur' - invalid path: {}", path);
if (mdir.length() == 4)
return "/";
@ -109,7 +107,7 @@ Mu::flags_from_path(const std::string& path)
if (!flags) {
/* LCOV_EXCL_START*/
return Err(Error{Error::Code::InvalidArgument,
"invalid flags ('%s')", parts.flags_suffix.c_str()});
"invalid flags ('{}')", parts.flags_suffix});
/* LCOV_EXCL_STOP*/
}
@ -182,8 +180,8 @@ test_flags_from_path()
assert_valid_result(res);
/* LCOV_EXCL_START*/
if (g_test_verbose()) {
g_print("%s -> <%s>\n", tcase.first.c_str(),
to_string(res.value()).c_str());
mu_println("{} -> <{}>", tcase.first,
to_string(res.value()));
g_assert_true(res.value() == tcase.second);
}
/*LCOV_EXCL_STOP*/

View File

@ -80,20 +80,18 @@ get_statbuf(const std::string& path, Message::Options opts = Message::Options::N
{
if (none_of(opts & Message::Options::AllowRelativePath) &&
!g_path_is_absolute(path.c_str()))
return Err(Error::Code::File, "path '%s' is not absolute",
path.c_str());
return Err(Error::Code::File, "path '{}' is not absolute", path);
if (::access(path.c_str(), R_OK) != 0)
return Err(Error::Code::File, "file @ '%s' is not readable",
path.c_str());
return Err(Error::Code::File, "file @ '{}' is not readable", path);
struct stat statbuf{};
if (::stat(path.c_str(), &statbuf) < 0)
return Err(Error::Code::File, "cannot stat %s: %s", path.c_str(),
g_strerror(errno));
return Err(Error::Code::File, "cannot stat {}: {}", path,
g_strerror(errno));
if (!S_ISREG(statbuf.st_mode))
return Err(Error::Code::File, "not a regular file: %s", path.c_str());
return Err(Error::Code::File, "not a regular file: {}", path);
return Ok(std::move(statbuf));
}
@ -200,13 +198,13 @@ Message::set_maildir(const std::string& maildir)
maildir.at(0) != '/' ||
(maildir.size() > 1 && maildir.at(maildir.length()-1) == '/'))
return Err(Error::Code::Message,
"'%s' is not a valid maildir", maildir.c_str());
"'{}' is not a valid maildir", maildir.c_str());
const auto path{document().string_value(Field::Id::Path)};
if (path == maildir || path.find(maildir) == std::string::npos)
return Err(Error::Code::Message,
"'%s' is not a valid maildir for message @ %s",
maildir.c_str(), path.c_str());
"'{}' is not a valid maildir for message @ {}",
maildir, path);
priv_->doc.remove(Field::Id::Maildir);
priv_->doc.add(Field::Id::Maildir, maildir);
@ -229,8 +227,8 @@ Message::load_mime_message(bool reload) const
const auto path{document().string_value(Field::Id::Path)};
if (auto mime_msg{MimeMessage::make_from_file(path)}; !mime_msg) {
g_warning("failed to load '%s': %s",
path.c_str(), mime_msg.error().what());
mu_warning("failed to load '{}': {}",
path, mime_msg.error().what());
return false;
} else {
priv_->mime_msg = std::move(mime_msg.value());
@ -258,17 +256,17 @@ get_priority(const MimeMessage& mime_msg)
constexpr std::array<std::pair<std::string_view, Priority>, 10>
prio_alist = {{
{"high", Priority::High},
{"1", Priority::High},
{"2", Priority::High},
{"1", Priority::High},
{"2", Priority::High},
{"normal", Priority::Normal},
{"3", Priority::Normal},
{"3", Priority::Normal},
{"low", Priority::Low},
{"low", Priority::Low},
{"list", Priority::Low},
{"bulk", Priority::Low},
{"4", Priority::Low},
{"5", Priority::Low}
{"4", Priority::Low},
{"5", Priority::Low}
}};
const auto opt_str = mime_msg.header("Precedence")
@ -440,14 +438,13 @@ handle_encrypted(const MimeMultipartEncrypted& part, Message::Private& info)
const auto proto{part.content_type_parameter("protocol").value_or("unknown")};
const auto ctx = MimeCryptoContext::make(proto);
if (!ctx) {
g_warning("failed to create context for protocol <%s>",
proto.c_str());
mu_warning("failed to create context for protocol <{}>", proto);
return;
}
auto res{part.decrypt(*ctx)};
if (!res) {
g_warning("failed to decrypt: %s", res.error().what());
mu_warning("failed to decrypt: {}", res.error().what());
return;
}
@ -538,9 +535,9 @@ process_message(const MimeMessage& mime_msg, const std::string& path,
if (info.body_txt) { /* attempt to get the body-language */
if (const auto lang{detect_language(info.body_txt.value())}; lang) {
info.language = lang->code;
g_debug("detected language: %s", lang->code);
mu_debug("detected language: {}", lang->code);
} else
g_debug("could not detect language");
mu_debug("could not detect language");
}
}
@ -551,8 +548,8 @@ calculate_sha256(const std::string& path)
FILE *file{::fopen(path.c_str(), "r")};
if (!file)
return Err(Error{Error::Code::File, "failed to open %s: %s",
path.c_str(), ::strerror(errno)});
return Err(Error{Error::Code::File, "failed to open {}: {}",
path, ::strerror(errno)});
std::array<uint8_t, 4096> buf{};
while (true) {
@ -566,7 +563,7 @@ calculate_sha256(const std::string& path)
::fclose(file);
if (has_err)
return Err(Error{Error::Code::File, "failed to read %s", path.c_str()});
return Err(Error{Error::Code::File, "failed to read {}", path});
return Ok(g_checksum_get_string(checksum));
}
@ -585,18 +582,19 @@ fake_message_id(const std::string& path)
// 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);
return mu_format("{:08x}{}", g_str_hash(path.c_str()), mu_suffix);
if (const auto sha256_res{calculate_sha256(path)}; !sha256_res)
return format("%08x%s", g_str_hash(path.c_str()), mu_suffix);
return mu_format("{:08x}{}", g_str_hash(path.c_str()), mu_suffix);
else
return format("%s%s", sha256_res.value().c_str(), mu_suffix);
return mu_format("{}{}", sha256_res.value(), mu_suffix);
}
/* many of the doc.add(fiels ....) automatically update the sexp-list as well;
/* many of the doc.add(fields ....) automatically update the sexp-list as well;
* however, there are some _extra_ values in the sexp-list that are not
* based on a field. So we add them here.
*/
static void
doc_add_list_post(Document& doc, const MimeMessage& mime_msg)
{
@ -797,11 +795,10 @@ Message::cache_path(Option<size_t> index) const
if (index) {
GError *err{};
auto tpath = format("%s/%zu", priv_->cache_path.c_str(), *index);
auto tpath = mu_format("{}/{}", priv_->cache_path, *index);
if (g_mkdir(tpath.c_str(), 0700) != 0)
return Err(Error::Code::File, &err,
"failed to create cache dir '%s'; err=%d",
tpath.c_str(), errno);
"failed to create cache dir '{}'; err={}", tpath, errno);
return Ok(std::move(tpath));
} else

View File

@ -49,7 +49,7 @@ Mu::init_gmime(void)
if (gmime_initialized)
return; // already
g_debug("initializing gmime %u.%u.%u",
mu_debug("initializing gmime {}.{}.{}",
gmime_major_version,
gmime_minor_version,
gmime_micro_version);
@ -58,7 +58,7 @@ Mu::init_gmime(void)
gmime_initialized = true;
std::atexit([] {
g_debug("shutting down gmime");
mu_debug("shutting down gmime");
g_mime_shutdown();
gmime_initialized = false;
});
@ -146,7 +146,7 @@ MimeObject::to_file(const std::string& path, bool overwrite) const noexcept
S_IRUSR|S_IWUSR,
&err)};
if (!strm)
return Err(Error::Code::File, &err, "failed to open '%s'", path.c_str());
return Err(Error::Code::File, &err, "failed to open '{}'", path);
MimeStream stream{MimeStream::make_from_stream(strm)};
return write_to_stream({}, stream);
@ -158,14 +158,14 @@ MimeObject::to_string_opt() const noexcept
{
auto stream{MimeStream::make_mem()};
if (!stream) {
g_warning("failed to create mem stream");
mu_warning("failed to create mem stream");
return Nothing;
}
const auto written = g_mime_object_write_to_stream(
self(), {}, GMIME_STREAM(stream.object()));
if (written < 0) {
g_warning("failed to write object to stream");
mu_warning("failed to write object to stream");
return Nothing;
}
@ -246,16 +246,15 @@ MimeCryptoContext::setup_gpg_test(const std::string& testpath)
if (g_mkdir_with_parents((testpath + "/.gnupg").c_str(), 0700) != 0)
return Err(Error::Code::File,
"failed to create gnupg dir; err=%d", errno);
"failed to create gnupg dir; err={}", errno);
auto write_gpgfile=[&](const std::string& fname, const std::string& data)
-> Result<void> {
GError *err{};
std::string path{format("%s/%s", testpath.c_str(), fname.c_str())};
std::string path{mu_format("{}/{}", testpath, fname)};
if (!g_file_set_contents(path.c_str(), data.c_str(), data.size(), &err))
return Err(Error::Code::File, &err,
"failed to write %s", path.c_str());
return Err(Error::Code::File, &err, "failed to write {}", path);
else
return Ok();
};
@ -303,7 +302,7 @@ MimeMessage::make_from_file(const std::string& path)
init_gmime();
if (auto&& stream{g_mime_stream_file_open(path.c_str(), "r", &err)}; !stream)
return Err(Error::Code::Message, &err,
"failed to open stream for %s", path.c_str());
"failed to open stream for {}", path);
else
return make_from_stream(std::move(stream));
}
@ -480,13 +479,13 @@ MimePart::size() const noexcept
{
auto wrapper{g_mime_part_get_content(self())};
if (!wrapper) {
g_warning("failed to get content wrapper");
mu_warning("failed to get content wrapper");
return 0;
}
auto stream{g_mime_data_wrapper_get_stream(wrapper)};
if (!stream) {
g_warning("failed to get stream");
mu_warning("failed to get stream");
return 0;
}
@ -510,13 +509,13 @@ MimePart::to_string() const noexcept
*/
GMimeDataWrapper *wrapper{g_mime_part_get_content(self())};
if (!wrapper) { /* this happens with invalid mails */
g_debug("failed to create data wrapper");
mu_warning("failed to create data wrapper");
return Nothing;
}
GMimeStream *stream{g_mime_stream_mem_new()};
if (!stream) {
g_warning("failed to create mem stream");
mu_warning("failed to create mem stream");
return Nothing;
}
@ -554,7 +553,7 @@ MimePart::to_file(const std::string& path, bool overwrite) const noexcept
S_IRUSR|S_IWUSR,
&err)};
if (!strm)
return Err(Error::Code::File, &err, "failed to open '%s'", path.c_str());
return Err(Error::Code::File, &err, "failed to open '{}'", path);
MimeStream stream{MimeStream::make_from_stream(strm)};
ssize_t written{g_mime_data_wrapper_write_to_stream(
@ -563,7 +562,7 @@ MimePart::to_file(const std::string& path, bool overwrite) const noexcept
if (written < 0) {
return Err(Error::Code::File, &err,
"failed to write to '%s'", path.c_str());
"failed to write to '{}'", path);
}
return Ok(static_cast<size_t>(written));
@ -635,7 +634,7 @@ MimeMultipartSigned::verify(const MimeCryptoContext& ctx, VerifyFlags vflags) co
const auto sign_proto{ctx.signature_protocol()};
if (!proto || !sign_proto || !mime_types_equal(*proto, *sign_proto))
return Err(Error::Code::Crypto, "unsupported protocol " +
return Err(Error::Code::Crypto, "unsupported protocol {}",
proto.value_or("<unknown>"));
const auto sig{signed_signature_part()};
@ -734,7 +733,7 @@ MimeMultipartEncrypted::decrypt(const MimeCryptoContext& ctx, DecryptFlags dflag
const auto enc_proto{ctx.encryption_protocol()};
if (!proto || !enc_proto || !mime_types_equal(*proto, *enc_proto))
return Err(Error::Code::Crypto, "unsupported protocol " +
return Err(Error::Code::Crypto, "unsupported protocol {}",
proto.value_or("<unknown>"));
const auto version{encrypted_version_part()};
@ -744,14 +743,14 @@ MimeMultipartEncrypted::decrypt(const MimeCryptoContext& ctx, DecryptFlags dflag
if (!mime_types_equal(version->mime_type().value_or(""), proto.value()))
return Err(Error::Code::Crypto,
"cannot decrypt; unexpected version content-type '%s' != '%s'",
version->mime_type().value_or("").c_str(),
proto.value().c_str());
"cannot decrypt; unexpected version content-type '{}' != '{}'",
version->mime_type().value_or(""), proto.value());
if (!mime_types_equal(encrypted->mime_type().value_or(""), "application/octet-stream"))
if (!mime_types_equal(encrypted->mime_type().value_or(""),
"application/octet-stream"))
return Err(Error::Code::Crypto,
"cannot decrypt; unexpected encrypted content-type '%s'",
encrypted->mime_type().value_or("").c_str());
"cannot decrypt; unexpected encrypted content-type '{}'",
encrypted->mime_type().value_or(""));
const auto content{encrypted->content()};
auto ciphertext{MimeStream::make_mem()};

View File

@ -674,7 +674,8 @@ struct MimeCryptoContext : public Object {
make(const std::string& protocol) {
auto ctx = g_mime_crypto_context_new(protocol.c_str());
if (!ctx)
return Err(Error::Code::Crypto, "unsupported protocol " + protocol);
return Err(Error::Code::Crypto,
"unsupported protocol {}", protocol);
MimeCryptoContext mctx{ctx};
mctx.unref(); /* remove extra ref */
return Ok(std::move(mctx));

View File

@ -369,7 +369,7 @@ Q46aYjxe0As6AP90bcAZ3dcn5RcTJaM0UhZssguawZ+tnriD3+5DPkMMCg==
const auto mpart{MimeMultipartSigned(mobj)};
const auto sigs{mpart.verify(*ctx)};
if (!sigs)
g_warning("%s", sigs.error().what());
mu_warning("{}", sigs.error().what());
g_assert_true(!!sigs);
g_assert_cmpuint(sigs->size(), ==, 1);

View File

@ -114,9 +114,8 @@ private:
throw rx.error();
rxvec.emplace_back(rx.value());
} catch (const Error& rex) {
g_warning("invalid personal address regexp '%s': %s",
p.c_str(),
rex.what());
mu_warning("invalid personal address regexp '{}': {}",
p, rex.what());
}
}
return rxvec;
@ -136,7 +135,7 @@ ContactsCache::Private::deserialize(const std::string& serialized) const
while (getline(ss, line)) {
const auto parts = Mu::split(line, Separator);
if (G_UNLIKELY(parts.size() != 5)) {
g_warning("error: '%s'", line.c_str());
mu_warning("error: '{}'", line);
continue;
}
Contact ci(parts[0], // email
@ -157,7 +156,7 @@ ContactsCache::Private::serialize() const
{
if (config_db_.read_only()) {
if (dirty_ > 0)
g_critical("dirty data in read-only ccache!"); // bug
mu_critical("dirty data in read-only ccache!"); // bug
return;
}
@ -209,7 +208,7 @@ ContactsCache::add(Contact&& contact)
/* we do _not_ cache invalid email addresses, so we won't offer them in completions etc. It
* should be _rare_, but we've seen cases ( broken local messages) */
if (!contact.has_valid_email()) {
g_warning("not caching invalid e-mail address '%s'", contact.email.c_str());
mu_warning("not caching invalid e-mail address '{}'", contact.email);
return;
}
@ -234,7 +233,7 @@ ContactsCache::add(Contact&& contact)
auto email{contact.email};
// return priv_->contacts_.emplace(ContactUMap::value_type(email, std::move(contact)))
// .first->second;
g_debug("adding contact %s <%s>", contact.name.c_str(), contact.email.c_str());
mu_debug("adding contact {} <{}>", contact.name.c_str(), contact.email.c_str());
priv_->contacts_.emplace(ContactUMap::value_type(email, std::move(contact)));
} else { // existing contact.
@ -248,8 +247,8 @@ ContactsCache::add(Contact&& contact)
existing.tstamp = g_get_monotonic_time();
existing.message_date = contact.message_date;
}
g_debug("updating contact %s <%s> (%zu)",
contact.name.c_str(), contact.email.c_str(), existing.frequency);
mu_debug("updating contact {} <{}> ({})",
contact.name, contact.email, existing.frequency);
}
}
@ -528,11 +527,11 @@ test_mu_contacts_cache_sort()
auto result_chars = [](const Mu::ContactsCache& ccache)->std::string {
std::string str;
if (g_test_verbose())
g_print("contacts-cache:\n");
fmt::print("contacts-cache:\n");
ccache.for_each([&](auto&& contact) {
if (g_test_verbose())
g_print("\t- %s\n", contact.display_name().c_str());
fmt::print("\t- {}\n", contact.display_name());
str += contact.name;
return true;
});

View File

@ -88,8 +88,8 @@ create_maildir(const std::string& path, mode_t mode)
* permissions; so we need to check */
if (rv != 0 || !check_dir(fullpath, true/*readable*/, true/*writable*/))
return Err(Error{Error::Code::File,
"creating dir failed for %s: %s",
fullpath.c_str(), g_strerror(errno)});
"creating dir failed for {}: {}",
fullpath, g_strerror(errno)});
}
return Ok();
@ -104,7 +104,7 @@ create_noindex(const std::string& path)
int fd = ::creat(noindexpath.c_str(), 0644);
if (fd < 0 || ::close(fd) != 0)
return Err(Error{Error::Code::File,
"error creating .noindex: %s", g_strerror(errno)});
"error creating .noindex: {}", g_strerror(errno)});
else
return Ok();
}
@ -141,8 +141,7 @@ check_subdir(const std::string& src, bool& in_cur)
g_free(srcpath);
if (invalid)
return Err(Error{Error::Code::File, "invalid source message '%s'",
src.c_str()});
return Err(Error{Error::Code::File, "invalid source message '{}'", src});
else
return Ok();
}
@ -186,10 +185,8 @@ Mu::maildir_link(const std::string& src, const std::string& targetpath,
auto rv{::symlink(src.c_str(), path_res->c_str())};
if (rv != 0)
return Err(Error{Error::Code::File,
"error creating link %s => %s: %s",
path_res->c_str(),
src.c_str(),
g_strerror(errno)});
"error creating link {} => {}: {}",
*path_res, src, g_strerror(errno)});
return Ok();
}
@ -209,19 +206,20 @@ clear_links(const std::string& path, DIR* dir)
continue; /* ignore .,.. other dotdirs */
const auto fullpath{join_paths(path, dentry->d_name)};
const auto d_type = get_dtype(dentry, fullpath.c_str(), true/*lstat*/);
const auto d_type = get_dtype(dentry, fullpath.c_str(),
true/*lstat*/);
switch(d_type) {
case DT_LNK:
if (::unlink(fullpath.c_str()) != 0) {
g_warning("error unlinking %s: %s",
fullpath.c_str(), g_strerror(errno));
mu_warning("error unlinking {}: {}",
fullpath, g_strerror(errno));
res = false;
}
break;
case DT_DIR: {
DIR* subdir{::opendir(fullpath.c_str())};
if (!subdir) {
g_warning("failed to open dir %s: %s", fullpath.c_str(),
mu_warning("failed to open dir {}: {}", fullpath,
g_strerror(errno));
res = false;
}
@ -243,8 +241,8 @@ Mu::maildir_clear_links(const std::string& path)
{
const auto dir{::opendir(path.c_str())};
if (!dir)
return Err(Error{Error::Code::File, "failed to open %s: %s",
path.c_str(), g_strerror(errno)});
return Err(Error{Error::Code::File, "failed to open {}: {}",
path, g_strerror(errno)});
clear_links(path, dir);
::closedir(dir);
@ -258,16 +256,15 @@ msg_move_verify(const std::string& src, const std::string& dst)
/* double check -- is the target really there? */
if (::access(dst.c_str(), F_OK) != 0)
return Err(Error{Error::Code::File,
"can't find target (%s->%s)",
src.c_str(), dst.c_str()});
"can't find target ({}->{})", src, dst});
if (::access(src.c_str(), F_OK) == 0) {
if (src == dst) {
g_warning("moved %s to itself", src.c_str());
mu_warning("moved {} to itself", src);
}
/* this could happen if some other tool (for mail syncing) is
* interfering */
g_debug("the source is still there (%s->%s)", src.c_str(), dst.c_str());
mu_debug("source is still there ({}->{})", src, dst);
}
return Ok();
@ -292,15 +289,14 @@ msg_move_g_file(const std::string& src, const std::string& dst)
return Ok();
else
return Err(Error{Error::Code::File, &err/*consumed*/,
"error moving %s -> %s",
src.c_str(), dst.c_str()});
"error moving {} -> {}", src, dst});
}
static Mu::Result<void>
msg_move(const std::string& src, const std::string& dst, bool force_gio)
{
if (::access(src.c_str(), R_OK) != 0)
return Err(Error{Error::Code::File, "cannot read %s", src.c_str()});
return Err(Error{Error::Code::File, "cannot read {}", src});
if (!force_gio) { /* for testing */
@ -308,8 +304,8 @@ msg_move(const std::string& src, const std::string& dst, bool force_gio)
return msg_move_verify(src, dst);
if (errno != EXDEV) /* some unrecoverable error occurred */
return Err(Error{Error::Code::File, "error moving %s -> %s: %s",
src.c_str(), dst.c_str(), strerror(errno)});
return Err(Error{Error::Code::File, "error moving {} -> {}: {}",
src, dst, strerror(errno)});
}
/* the EXDEV / force-gio case -- source and target live on different
@ -330,7 +326,7 @@ Mu::maildir_move_message(const std::string& oldpath,
if (oldpath == newpath)
return Ok(); // nothing to do.
g_debug("moving %s --> %s", oldpath.c_str(), newpath.c_str());
mu_debug("moving {} --> {}", oldpath, newpath);
return msg_move(oldpath, newpath, force_gio);
}
@ -387,27 +383,26 @@ check_determine_target_params (const std::string& old_path,
{
if (!g_path_is_absolute(old_path.c_str()))
return Err(Error{Error::Code::File,
"old_path is not absolute (%s)", old_path.c_str()});
"old_path is not absolute ({})", old_path});
if (!g_path_is_absolute(root_maildir_path.c_str()))
return Err(Error{Error::Code::File,
"root maildir path is not absolute",
root_maildir_path.c_str()});
"root maildir path is not absolute ({})",
root_maildir_path});
if (!target_maildir.empty() && target_maildir[0] != '/')
return Err(Error{Error::Code::File,
"target maildir must be empty or start with / (%s)",
target_maildir.c_str()});
"target maildir must be empty or start with / ({})",
target_maildir});
if (old_path.find(root_maildir_path) != 0)
return Err(Error{Error::Code::File,
"old-path must be below root-maildir (%s) (%s)",
old_path.c_str(), root_maildir_path.c_str()});
"old-path must be below root-maildir ({}) ({})",
old_path, root_maildir_path});
if (any_of(newflags & Flags::New) && newflags != Flags::New)
return Err(Error{Error::Code::File,
"if ::New is specified, "
"it must be the only flag"});
"if ::New is specified, it must be the only flag"});
return Ok();
}

View File

@ -43,7 +43,7 @@ using namespace Mu;
// <regex> -> [field:]/regex/
#define BUG(...) \
Mu::Error(Error::Code::Internal, format("%u: BUG: ", __LINE__) + format(__VA_ARGS__))
Mu::Error(Error::Code::Internal, "BUG @ line {}", __LINE__);
/**
* Get the "shortcut"/internal fields for the the given fieldstr or empty if there is none

View File

@ -91,9 +91,9 @@ Query::Private::make_enquire(const std::string& expr,
WarningVec warns;
const auto tree{parser_.parse(expr, warns)};
for (auto&& w : warns)
g_warning("query warning: %s", to_string(w).c_str());
mu_warning("query warning: {}", to_string(w));
enq.set_query(xapian_query(tree));
g_debug("qtree: %s", to_string(tree).c_str());
mu_debug("qtree: {}", to_string(tree));
}
sort_enquire(enq, sortfield_id, qflags);
@ -291,7 +291,7 @@ Query::parse(const std::string& expr, bool xapian) const
WarningVec warns;
const auto tree{priv_->parser_.parse(expr, warns)};
for (auto&& w : warns)
g_warning("query warning: %s", to_string(w).c_str());
mu_warning("query warning: {}", to_string(w));
if (xapian)
return xapian_query(tree).get_description();

View File

@ -1,5 +1,5 @@
/*
** Copyright (C) 2022 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** Copyright (C) 2022-2023 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
@ -19,14 +19,6 @@
#include "config.h"
#include "mu-script.hh"
#ifdef BUILD_GUILE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wredundant-decls"
#include <libguile.h>
#pragma GCC diagnostic pop
#endif /*BUILD_GUILE*/
#include "mu/mu-options.hh"
#include "utils/mu-utils.hh"
#include "utils/mu-option.hh"
@ -34,6 +26,14 @@
#include <fstream>
#include <iostream>
#ifdef BUILD_GUILE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wredundant-decls"
#pragma GCC diagnostic ignored "-Wvolatile"
#include <libguile.h>
#pragma GCC diagnostic pop
#endif /*BUILD_GUILE*/
using namespace Mu;
static std::string
@ -58,7 +58,7 @@ get_info(std::string&& path, const std::string& prefix)
{
std::ifstream file{path};
if (!file.is_open()) {
g_warning ("failed to open %s", path.c_str());
mu_warning ("failed to open {}", path);
return Nothing;
}
@ -93,7 +93,7 @@ script_infos_in_dir(const std::string& scriptdir, Mu::ScriptInfos& infos)
{
DIR *dir = opendir(scriptdir.c_str());
if (!dir) {
g_debug("failed to open '%s': %s", scriptdir.c_str(),
mu_debug("failed to open '{}': {}", scriptdir,
g_strerror(errno));
return;
}

View File

@ -1,5 +1,5 @@
/*
** Copyright (C) 2020-2022 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** Copyright (C) 2020-2023 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
@ -337,23 +337,15 @@ Server::Private::make_command_map()
return cmap;
}
G_GNUC_PRINTF(2, 3)
static Sexp
make_error(Error::Code code, const char* frm, ...)
{
va_list ap;
va_start(ap, frm);
auto err = Sexp().put_props(
":error", Error::error_number(code),
":message", vformat(frm, ap));
va_end(ap);
return err;
}
bool
Server::Private::invoke(const std::string& expr) noexcept
{
auto make_error=[](auto&& code, auto&& msg) {
return Sexp().put_props(
":error", Error::error_number(code),
":message", msg);
};
if (!keep_going_)
return false;
try {
@ -366,17 +358,20 @@ Server::Private::invoke(const std::string& expr) noexcept
throw res.error();
} catch (const Mu::Error& me) {
output_sexp(make_error(me.code(), "%s", me.what()));
output_sexp(make_error(me.code(), mu_format("{}", me.what())));
keep_going_ = true;
} catch (const Xapian::Error& xerr) {
output_sexp(make_error(Error::Code::Internal, "xapian error: %s: %s",
xerr.get_type(), xerr.get_description().c_str()));
output_sexp(make_error(Error::Code::Internal,
mu_format("xapian error: {}: {}",
xerr.get_type(), xerr.get_description())));
keep_going_ = false;
} catch (const std::runtime_error& re) {
output_sexp(make_error(Error::Code::Internal, "caught exception: %s", re.what()));
output_sexp(make_error(Error::Code::Internal,
mu_format("caught exception: {}", re.what())));
keep_going_ = false;
} catch (...) {
output_sexp(make_error(Error::Code::Internal, "something went wrong: quiting"));
output_sexp(make_error(Error::Code::Internal,
mu_format("something went wrong: quitting")));
keep_going_ = false;
}
@ -405,8 +400,7 @@ Server::Private::add_handler(const Command& cmd)
auto msg_res{store().find_message(docid)};
if (!msg_res)
throw Error(Error::Code::Store,
"failed to get message at %s (docid=%u): %s",
path->c_str(), docid);
"failed to get message at {} (docid={})", *path, docid);
output_sexp(Sexp().put_props(":update",
build_message_sexp(msg_res.value(), docid, {})));
@ -470,7 +464,7 @@ Server::Private::compose_handler(const Command& cmd)
const unsigned docid{static_cast<unsigned>(cmd.number_arg(":docid").value_or(0))};
auto msg{store().find_message(docid)};
if (!msg)
throw Error{Error::Code::Store, "failed to get message %u", docid};
throw Error{Error::Code::Store, "failed to get message {}", docid};
comp_lst.put_props(":original", build_message_sexp(msg.value(), docid, {}));
@ -492,8 +486,7 @@ Server::Private::compose_handler(const Command& cmd)
}
} else if (ctype != "new")
throw Error(Error::Code::InvalidArgument, "invalid compose type '%s'",
ctype.c_str());
throw Error(Error::Code::InvalidArgument, "invalid compose type '{}'", ctype);
output_sexp(comp_lst);
}
@ -510,10 +503,8 @@ Server::Private::contacts_handler(const Command& cmd)
parse_date_time(afterstr, true).value_or(0)};
const auto tstamp = g_ascii_strtoll(tstampstr.c_str(), NULL, 10);
g_debug("find %s contacts last seen >= %s (tstamp: %zu)",
personal ? "personal" : "any",
time_to_string("%c", after).c_str(),
static_cast<size_t>(tstamp));
mu_debug("find {} contacts last seen >= {} (tstamp: {})",
personal ? "personal" : "any", time_to_string("%c", after), tstamp);
auto n{0};
Sexp contacts;
@ -540,7 +531,7 @@ Server::Private::contacts_handler(const Command& cmd)
":tstamp", format("%" G_GINT64_FORMAT, g_get_monotonic_time()));
/* dump the contacts cache as a giant sexp */
g_debug("sending %d of %zu contact(s)", n, store().contacts_cache().size());
mu_debug("sending {} of {} contact(s)", n, store().contacts_cache().size());
output_sexp(seq, Server::OutputFlags::SplitList);
}
@ -549,8 +540,7 @@ static std::vector<Store::Id>
docids_for_msgid(const Store& store, const std::string& msgid, size_t max = 100)
{
if (msgid.size() > MaxTermLength) {
throw Error(Error::Code::InvalidArgument,
"invalid message-id '%s'", msgid.c_str());
throw Error(Error::Code::InvalidArgument, "invalid message-id '{}'", msgid);
} else if (msgid.empty())
return {};
@ -566,10 +556,10 @@ docids_for_msgid(const Store& store, const std::string& msgid, size_t max = 100)
g_free(expr);
if (!res)
throw Error(Error::Code::Store, &gerr,
"failed to run message-id-query: %s", res.error().what());
"failed to run message-id-query: {}", res.error().what());
else if (res->empty())
throw Error(Error::Code::NotFound,
"could not find message(s) for msgid %s", msgid.c_str());
"could not find message(s) for msgid {}", msgid);
std::vector<Store::Id> docids{};
for (auto&& mi : *res)
@ -590,7 +580,7 @@ path_from_docid(const Store& store, Store::Id docid)
throw Error(Error::Code::Store, "could not get message from store");
if (auto path{msg->path()}; path.empty())
throw Error(Error::Code::Store, "could not get path for message %u",
throw Error(Error::Code::Store, "could not get path for message {}",
docid);
else
return path;
@ -667,17 +657,17 @@ Server::Private::find_handler(const Command& cmd)
if (const auto arg = cmd.symbol_arg(":sortfield"); !arg)
return Field::Id::Date;
else if (arg->length() < 2)
throw Error{Error::Code::InvalidArgument, "invalid sort field '%s'",
arg->c_str()};
throw Error{Error::Code::InvalidArgument, "invalid sort field '{}'",
*arg};
else if (const auto field{field_from_name(arg->substr(1))}; !field)
throw Error{Error::Code::InvalidArgument, "invalid sort field '%s'",
arg->c_str()};
throw Error{Error::Code::InvalidArgument, "invalid sort field '{}'",
*arg};
else
return field->id;
});
if (batch_size < 1)
throw Error{Error::Code::InvalidArgument, "invalid batch-size %d", batch_size};
throw Error{Error::Code::InvalidArgument, "invalid batch-size {}", batch_size};
auto qflags{QueryFlags::SkipUnreadable}; // don't show unreadables.
if (descending)
@ -695,7 +685,7 @@ Server::Private::find_handler(const Command& cmd)
std::lock_guard l{store_.lock()};
auto qres{store_.run_query(q, sort_field_id, qflags, maxnum)};
if (!qres)
throw Error(Error::Code::Query, "failed to run query: %s", qres.error().what());
throw Error(Error::Code::Query, "failed to run query: {}", qres.error().what());
/* before sending new results, send an 'erase' message, so the frontend
* knows it should erase the headers buffer. this will ensure that the
@ -864,7 +854,7 @@ calculate_message_flags(const Message& msg, Option<std::string> flagopt)
if (!flags)
throw Error{Error::Code::InvalidArgument,
"invalid flags '%s'", flagopt.value_or("").c_str()};
"invalid flags '{}'", flagopt.value_or("")};
else
return flags.value();
}
@ -913,7 +903,7 @@ Server::Private::move_handler(const Command& cmd)
const auto docid{docids.at(0)};
auto msg = store().find_message(docid)
.or_else([&]{throw Error{Error::Code::InvalidArgument,
"cannot find message %u", docid};}).value();
"cannot find message {}", docid};}).value();
/* if maildir was not specified, take the current one */
if (maildir.empty())
@ -982,12 +972,10 @@ Server::Private::remove_handler(const Command& cmd)
if (::unlink(path.c_str()) != 0 && errno != ENOENT)
throw Error(Error::Code::File,
"could not delete %s: %s",
path.c_str(),
g_strerror(errno));
"could not delete {}: {}", path, g_strerror(errno));
if (!store().remove_message(path))
g_warning("failed to remove message @ %s (%d) from store", path.c_str(), docid);
mu_warning("failed to remove message @ {} ({}) from store", path, docid);
output_sexp(Sexp().put_props(":remove", docid)); // act as if it worked.
}
@ -997,8 +985,9 @@ Server::Private::sent_handler(const Command& cmd)
const auto path{cmd.string_arg(":path").value_or("")};
const auto docid = store().add_message(path);
if (!docid)
throw Error{Error::Code::Store, "failed to add path: %s",
docid.error().what()};
throw Error{Error::Code::Store, "failed to add path: {}: {}",
path, docid.error().what()};
output_sexp(Sexp().put_props(
":sent", Sexp::t_sym,
":path", path,

View File

@ -71,18 +71,18 @@ struct Store::Private {
{}
~Private() try {
g_debug("closing store @ %s", xapian_db_.path().c_str());
mu_debug("closing store @ {}", xapian_db_.path());
if (!xapian_db_.read_only()) {
transaction_maybe_commit(true /*force*/);
}
} catch (...) {
g_critical("caught exception in store dtor");
mu_critical("caught exception in store dtor");
}
// If not started yet, start a transaction. Otherwise, just update the transaction size.
void transaction_inc() noexcept {
if (transaction_size_ == 0) {
g_debug("starting transaction");
mu_debug("starting transaction");
xapian_db_.begin_transaction();
}
++transaction_size_;
@ -102,16 +102,12 @@ struct Store::Private {
if (transaction_size_ == 0)
return; // nothing more to do here.
g_debug("committing transaction (n=%zu)", transaction_size_);
mu_debug("committing transaction (n={})", transaction_size_);
xapian_db_.commit_transaction();
transaction_size_ = 0;
}
}
time_t metadata_time_t(const std::string& key) const {
return static_cast<time_t>(::atoll(xapian_db_.metadata(key).c_str()));
}
XapianDb make_db(const std::string& path, XapianDb::Flavor flavor) {
if (auto&& res{XapianDb::make(path, flavor)}; res)
return std::move(res.value());
@ -193,7 +189,7 @@ Store::Store(const std::string& path, Store::Options opts)
/* don't try to recover from version with an incompatible scheme */
if (s_version < 500)
throw Mu::Error(Error::Code::CannotReinit,
"old schema (%zu) is too old to re-initialize from",
"old schema ({}) is too old to re-initialize from",
s_version);
const auto old_root_maildir{root_maildir()};
@ -210,7 +206,7 @@ Store::Store(const std::string& path, Store::Options opts)
/* otherwise, the schema version should match. */
if (s_version != ExpectedSchemaVersion)
throw Mu::Error(Error::Code::SchemaMismatch,
"expected schema-version %zu, but got %zu",
"expected schema-version {}, but got {}",
ExpectedSchemaVersion, s_version);
}
@ -433,7 +429,7 @@ static Store::IdMessageVec
messages_with_msgid(const Store& store, const std::string& msgid, size_t max=100)
{
if (msgid.size() > MaxTermLength) {
g_warning("invalid message-id '%s'", msgid.c_str());
mu_warning("invalid message-id '{}'", msgid.c_str());
return {};
} else if (msgid.empty())
return {};
@ -447,11 +443,11 @@ messages_with_msgid(const Store& store, const std::string& msgid, size_t max=100
const auto res{store.run_query(expr, {}, QueryFlags::None, max)};
g_free(expr);
if (!res) {
g_warning("failed to run message-id-query: %s", res.error().what());
mu_warning("failed to run message-id-query: {}", res.error().what());
return {};
}
if (res->empty()) {
g_warning("could not find message(s) for msgid %s", msgid.c_str());
mu_warning("could not find message(s) for msgid {}", msgid);
return {};
}
@ -483,7 +479,7 @@ Store::move_message(Store::Id id,
auto msg{priv_->find_message_unlocked(id)};
if (!msg)
return Err(Error::Code::Store, "cannot find message <%u>", id);
return Err(Error::Code::Store, "cannot find message <{}>", id);
auto res{priv_->move_message_unlocked(std::move(*msg), target_mdir, new_flags, opts)};
if (!res)
@ -513,7 +509,7 @@ Store::move_message(Store::Id id,
if (dup_res)
imvec.emplace_back(docid, std::move(*dup_res));
else
g_warning("failed to move dup: %s", dup_res.error().what());
mu_warning("failed to move dup: {}", dup_res.error().what());
}
return Ok(std::move(imvec));

View File

@ -102,8 +102,8 @@ XapianDb::make(const std::string& db_path, Flavor flavor) noexcept try {
g_setenv("XAPIAN_FLUSH_THRESHOLD", "500000", 1);
/* create path if needed */
if (g_mkdir_with_parents(db_path.c_str(), 0700) != 0)
return Err(Error::Code::File, "failed to create database dir %s: %s",
db_path.c_str(), ::strerror(errno));
return Err(Error::Code::File, "failed to create database dir {}: {}",
db_path, ::strerror(errno));
}
switch (flavor) {
@ -125,12 +125,12 @@ XapianDb::make(const std::string& db_path, Flavor flavor) noexcept try {
}
} catch (const Xapian::DatabaseLockError& xde) {
return Err(Error::Code::StoreLock, "%s", xde.get_msg().c_str());
return Err(Error::Code::StoreLock, "{}", xde.get_msg());
} catch (const Xapian::DatabaseError& xde) {
return Err(Error::Code::Store, "%s", xde.get_msg().c_str());
return Err(Error::Code::Store, "{}", xde.get_msg());
} catch (const Mu::Error& me) {
return Err(me);
} catch (...) {
return Err(Error::Code::Internal,
"something went wrong when opening store @ %s", db_path.c_str());
"something went wrong when opening store @ {}", db_path);
}

View File

@ -31,6 +31,7 @@
#include <xapian.h>
#include <utils/mu-result.hh>
#include <utils/mu-utils.hh>
namespace Mu {
@ -42,13 +43,13 @@ xapian_try(Func&& func) noexcept
try {
func();
} catch (const Xapian::Error& xerr) {
g_critical("%s: xapian error '%s'", __func__, xerr.get_msg().c_str());
mu_critical("{}: xapian error '{}'", __func__, xerr.get_msg());
} catch (const std::runtime_error& re) {
g_critical("%s: runtime error: %s", __func__, re.what());
mu_critical("{}: runtime error: {}", __func__, re.what());
} catch (const std::exception& e) {
g_critical("%s: caught std::exception: %s", __func__, e.what());
mu_critical("{}: caught std::exception: {}", __func__, e.what());
} catch (...) {
g_critical("%s: caught exception", __func__);
mu_critical("{}: caught exception", __func__);
}
template <typename Func, typename Default = std::invoke_result<Func>> auto
@ -58,30 +59,29 @@ try {
} catch (const Xapian::DocNotFoundError& xerr) {
return static_cast<Default>(def);
} catch (const Xapian::Error& xerr) {
g_warning("%s: xapian error '%s'", __func__, xerr.get_msg().c_str());
mu_warning("{}: xapian error '{}'", __func__, xerr.get_msg());
return static_cast<Default>(def);
} catch (const std::runtime_error& re) {
g_critical("%s: runtime error: %s", __func__, re.what());
mu_critical("{}: runtime error: {}", __func__, re.what());
return static_cast<Default>(def);
} catch (const std::exception& e) {
g_critical("%s: caught std::exception: %s", __func__, e.what());
mu_critical("{}: caught std::exception: {}", __func__, e.what());
return static_cast<Default>(def);
} catch (...) {
g_critical("%s: caught exception", __func__);
mu_critical("{}: caught exception", __func__);
return static_cast<Default>(def);
}
template <typename Func> auto
xapian_try_result(Func&& func) noexcept -> std::decay_t<decltype(func())>
try {
return func();
} catch (const Xapian::Error& xerr) {
return Err(Error::Code::Xapian, "%s", xerr.get_error_string());
return Err(Error::Code::Xapian, "{}", xerr.get_error_string());
} catch (const std::runtime_error& re) {
return Err(Error::Code::Internal, "runtime error: %s", re.what());
return Err(Error::Code::Internal, "runtime error: {}", re.what());
} catch (const std::exception& e) {
return Err(Error::Code::Internal, "caught std::exception: %s", e.what());
return Err(Error::Code::Internal, "caught std::exception: {}", e.what());
} catch (...) {
return Err(Error::Code::Internal, "caught exception");
}

View File

@ -443,7 +443,7 @@ tear_down()
GError *err{};
const auto cmd{format("/bin/rm -rf '%s' '%s'", BENCH_MAILDIRS, BENCH_STORE)};
if (!g_spawn_command_line_sync(cmd.c_str(), NULL, NULL, NULL, &err)) {
g_warning("error: %s\n", err ? err->message : "?");
mu_warning("error: {}", err ? err->message : "?");
g_clear_error(&err);
}
}

View File

@ -47,12 +47,13 @@ assert_contacts_equal(const Contacts& contacts,
size_t n{};
for (auto&& contact: contacts) {
if (g_test_verbose())
g_message("{ \"%s\", \"%s\"},\n", contact.name.c_str(), contact.email.c_str());
mu_message("{{ \"{}\", \"{}\"}},\n",
contact.name, contact.email);
assert_equal(contact.name, expected.at(n).first);
assert_equal(contact.email, expected.at(n).second);
++n;
}
g_print("\n");
mu_print("\n");
}
@ -97,7 +98,7 @@ test_mu_msg_02(void)
g_assert_true(msg.priority() /* 'low' */
== Priority::Low);
g_assert_cmpuint(msg.date(), ==, 1218051515);
g_print("flags: %s\n", Mu::to_string(msg.flags()).c_str());
mu_println("flags: {}", Mu::to_string(msg.flags()));
g_assert_true(msg.flags() == (Flags::Seen|Flags::MailingList));
assert_contacts_equal(msg.all_contacts(), {

View File

@ -80,7 +80,5 @@ test('test-lang-detector',
executable('test-lang-detector', 'mu-lang-detector.cc',
install: false,
cpp_args: ['-DBUILD_TESTS'],
dependencies: [glib_dep, lib_mu_utils_dep, cld2_dep, config_h_dep]))
subdir('tests')

View File

@ -36,8 +36,8 @@ Command::string_vec_arg(const std::string& name) const
std::vector<std::string> vec;
for (const auto& item : val->list()) {
if (!item.stringp()) {
// g_warning("command: non-string in string-list for %s: %s",
// name.c_str(), to_string().c_str());
// mu_warning("command: non-string in string-list for {}: {}",
// name, to_string());
return Nothing;
} else
vec.emplace_back(item.string());
@ -68,19 +68,17 @@ validate(const CommandHandler::CommandInfoMap& cmap,
if (param_it == cmd.cend()) {
if (arginfo.required)
return Err(Error::Code::Command,
"missing required parameter %s in command '%s'",
argname.c_str(), cmd.to_string().c_str());
"missing required parameter {} in command '{}'",
argname, cmd.to_string());
continue; // not required
}
// the types must match, but the 'nil' symbol is acceptable as "no value"
if (param_val->type() != arginfo.type && !(param_val->nilp()))
return Err(Error::Code::Command,
"parameter %s expects type %s, but got %s in command '%s'",
argname.c_str(),
to_string(arginfo.type).c_str(),
to_string(param_val->type()).c_str(),
cmd.to_string().c_str());
"parameter {} expects type {}, but got {} in command '{}'",
argname, to_string(arginfo.type),
to_string(param_val->type()), cmd.to_string());
}
// all parameters must be known
@ -89,7 +87,7 @@ validate(const CommandHandler::CommandInfoMap& cmap,
if (std::none_of(cmd_info.args.cbegin(), cmd_info.args.cend(),
[&](auto&& arg) { return cmdargname == arg.first; }))
return Err(Error::Code::Command,
"unknown parameter '%s 'in command '%s'",
"unknown parameter '{} 'in command '{}'",
cmdargname.name.c_str(), cmd.to_string().c_str());
}
@ -103,7 +101,7 @@ CommandHandler::invoke(const Command& cmd, bool do_validate) const
const auto cmit{cmap_.find(cmd.name())};
if (cmit == cmap_.cend())
return Err(Error::Code::Command,
"unknown command '%s'", cmd.to_string().c_str());
"unknown command '{}'", cmd.to_string().c_str());
const auto& cmd_info{cmit->second};
if (do_validate) {
@ -142,8 +140,6 @@ test_args()
assert_equal(cmd->string_arg(":bar").value_or("abc"), "abc"); // wrong type
g_assert_false(cmd->boolean_arg(":boo"));
g_assert_true(cmd->boolean_arg(":bah"));
}
@ -164,7 +160,7 @@ call(const CommandInfoMap& cmap, const std::string& str) try {
return !!res;
} catch (const Error& err) {
g_warning("%s", err.what());
mu_warning("{}", err.what());
return false;
}

View File

@ -1,15 +1,21 @@
/*
* Created on 2020-11-08 by Dirk-Jan C. Binnema <dbinnema@logitech.com>
*
* Copyright (c) 2020 Logitech, Inc. All Rights Reserved
* This program is a trade secret of LOGITECH, and it is not to be reproduced,
* published, disclosed to others, copied, adapted, distributed or displayed
* without the prior authorization of LOGITECH.
*
* Licensee agrees to attach or embed this notice on all copies of the program,
* including partial copies or modified versions thereof.
*
*/
** Copyright (C) 2023 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
** Free Software Foundation; either version 3, or (at your option) any
** later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software Foundation,
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**
*/
#ifndef MU_OPTION__
#define MU_OPTION__
@ -28,7 +34,7 @@ Some(T&& t)
{
return std::move(t);
}
constexpr auto Nothing = tl::nullopt; // 'None' is take already
constexpr auto Nothing = tl::nullopt; // 'None' is already taken.
/**
* Maybe create a string from a const char pointer.

View File

@ -103,13 +103,13 @@ Err(Error::Code code, GError **err, fmt::format_string<T...> frm, T&&... args)
*
* @param R some result
*/
#define assert_valid_result(R) do { \
if(!R) { \
g_printerr("%s:%u: error-result: %s\n", \
__FILE__, __LINE__, \
(R).error().what()); \
g_assert_true(!!R); \
} \
#define assert_valid_result(R) do { \
if(!R) { \
mu_printerrln("{}:{}: error-result: {}", \
__FILE__, __LINE__, \
(R).error().what()); \
g_assert_true(!!R); \
} \
} while(0)
}// namespace Mu

View File

@ -36,9 +36,9 @@ parsing_error(size_t pos, const char* frm, ...)
va_end(args);
if (pos == 0)
return Mu::Error(Error::Code::Parsing, "%s", msg.c_str());
return Mu::Error(Error::Code::Parsing, "{}", msg);
else
return Mu::Error(Error::Code::Parsing, "%zu: %s", pos, msg.c_str());
return Mu::Error(Error::Code::Parsing, "{}: {}", pos, msg);
}
static size_t
skip_whitespace(const std::string& s, size_t pos)
@ -58,7 +58,7 @@ static Result<Sexp>
parse_list(const std::string& expr, size_t& pos)
{
if (expr[pos] != '(') // sanity check.
return Err(parsing_error(pos, "expected: '(' but got '%c", expr[pos]));
return Err(parsing_error(pos, "expected: '(' but got '{}", expr[pos]));
Sexp lst{};
@ -71,7 +71,7 @@ parse_list(const std::string& expr, size_t& pos)
}
if (expr[pos] != ')')
return Err(parsing_error(pos, "expected: ')' but got '%c'", expr[pos]));
return Err(parsing_error(pos, "expected: ')' but got '{}'", expr[pos]));
++pos;
return Ok(std::move(lst));
}
@ -80,7 +80,7 @@ static Result<Sexp>
parse_string(const std::string& expr, size_t& pos)
{
if (expr[pos] != '"') // sanity check.
return Err(parsing_error(pos, "expected: '\"'' but got '%c", expr[pos]));
return Err(parsing_error(pos, "expected: '\"'' but got '{}", expr[pos]));
bool escape{};
std::string str;
@ -101,7 +101,7 @@ parse_string(const std::string& expr, size_t& pos)
}
if (escape || expr[pos] != '"')
return Err(parsing_error(pos, "unterminated string '%s'", str.c_str()));
return Err(parsing_error(pos, "unterminated string '{}'", str));
++pos;
return Ok(Sexp{std::move(str)});
@ -112,7 +112,7 @@ static Result<Sexp>
parse_integer(const std::string& expr, size_t& pos)
{
if (!isdigit(expr[pos]) && expr[pos] != '-') // sanity check.
return Err(parsing_error(pos, "expected: <digit> but got '%c", expr[pos]));
return Err(parsing_error(pos, "expected: <digit> but got '{}", expr[pos]));
std::string num; // negative number?
if (expr[pos] == '-') {
@ -130,7 +130,7 @@ static Result<Sexp>
parse_symbol(const std::string& expr, size_t& pos)
{
if (!isalpha(expr[pos]) && expr[pos] != ':') // sanity check.
return Err(parsing_error(pos, "expected: <alpha>|: but got '%c", expr[pos]));
return Err(parsing_error(pos, "expected: <alpha>|: but got '{}", expr[pos]));
std::string symb(1, expr[pos]);
for (++pos; isalnum(expr[pos]) || expr[pos] == '-'; ++pos)
@ -145,7 +145,7 @@ parse(const std::string& expr, size_t& pos)
pos = skip_whitespace(expr, pos);
if (pos == expr.size())
return Err(parsing_error(pos, "expected: character '%c", expr[pos]));
return Err(parsing_error(pos, "expected: character '{}", expr[pos]));
const auto kar = expr[pos];
const auto sexp = std::invoke([&]() -> Result<Sexp> {
@ -158,7 +158,7 @@ parse(const std::string& expr, size_t& pos)
else if (isalpha(kar) || kar == ':')
return parse_symbol(expr, pos);
else
return Err(parsing_error(pos, "unexpected character '%c", kar));
return Err(parsing_error(pos, "unexpected character '{}", kar));
});
if (sexp)
@ -175,7 +175,7 @@ Sexp::parse(const std::string& expr)
if (!res)
return res;
else if (pos != expr.size())
return Err(parsing_error(pos, "trailing data starting with '%c'", expr[pos]));
return Err(parsing_error(pos, "trailing data starting with '{}'", expr[pos]));
else
return res;
}

View File

@ -133,16 +133,16 @@ Mu::TempDir::~TempDir()
return; /* nothing to do */
if (!autodelete_) {
g_debug("_not_ deleting %s", path_.c_str());
mu_debug("_not_ deleting {}", path_);
return;
}
/* ugly */
GError *err{};
const auto cmd{format("/bin/rm -rf '%s'", path_.c_str())};
const auto cmd{fmt::format("/bin/rm -rf '{}'", path_)};
if (!g_spawn_command_line_sync(cmd.c_str(), NULL, NULL, NULL, &err)) {
g_warning("error: %s\n", err ? err->message : "?");
mu_warning("error: {}", err ? err->message : "?");
g_clear_error(&err);
} else
g_debug("removed '%s'", path_.c_str());
mu_debug("removed '{}'", path_);
}

View File

@ -60,7 +60,7 @@ Mu::play (const std::string& path)
auto is_native = g_file_is_native(gf);
g_object_unref(gf);
if (!is_native)
return Err(Error::Code::File, "'%s' is not a native file", path.c_str());
return Err(Error::Code::File, "'{}' is not a native file", path);
const char *prog{g_getenv ("MU_PLAY_PROGRAM")};
if (!prog) {
@ -73,7 +73,7 @@ Mu::play (const std::string& path)
const auto program_path{program_in_path(prog)};
if (!program_path)
return Err(Error::Code::File, "cannot find '%s' in path", prog);
return Err(Error::Code::File, "cannot find '{}' in path", prog);
const gchar *argv[3]{};
argv[0] = program_path->c_str();
@ -83,9 +83,8 @@ Mu::play (const std::string& path)
GError *err{};
if (!g_spawn_async ({}, (gchar**)&argv, {}, G_SPAWN_SEARCH_PATH, maybe_setsid,
{}, {}, &err))
return Err(Error::Code::File, &err/*consumes*/, "failed to open '%s' with '%s'",
path. c_str(), program_path->c_str());
return Err(Error::Code::File, &err/*consumes*/,
"failed to open '{}' with '{}'", path, *program_path);
return Ok();
}
@ -117,8 +116,8 @@ Mu::determine_dtype (const std::string& path, bool use_lstat)
res = ::stat(path.c_str(), &statbuf);
if (res != 0) {
g_warning ("%sstat failed on %s: %s",
use_lstat ? "l" : "", path.c_str(), g_strerror(errno));
mu_warning ("{}stat failed on {}: {}",
use_lstat ? "l" : "", path, g_strerror(errno));
return DT_UNKNOWN;
}

View File

@ -347,8 +347,7 @@ Mu::time_to_string(const char *frm, time_t t, bool utc)
});
if (!dt) {
g_warning("time_t out of range: <%" G_GUINT64_FORMAT ">",
static_cast<guint64>(t));
mu_warning("time_t out of range: <{}>", t);
return {};
}
@ -356,7 +355,7 @@ Mu::time_to_string(const char *frm, time_t t, bool utc)
auto datestr{to_string_opt_gchar(g_date_time_format(dt, frm))};
g_date_time_unref(dt);
if (!datestr)
g_warning("failed to format time with format '%s'", frm);
mu_warning("failed to format time with format '{}'", frm);
return datestr.value_or("");
}
@ -692,7 +691,7 @@ __attribute__((format(printf, 2, 0)))
static bool
print_args (FILE *stream, const char *frm, va_list args)
{
gchar *str;
char *str;
gboolean rv;
str = g_strdup_vprintf (frm, args);

View File

@ -47,7 +47,12 @@
namespace Mu {
/*
* Logging functions connect libfmt with the Glib logging system
* Logging/printing/formatting functions connect libfmt with the Glib logging
* system. We wrap so perhaps at some point (C++23?) we can use std:: instead.
*/
/*
* Debug/error/warning logging
*/
template<typename...T>
@ -81,6 +86,35 @@ inline void mu_error(fmt::format_string<T...> frm, T&&... args) noexcept {
fmt::format(frm, std::forward<T>(args)...).c_str());
}
/*
* Printing
*/
template<typename...T>
inline void mu_print(fmt::format_string<T...> frm, T&&... args) noexcept {
fmt::print(frm, std::forward<T>(args)...);
}
template<typename...T>
inline void mu_println(fmt::format_string<T...> frm, T&&... args) noexcept {
fmt::println(frm, std::forward<T>(args)...);
}
template<typename...T>
inline void mu_printerr(fmt::format_string<T...> frm, T&&... args) noexcept {
fmt::print(stderr, frm, std::forward<T>(args)...);
}
template<typename...T>
inline void mu_printerrln(fmt::format_string<T...> frm, T&&... args) noexcept {
fmt::println(stderr, frm, std::forward<T>(args)...);
}
/*
* Fprmatting
*/
template<typename...T>
inline std::string mu_format(fmt::format_string<T...> frm, T&&... args) noexcept {
return fmt::format(frm, std::forward<T>(args)...);
}
using StringVec = std::vector<std::string>;
/**
@ -207,7 +241,6 @@ std::string date_to_time_t_string(int64_t t);
*/
std::string time_to_string(const char *frm, time_t t, bool utc = false) G_GNUC_CONST;
/**
* Hack to avoid locale crashes
*

View File

@ -55,6 +55,7 @@ extra_flags = [
'-Wstack-protector',
'-Wno-switch-enum',
'-Wno-keyword-macro',
'-Wno-volatile',
'-Wno-#warnings']
if get_option('buildtype') == 'debug'

View File

@ -137,7 +137,7 @@ static void
output_mutt_address_book(ItemType itype, OptContact contact, const Options& opts)
{
if (itype == ItemType::Header)
g_print ("Matching addresses in the mu database:\n");
mu_print ("Matching addresses in the mu database:\n");
if (!contact)
return;
@ -176,8 +176,8 @@ static void
output_bbdb(ItemType itype, OptContact contact, const Options& opts)
{
if (itype == ItemType::Header)
g_print (";; -*-coding: utf-8-emacs;-*-\n"
";;; file-version: 6\n");
mu_println (";; -*-coding: utf-8-emacs;-*-\n"
";;; file-version: 6");
if (!contact)
return;
@ -185,13 +185,9 @@ output_bbdb(ItemType itype, OptContact contact, const Options& opts)
const auto now{time_to_string("%Y-%m-%d", ::time(NULL))};
const auto timestamp{time_to_string("%Y-%m-%d", contact->message_date)};
g_print("[\"%s\" \"%s\" nil nil nil nil (\"%s\") "
"((creation-date . \"%s\") (time-stamp . \"%s\")) nil]\n",
names.first.c_str(),
names.second.c_str(),
contact->email.c_str(),
now.c_str(),
timestamp.c_str());
mu_println("[\"{}\" \"{}\" nil nil nil nil (\"{}\") "
"((creation-date . \"{}\") (time-stamp . \"{}\")) nil]",
names.first, names.second, contact->email, now, timestamp);
}
static void
@ -209,10 +205,10 @@ static void
output_json(ItemType itype, OptContact contact, const Options& opts)
{
if (itype == ItemType::Header)
g_print("[\n");
mu_println("[");
if (contact) {
g_print("%s", itype == ItemType::Header ? "" : ",\n");
g_print (" {\n");
mu_print("{}", itype == ItemType::Header ? "" : ",\n");
mu_println (" {{");
const std::string name = contact->name.empty() ? "null" : Mu::quote(contact->name);
print_encoded(
@ -230,11 +226,11 @@ output_json(ItemType itype, OptContact contact, const Options& opts)
time_to_string("%FT%TZ", contact->message_date, true/*utc*/).c_str(),
contact->personal ? "true" : "false",
contact->frequency);
g_print (" }");
mu_print (" }}");
}
if (itype == ItemType::Footer)
g_print("\n]\n");
mu_println("\n]");
}
static OutputFunc
@ -260,7 +256,7 @@ find_output_func(Format format)
case Format::Json:
return output_json;
default:
g_warning("unsupported format");
mu_warning("unsupported format");
return {};
}
#pragma GCC diagnostic pop

View File

@ -86,7 +86,7 @@ save_parts(const Message& message, const std::string& filename_rx,
if (saved_num == 0)
return Err(Error::Code::File,
"no %s extracted from this message",
"no {} extracted from this message",
opts.extract.save_attachments ? "attachments" : "parts");
else
return Ok();
@ -102,7 +102,7 @@ static void
show_part(const MessagePart& part, size_t index, bool color)
{
/* index */
g_print(" %zu ", index);
mu_print(" {} ", index);
/* filename */
color_maybe(MU_COLOR_GREEN);
@ -122,7 +122,7 @@ show_part(const MessagePart& part, size_t index, bool color)
/* size */
if (part.size() > 0) {
color_maybe(MU_COLOR_CYAN);
g_print(" (%zu bytes)", part.size());
mu_print(" ({} bytes)", part.size());
}
color_maybe(MU_COLOR_DEFAULT);
@ -133,7 +133,7 @@ static Mu::Result<void>
show_parts(const Message& message, const Options& opts)
{
size_t index{};
g_print("MIME-parts in this message:\n");
mu_println("MIME-parts in this message:");
for (auto&& part: message.parts())
show_part(part, ++index, !opts.nocolor);
@ -164,8 +164,8 @@ Mu::mu_cmd_extract(const Options& opts)
if (!check_dir(opts.extract.targetdir, false/*!readable*/, true/*writeable*/))
return Err(Error::Code::File,
"target '%s' is not a writable directory",
opts.extract.targetdir.c_str());
"target '{}' is not a writable directory",
opts.extract.targetdir);
return save_parts(*message, opts.extract.filename_rx, opts);
}

View File

@ -116,14 +116,14 @@ resolve_bookmark(const Options& opts)
auto bm = mu_bookmarks_new(bmfile.c_str());
if (!bm)
return Err(Error::Code::File,
"failed to open bookmarks file '%s'", bmfile.c_str());
"failed to open bookmarks file '{}'", bmfile);
const auto bookmark{opts.find.bookmark};
const auto val = mu_bookmarks_lookup(bm, bookmark.c_str());
if (!val) {
mu_bookmarks_destroy(bm);
return Err(Error::Code::NoMatches,
"bookmark '%s' not found", bookmark.c_str());
"bookmark '{}' not found", bookmark);
}
mu_bookmarks_destroy(bm);
@ -263,9 +263,9 @@ print_summary(const Message& msg, const Options& opts)
const auto summ{summarize(body->c_str(), opts.find.summary_len.value_or(0))};
g_print("Summary: ");
mu_print("Summary: ");
fputs_encoded(summ, stdout);
g_print("\n");
mu_println("");
}
static void
@ -361,21 +361,19 @@ static bool
output_json(const Option<Message>& msg, const OutputInfo& info, const Options& opts, GError** err)
{
if (info.header) {
g_print("[\n");
mu_println("[");
return true;
}
if (info.footer) {
g_print("]\n");
mu_println("]");
return true;
}
if (!msg)
return true;
g_print("%s%s\n",
msg->sexp().to_json_string().c_str(),
info.last ? "" : ",");
mu_println("{}{}", msg->sexp().to_json_string(), info.last ? "" : ",");
return true;
}
@ -387,34 +385,34 @@ print_attr_xml(const std::string& elm, const std::string& str)
return; /* empty: don't include */
auto&& esc{to_string_opt_gchar(g_markup_escape_text(str.c_str(), -1))};
g_print("\t\t<%s>%s</%s>\n", elm.c_str(), esc.value_or("").c_str(), elm.c_str());
mu_println("\t\t<{}>{}</{}>", elm, esc.value_or(""), elm);
}
static bool
output_xml(const Option<Message>& msg, const OutputInfo& info, const Options& opts, GError** err)
{
if (info.header) {
g_print("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
g_print("<messages>\n");
mu_println("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
mu_println("<messages>");
return true;
}
if (info.footer) {
g_print("</messages>\n");
mu_println("</messages>");
return true;
}
g_print("\t<message>\n");
mu_println("\t<message>");
print_attr_xml("from", to_string(msg->from()));
print_attr_xml("to", to_string(msg->to()));
print_attr_xml("cc", to_string(msg->cc()));
print_attr_xml("subject", msg->subject());
g_print("\t\t<date>%u</date>\n", (unsigned)msg->date());
g_print("\t\t<size>%u</size>\n", (unsigned)msg->size());
mu_println("\t\t<date>{}</date>", (unsigned)msg->date());
mu_println("\t\t<size>{}</size>", (unsigned)msg->size());
print_attr_xml("msgid", msg->message_id());
print_attr_xml("path", msg->path());
print_attr_xml("maildir", msg->maildir());
g_print("\t</message>\n");
mu_println("\t</message>");
return true;
}

View File

@ -55,7 +55,7 @@ install_sig_handler(void)
for (i = 0; i != G_N_ELEMENTS(sigs); ++i)
if (sigaction(sigs[i], &action, NULL) != 0)
g_critical("set sigaction for %d failed: %s",
mu_critical("set sigaction for {} failed: {}",
sigs[i], g_strerror(errno));
}
@ -79,7 +79,7 @@ Mu::mu_cmd_index(Store& store, const Options& opts)
{
const auto mdir{store.root_maildir()};
if (G_UNLIKELY(access(mdir.c_str(), R_OK) != 0))
return Err(Error::Code::File, "'%s' is not readable: %s",
return Err(Error::Code::File, "'{}' is not readable: {}",
mdir.c_str(), g_strerror(errno));
MaybeAnsi col{!opts.nocolor};

View File

@ -28,11 +28,10 @@ Mu::mu_cmd_remove(Mu::Store& store, const Options& opts)
for (auto&& file: opts.remove.files) {
const auto res = store.remove_message(file);
if (!res)
return Err(Error::Code::File, "failed to remove %s", file.c_str());
return Err(Error::Code::File, "failed to remove {}", file.c_str());
else
g_debug("removed message @ %s", file.c_str());
}
return Ok();
}

View File

@ -36,7 +36,7 @@ Mu::mu_cmd_script(const Options& opts)
if (script_it == scriptinfos.cend())
return Err(Error::Code::InvalidArgument,
"cannot find script '%s'", opts.script.name.c_str());
"cannot find script '{}'", opts.script.name);
std::vector<std::string> params{opts.script.params};
if (!opts.muhome.empty()) {

View File

@ -57,7 +57,7 @@ install_sig_handler(void)
for (i = 0; i != G_N_ELEMENTS(sigs); ++i)
if (sigaction(sigs[i], &action, NULL) != 0)
g_critical("set sigaction for %d failed: %s",
mu_critical("set sigaction for {} failed: {}",
sigs[i], g_strerror(errno));
}
@ -92,7 +92,7 @@ output_sexp_stdout(const Sexp& sexp, Server::OutputFlags flags)
const auto str{sexp.to_string(fopts)};
cookie(str.size() + 1);
if (G_UNLIKELY(::puts(str.c_str()) < 0)) {
g_critical("failed to write output '%s'", str.c_str());
mu_critical("failed to write output '{}'", str);
::raise(SIGTERM); /* terminate ourselves */
}
@ -118,12 +118,11 @@ Mu::mu_cmd_server(const Mu::Options& opts) try {
return Err(store.error());
Server server{*store, output_sexp_stdout};
g_message("created server with store @ %s; maildir @ %s; debug-mode %s;"
"readline: %s",
store->path().c_str(),
store->root_maildir().c_str(),
opts.debug ? "yes" : "no",
have_readline() ? "yes" : "no");
mu_message("created server with store @ {}; maildir @ {}; debug-mode {};"
"readline: {}",
store->path(), store->root_maildir(),
opts.debug ? "yes" : "no",
have_readline() ? "yes" : "no");
tty = ::isatty(::fileno(stdout));
const auto eval = std::string{opts.server.commands ? "(help :full t)" : opts.server.eval};
@ -153,18 +152,17 @@ Mu::mu_cmd_server(const Mu::Options& opts) try {
}
if (MuTerminate != 0)
g_message ("shutting down due to signal %d", MuTerminate.load());
mu_message ("shutting down due to signal {}", MuTerminate.load());
shutdown_readline();
return Ok();
} catch (const Error& er) {
/* note: user-level error, "OK" for mu */
} catch (const Error& er) { /* note: user-level error, "OK" for mu */
report_error(er);
g_warning("server caught exception: %s", er.what());
mu_warning("server caught exception: {}", er.what());
return Ok();
} catch (...) {
g_critical("server caught exception");
mu_critical("server caught exception");
return Err(Error::Code::Internal, "caught exception");
}

View File

@ -34,13 +34,11 @@ key_val(const Mu::MaybeAnsi& col, const std::string& key, T val)
{
using Color = Mu::MaybeAnsi::Color;
std::cout << col.fg(Color::BrightBlue) << std::left << std::setw(18) << key << col.reset()
<< ": ";
std::cout << col.fg(Color::Green) << val << col.reset() << "\n";
mu_println("{}{:<18}{}: {}{}{}",
col.fg(Color::BrightBlue), key, col.reset(),
col.fg(Color::Green), val, col.reset());
}
static void
print_signature(const Mu::MimeSignature& sig, const Options& opts)
{
@ -90,7 +88,7 @@ verify(const MimeMultipartSigned& sigpart, const Options& opts)
if (!sigs || sigs->empty()) {
if (!opts.quiet)
g_print("cannot find signatures in part\n");
mu_println("cannot find signatures in part");
return true;
}
@ -119,7 +117,7 @@ verify_message(const Message& message, const Options& opts, const std::string& n
{
if (none_of(message.flags() & Flags::Signed)) {
if (!opts.quiet)
g_print("%s: no signed parts found\n", name.c_str());
mu_println("{}: no signed parts found", name);
return false;
}
@ -155,7 +153,7 @@ Mu::mu_cmd_verify(const Options& opts)
return Err(message.error());
if (!opts.quiet && opts.verify.files.size() > 1)
g_print("verifying %s\n", file.c_str());
mu_println("verifying {}", file);
if (!verify_message(*message, opts, file))
all_ok = false;

View File

@ -93,11 +93,10 @@ body_or_summary(const Message& message, const Options& opts)
if (!body || body->empty()) {
if (any_of(message.flags() & Flags::Encrypted)) {
color_maybe(MU_COLOR_CYAN);
g_print("[No text body found; "
"message has encrypted parts]\n");
mu_println("[No text body found; message has encrypted parts]");
} else {
color_maybe(MU_COLOR_MAGENTA);
g_print("[No text body found]\n");
mu_println("[No text body found]");
}
color_maybe(MU_COLOR_DEFAULT);
return;
@ -109,7 +108,7 @@ body_or_summary(const Message& message, const Options& opts)
} else {
print_encoded("%s", body->c_str());
if (!g_str_has_suffix(body->c_str(), "\n"))
g_print("\n");
mu_println("");
}
}
@ -148,7 +147,7 @@ handle_msg(const Message& message, const Options& opts)
case Format::Sexp:
return view_msg_sexp(message, opts);
default:
g_critical("bug: should not be reached");
mu_critical("bug: should not be reached");
return Err(Error::Code::Internal, "error");
}
}
@ -166,7 +165,7 @@ Mu::mu_cmd_view(const Options& opts)
return res;
/* add a separator between two messages? */
if (opts.view.terminate)
g_print("%c", VIEW_TERMINATOR);
mu_print("{}", VIEW_TERMINATOR);
}
// no files? read from stding

View File

@ -47,13 +47,14 @@ using namespace Mu;
static Result<void>
cmd_fields(const Options& opts)
{
g_printerr("the 'mu fields' command has been superseded by 'mu info'; try:\n"
mu_printerrln("the 'mu fields' command has been superseded by 'mu info'; try:\n"
" mu info fields\n"
" mu info flags\n");
" mu info flags");
return Ok();
}
static Result<void>
cmd_find(const Options& opts)
{
@ -64,14 +65,15 @@ cmd_find(const Options& opts)
return mu_cmd_find(*store, opts);
}
static void
show_usage(void)
{
g_print("usage: mu command [options] [parameters]\n");
g_print("where command is one of index, find, cfind, view, mkdir, "
"extract, add, remove, script, verify or server\n");
g_print("see the mu, mu-<command> or mu-easy manpages for "
"more information\n");
mu_println("usage: mu command [options] [parameters]");
mu_println("where command is one of index, find, cfind, view, mkdir, "
"extract, add, remove, script, verify or server");
mu_println("see the mu, mu-<command> or mu-easy manpages for "
"more information");
}
@ -157,9 +159,9 @@ Mu::mu_cmd_execute(const Options& opts) try {
} catch (const Mu::Error& er) {
return Err(er);
} catch (const std::runtime_error& re) {
return Err(Error::Code::Internal, "runtime-error: %s", re.what());
return Err(Error::Code::Internal, "runtime-error: {}", re.what());
} catch (const std::exception& ex) {
return Err(Error::Code::Internal, "error: %s", ex.what());
return Err(Error::Code::Internal, "error: {}", ex.what());
} catch (...) {
return Err(Error::Code::Internal, "caught exception");
}

View File

@ -623,7 +623,7 @@ cmd_help(const CLI::App& app, Options& opts)
return show_manpage(opts, "mu-" + opts.help.command);
return Err(Error::Code::Command,
"no help available for '%s'", opts.help.command.c_str());
"no help available for '{}'", opts.help.command);
}
bool
@ -660,7 +660,7 @@ Options::make(int argc, char *argv[])
CLI::App app{"mu mail indexer/searcher", "mu"};
app.description(R"(mu mail indexer/searcher
Copyright (C) 2008-2022 Dirk-Jan C. Binnema
Copyright (C) 2008-2023 Dirk-Jan C. Binnema
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
@ -743,7 +743,7 @@ There is NO WARRANTY, to the extent permitted by law.
} catch (const CLI::CallForVersion&) {
std::cout << "version " << PACKAGE_VERSION << "\n";
} catch (const CLI::ParseError& pe) {
return Err(Error::Code::InvalidArgument, "%s", pe.what());
return Err(Error::Code::InvalidArgument, "{}", pe.what());
} catch (...) {
return Err(Error::Code::Internal, "error parsing arguments");
}

View File

@ -284,7 +284,6 @@ struct Options {
std::string runtime_path(RuntimePath path) const {
return Mu::runtime_path(path, muhome);
}
};
} // namepace Mu

View File

@ -56,7 +56,7 @@ make_database(const std::string& testdir)
MU_PROGRAM, testdir, MU_PROGRAM)};
if (g_test_verbose())
g_printerr("\n%s\n", cmdline.c_str());
mu_printerrln("\n{}", cmdline);
g_assert(g_spawn_command_line_sync(cmdline.c_str(), NULL, NULL, NULL, NULL));
auto xpath = mu_format("{}{}{}",
@ -106,7 +106,7 @@ run_and_count_matches(const std::string& xpath,
if (g_test_verbose())
g_print("'%s' => %zu\n", expr.c_str(), qres->size());
mu_println("'{}' => {}\n", expr, qres->size());
return qres->size();
}
@ -247,7 +247,7 @@ test_mu_query_accented_chars_01(void)
const auto msg{qres->begin().message()};
if (!msg) {
g_warning("error getting message");
mu_warning("error getting message");
g_assert_not_reached();
}
@ -269,7 +269,7 @@ test_mu_query_accented_chars_02(void)
for (i = 0; i != G_N_ELEMENTS(queries); ++i) {
auto count = run_and_count_matches(DB_PATH1, queries[i].query);
if (count != queries[i].count)
g_warning("query '%s'; expect %zu but got %zu",
mu_warning("query '{}'; expected {} but got {}",
queries[i].query, queries[i].count, count);
g_assert_cmpuint(run_and_count_matches(DB_PATH1, queries[i].query),
==,
@ -292,7 +292,7 @@ test_mu_query_accented_chars_fraiche(void)
for (i = 0; i != G_N_ELEMENTS(queries); ++i) {
if (g_test_verbose())
g_print("'%s'\n", queries[i].query);
mu_println("{}", queries[i].query);
g_assert_cmpuint(run_and_count_matches(DB_PATH2, queries[i].query),
==,
@ -439,7 +439,7 @@ test_mu_query_attach(void)
for (i = 0; i != G_N_ELEMENTS(queries); ++i) {
if (g_test_verbose())
g_print("query: %s\n", queries[i].query);
mu_println("query: {}", queries[i].query);
g_assert_cmpuint(run_and_count_matches(DB_PATH2, queries[i].query),
==,
queries[i].count);
@ -462,7 +462,7 @@ test_mu_query_msgid(void)
for (i = 0; i != G_N_ELEMENTS(queries); ++i) {
if (g_test_verbose())
g_print("query: %s\n", queries[i].query);
mu_println("query: {}", queries[i].query);
g_assert_cmpuint(run_and_count_matches(DB_PATH2, queries[i].query),
==,
queries[i].count);