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 ** 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 ** 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. ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
** **
*/ */
#include <config.h>
#include "mu-guile-message.hh" #include "mu-guile-message.hh"
#include <libguile.h>
#include "message/mu-message.hh" #include "message/mu-message.hh"
#include "utils/mu-utils.hh" #include "utils/mu-utils.hh"
#include <config.h>
#include <glib-object.h> #include <glib-object.h>
#include <memory> #include <memory>
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wredundant-decls" #pragma GCC diagnostic ignored "-Wredundant-decls"
#pragma GCC diagnostic ignored "-Wvolatile"
#include <libguile.h> #include <libguile.h>
#pragma GCC diagnostic pop #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 ** 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 ** 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. ** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
** **
*/ */
#include <config.h>
#include "mu-guile.hh" #include "mu-guile.hh"
#include <config.h>
#include <locale.h> #include <locale.h>
#include <glib-object.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-store.hh>
#include <mu-query.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)}; const auto path{runtime_path(RuntimePath::XapianDb, muhome)};
auto store = Store::make(path); auto store = Store::make(path);
if (!store) { if (!store) {
g_critical("error creating store @ %s: %s", path.c_str(), mu_critical("error creating store @ %s: %s", path,
store.error().what()); store.error().what());
throw store.error(); throw store.error();
} else } else
StoreSingleton.emplace(std::move(store.value())); StoreSingleton.emplace(std::move(store.value()));
g_debug("mu-guile: opened store @ %s (n=%zu); maildir: %s", mu_debug("mu-guile: opened store @ {} (n={}); maildir: {}",
StoreSingleton->path().c_str(), StoreSingleton->path(),
StoreSingleton->size(), StoreSingleton->size(),
StoreSingleton->root_maildir().c_str()); StoreSingleton->root_maildir());
return true; return true;
} catch (const Xapian::Error& xerr) { } 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; return false;
} catch (const std::runtime_error& re) { } catch (const std::runtime_error& re) {
g_critical("%s: error: %s", __func__, re.what()); mu_critical("{}: error: {}", __func__, re.what());
return false; return false;
} catch (const std::exception& e) { } catch (const std::exception& e) {
g_critical("%s: caught exception: %s", __func__, e.what()); mu_critical("{}: caught exception: {}", __func__, e.what());
return false; return false;
} catch (...) { } catch (...) {
g_critical("%s: caught exception", __func__); mu_critical("{}: caught exception", __func__);
return false; return false;
} }
@ -118,7 +113,7 @@ Mu::Store&
mu_guile_store() mu_guile_store()
{ {
if (!StoreSingleton) if (!StoreSingleton)
g_error("mu guile not initialized"); mu_error("mu guile not initialized");
return StoreSingleton.value(); return StoreSingleton.value();
} }

View File

@ -21,9 +21,14 @@
#define __MU_GUILE_H__ #define __MU_GUILE_H__
#include <glib.h> #include <glib.h>
#include <libguile.h>
#include <mu-query.hh> #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 * get the singleton Store instance
*/ */

View File

@ -67,7 +67,7 @@ struct IndexState {
return state_.load() != rhs; return state_.load() != rhs;
} }
void change_to(State new_state) { 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)); name((State)new_state));
state_.store(new_state); state_.store(new_state);
} }
@ -84,9 +84,9 @@ struct Indexer::Private {
return handler(path, statbuf, info); return handler(path, statbuf, info);
}}, }},
max_message_size_{store_.config().get<Mu::Config::Id::MaxMessageSize>()} { max_message_size_{store_.config().get<Mu::Config::Id::MaxMessageSize>()} {
g_message("created indexer for %s -> %s (batch-size: %zu)", mu_message("created indexer for {} -> {} (batch-size: {})",
store.root_maildir().c_str(), store.root_maildir(), store.path(),
store.path().c_str(), store.config().get<Mu::Config::Id::BatchSize>()); store.config().get<Mu::Config::Id::BatchSize>());
} }
~Private() { ~Private() {
@ -148,16 +148,16 @@ Indexer::Private::handler(const std::string& fullpath, struct stat* statbuf,
dirstamp_ = store_.dirstamp(fullpath); dirstamp_ = store_.dirstamp(fullpath);
if (conf_.lazy_check && dirstamp_ >= statbuf->st_ctime && if (conf_.lazy_check && dirstamp_ >= statbuf->st_ctime &&
htype == Scanner::HandleType::EnterNewCur) { htype == Scanner::HandleType::EnterNewCur) {
g_debug("skip %s (seems up-to-date: %s >= %s)", fullpath.c_str(), mu_debug("skip {} (seems up-to-date: {} >= {})", fullpath,
time_to_string("%FT%T", dirstamp_).c_str(), time_to_string("%FT%T", dirstamp_),
time_to_string("%FT%T", statbuf->st_ctime).c_str()); time_to_string("%FT%T", statbuf->st_ctime));
return false; return false;
} }
// don't index dirs with '.noindex' // don't index dirs with '.noindex'
auto noindex = ::access((fullpath + "/.noindex").c_str(), F_OK) == 0; auto noindex = ::access((fullpath + "/.noindex").c_str(), F_OK) == 0;
if (noindex) { 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. 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) { if (!conf_.ignore_noupdate) {
auto noupdate = ::access((fullpath + "/.noupdate").c_str(), F_OK) == 0; auto noupdate = ::access((fullpath + "/.noupdate").c_str(), F_OK) == 0;
if (noupdate) { if (noupdate) {
g_debug("skip %s (has .noupdate)", fullpath.c_str()); mu_debug("skip {} (has .noupdate)", fullpath);
return false; return false;
} }
} }
g_debug("checked %s", fullpath.c_str()); mu_debug("checked {}", fullpath);
return true; return true;
} }
case Scanner::HandleType::LeaveDir: { case Scanner::HandleType::LeaveDir: {
@ -183,17 +183,14 @@ Indexer::Private::handler(const std::string& fullpath, struct stat* statbuf,
++progress_.checked; ++progress_.checked;
if ((size_t)statbuf->st_size > max_message_size_) { if ((size_t)statbuf->st_size > max_message_size_) {
g_debug("skip %s (too big: %" G_GINT64_FORMAT " bytes)", fullpath.c_str(), mu_debug("skip {} (too big: {} bytes)", fullpath, statbuf->st_size);
(gint64)statbuf->st_size);
return false; return false;
} }
// if the message is not in the db yet, or not up-to-date, queue // if the message is not in the db yet, or not up-to-date, queue
// it for updating/inserting. // it for updating/inserting.
if (statbuf->st_ctime <= dirstamp_ && store_.contains_message(fullpath)) { if (statbuf->st_ctime <= dirstamp_ && store_.contains_message(fullpath))
// g_debug ("skip %s: already up-to-date");
return false; return false;
}
// push the remaining messages to our "todo" queue for // push the remaining messages to our "todo" queue for
// (re)parsing and adding/updating to the database. // (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_) { if (todos_.size() > workers_.size() && workers_.size() < max_workers_) {
workers_.emplace_back(std::thread([this] { item_worker(); })); 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)}; auto msg{Message::make_from_path(path)};
if (!msg) { if (!msg) {
g_warning("failed to create message from %s: %s", mu_warning("failed to create message from {}: {}", path, msg.error().what());
path.c_str(), msg.error().what());
return false; return false;
} }
auto res = store_.add_message(msg.value(), true /*use-transaction*/); auto res = store_.add_message(msg.value(), true /*use-transaction*/);
if (!res) { if (!res) {
g_warning("failed to add message @ %s: %s", mu_warning("failed to add message @ {}: {}", path, res.error().what());
path.c_str(), res.error().what());
return false; return false;
} }
@ -250,7 +245,7 @@ Indexer::Private::item_worker()
{ {
WorkItem item; WorkItem item;
g_debug("started worker"); mu_debug("started worker");
while (state_ == IndexState::Scanning) { while (state_ == IndexState::Scanning) {
if (!todos_.pop(item, 250ms)) if (!todos_.pop(item, 250ms))
@ -269,8 +264,7 @@ Indexer::Private::item_worker()
break; break;
} }
} catch (const Mu::Error& er) { } catch (const Mu::Error& er) {
g_warning("error adding message @ %s: %s", mu_warning("error adding message @ {}: {}", item.full_path, er.what());
item.full_path.c_str(), er.what());
} }
maybe_start_worker(); maybe_start_worker();
@ -281,15 +275,15 @@ Indexer::Private::item_worker()
bool bool
Indexer::Private::cleanup() Indexer::Private::cleanup()
{ {
g_debug("starting cleanup"); mu_debug("starting cleanup");
size_t n{}; size_t n{};
std::vector<Store::Id> orphans; // store messages without files. std::vector<Store::Id> orphans; // store messages without files.
store_.for_each_message_path([&](Store::Id id, const std::string& path) { store_.for_each_message_path([&](Store::Id id, const std::string& path) {
++n; ++n;
if (::access(path.c_str(), R_OK) != 0) { if (::access(path.c_str(), R_OK) != 0) {
g_debug("cannot read %s (id=%u); queueing for removal from store", mu_debug("cannot read {} (id={}); queuing for removal from store",
path.c_str(), id); path, id);
orphans.emplace_back(id); orphans.emplace_back(id);
} }
@ -297,9 +291,9 @@ Indexer::Private::cleanup()
}); });
if (orphans.empty()) if (orphans.empty())
g_debug("nothing to clean up"); mu_debug("nothing to clean up");
else { 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); store_.remove_messages(orphans);
progress_.removed += orphans.size(); progress_.removed += orphans.size();
} }
@ -313,13 +307,13 @@ Indexer::Private::scan_worker()
progress_.reset(); progress_.reset();
if (conf_.scan) { if (conf_.scan) {
g_debug("starting scanner"); mu_debug("starting scanner");
if (!scanner_.start()) { // blocks. if (!scanner_.start()) { // blocks.
g_warning("failed to start scanner"); mu_warning("failed to start scanner");
state_.change_to(IndexState::Idle); state_.change_to(IndexState::Idle);
return; 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... // now there may still be messages in the work queue...
@ -331,7 +325,7 @@ Indexer::Private::scan_worker()
std::lock_guard lock{w_lock_}; std::lock_guard lock{w_lock_};
return workers_.size(); 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); todos_.size(), workers_size);
while (!todos_.empty()) while (!todos_.empty())
std::this_thread::sleep_for(100ms); std::this_thread::sleep_for(100ms);
@ -343,11 +337,10 @@ Indexer::Private::scan_worker()
w.join(); w.join();
if (conf_.cleanup) { if (conf_.cleanup) {
g_debug("starting cleanup"); mu_debug("starting cleanup");
state_.change_to(IndexState::Cleaning); state_.change_to(IndexState::Cleaning);
cleanup(); cleanup();
g_debug("cleanup finished"); mu_debug("cleanup finished");
} }
completed_ = ::time({}); completed_ = ::time({});
@ -369,9 +362,9 @@ Indexer::Private::start(const Indexer::Config& conf)
} else } else
max_workers_ = conf.max_threads; max_workers_ = conf.max_threads;
g_debug("starting indexer with <= %zu worker thread(s)", max_workers_); mu_debug("starting indexer with <= {} worker thread(s)", max_workers_);
g_debug("indexing: %s; clean-up: %s", conf_.scan ? "yes" : "no", mu_debug("indexing: {}; clean-up: {}", conf_.scan ? "yes" : "no",
conf_.cleanup ? "yes" : "no"); conf_.cleanup ? "yes" : "no");
state_.change_to(IndexState::Scanning); state_.change_to(IndexState::Scanning);
/* kick off the first worker, which will spawn more if needed. */ /* 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 */ /* kick the disk-scanner thread */
scanner_worker_ = std::thread([this] { scan_worker(); }); scanner_worker_ = std::thread([this] { scan_worker(); });
g_debug("started indexer"); mu_debug("started indexer");
return true; return true;
} }
@ -413,7 +406,7 @@ Indexer::start(const Indexer::Config& conf)
{ {
const auto mdir{priv_->store_.root_maildir()}; const auto mdir{priv_->store_.root_maildir()};
if (G_UNLIKELY(access(mdir.c_str(), R_OK) != 0)) { 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; return false;
} }
@ -432,7 +425,7 @@ Indexer::stop()
if (!is_running()) if (!is_running())
return true; return true;
g_debug("stopping indexer"); mu_debug("stopping indexer");
return priv_->stop(); 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) if (is_dotdir(d_name) || std::strcmp(d_name, "tmp") == 0)
return true; // ignore. return true; // ignore.
if (do_ignore(d_name)) { 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 return true; // ignore
} }
const auto fullpath{join_paths(path, d_name)}; const auto fullpath{join_paths(path, d_name)};
struct stat statbuf {}; struct stat statbuf {};
if (::stat(fullpath.c_str(), &statbuf) != 0) { 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; 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) } else if (S_ISREG(statbuf.st_mode) && is_maildir)
return handler_(fullpath, &statbuf, Scanner::HandleType::File); 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; return true;
} }
@ -136,7 +136,7 @@ Scanner::Private::process_dir(const std::string& path, bool is_maildir)
const auto dir = opendir(path.c_str()); const auto dir = opendir(path.c_str());
if (G_UNLIKELY(!dir)) { 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; return false;
} }
@ -153,7 +153,7 @@ Scanner::Private::process_dir(const std::string& path, bool is_maildir)
} }
if (errno != 0) { 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; continue;
} }
@ -169,30 +169,29 @@ Scanner::Private::start()
{ {
const auto& path{root_dir_}; const auto& path{root_dir_};
if (G_UNLIKELY(path.length() > PATH_MAX)) { if (G_UNLIKELY(path.length() > PATH_MAX)) {
g_warning("path too long"); mu_warning("path too long");
return false; return false;
} }
const auto mode{F_OK | R_OK}; const auto mode{F_OK | R_OK};
if (G_UNLIKELY(access(path.c_str(), mode) != 0)) { 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; return false;
} }
struct stat statbuf { struct stat statbuf {};
};
if (G_UNLIKELY(stat(path.c_str(), &statbuf) != 0)) { 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; return false;
} }
if (G_UNLIKELY(!S_ISDIR(statbuf.st_mode))) { 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; return false;
} }
running_ = true; 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())}; auto basename{g_path_get_basename(root_dir_.c_str())};
const auto is_maildir = const auto is_maildir =
@ -202,8 +201,7 @@ Scanner::Private::start()
const auto start{std::chrono::steady_clock::now()}; const auto start{std::chrono::steady_clock::now()};
process_dir(root_dir_, is_maildir); process_dir(root_dir_, is_maildir);
const auto elapsed = std::chrono::steady_clock::now() - start; const auto elapsed = std::chrono::steady_clock::now() - start;
g_debug("finished scan of %s in %" G_GINT64_FORMAT " ms", root_dir_.c_str(), mu_debug("finished scan of {} in {} ms", root_dir_, to_ms(elapsed));
to_ms(elapsed));
running_ = false; running_ = false;
return true; return true;
@ -215,7 +213,7 @@ Scanner::Private::stop()
if (!running_) if (!running_)
return true; // nothing to do return true; // nothing to do
g_debug("stopping scan"); mu_debug("stopping scan");
running_ = false; running_ = false;
return true; 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)}; const auto ctype{contact_type_from_field_id(id)};
if (G_UNLIKELY(!ctype)) { 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)); static_cast<size_t>(id));
return {}; return {};
} }
@ -217,7 +217,7 @@ Document::contacts_value(Field::Id id) const noexcept
const auto pos = s.find(SepaChar2); const auto pos = s.find(SepaChar2);
if (G_UNLIKELY(pos == std::string::npos)) { if (G_UNLIKELY(pos == std::string::npos)) {
g_critical("invalid contact data '%s'", s.c_str()); mu_critical("invalid contact data '{}'", s);
break; break;
} }
@ -348,7 +348,7 @@ Document::remove(Field::Id field_id)
try { try {
xdoc_.remove_term(term); xdoc_.remove_term(term);
} catch(const Xapian::InvalidArgumentError& xe) { } 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 #ifdef BUILD_TESTS
if (shortcut != 0) { if (shortcut != 0) {
if (++no_dups[static_cast<size_t>(shortcut-'a')] > 1) { if (++no_dups[static_cast<size_t>(shortcut-'a')] > 1) {
g_critical("shortcut '%c' is duplicated", mu_critical("shortcut '{}' is duplicated", shortcut);
shortcut);
return false; return false;
} }
} }
@ -105,7 +104,7 @@ validate_field_flags()
++flagnum; ++flagnum;
if (flagnum > 1) { if (flagnum > 1) {
//g_warning("invalid field %*.s", STR_V(field.name)); //mu_warning("invalid field {}", field.name);
return false; 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); const auto pos = path.find(root);
if (pos != 0 || path[root.length()] != '/') if (pos != 0 || path[root.length()] != '/')
return Err(Error{Error::Code::InvalidArgument, return Err(Error{Error::Code::InvalidArgument,
"root '%s' is not a root for path '%s'", "root '{}' is not a root for path '{}'", root, path});
root.c_str(), path.c_str()});
auto mdir{path.substr(root.length())}; auto mdir{path.substr(root.length())};
auto slash{mdir.rfind('/')}; auto slash{mdir.rfind('/')};
if (G_UNLIKELY(slash == std::string::npos) || slash < 4) if (G_UNLIKELY(slash == std::string::npos) || slash < 4)
return Err(Error{Error::Code::InvalidArgument, return Err(Error{Error::Code::InvalidArgument,
"invalid path: %s", path.c_str()}); "invalid path: {}", path});
mdir.erase(slash); mdir.erase(slash);
auto subdir = mdir.data() + slash - 4; auto subdir = mdir.data() + slash - 4;
if (G_UNLIKELY(strncmp(subdir, "/cur", 4) != 0 && strncmp(subdir, "/new", 4))) if (G_UNLIKELY(strncmp(subdir, "/cur", 4) != 0 && strncmp(subdir, "/new", 4)))
return Err(Error::Code::InvalidArgument, return Err(Error::Code::InvalidArgument,
"cannot find '/new' or '/cur' - invalid path: %s", "cannot find '/new' or '/cur' - invalid path: {}", path);
path.c_str());
if (mdir.length() == 4) if (mdir.length() == 4)
return "/"; return "/";
@ -109,7 +107,7 @@ Mu::flags_from_path(const std::string& path)
if (!flags) { if (!flags) {
/* LCOV_EXCL_START*/ /* LCOV_EXCL_START*/
return Err(Error{Error::Code::InvalidArgument, return Err(Error{Error::Code::InvalidArgument,
"invalid flags ('%s')", parts.flags_suffix.c_str()}); "invalid flags ('{}')", parts.flags_suffix});
/* LCOV_EXCL_STOP*/ /* LCOV_EXCL_STOP*/
} }
@ -182,8 +180,8 @@ test_flags_from_path()
assert_valid_result(res); assert_valid_result(res);
/* LCOV_EXCL_START*/ /* LCOV_EXCL_START*/
if (g_test_verbose()) { if (g_test_verbose()) {
g_print("%s -> <%s>\n", tcase.first.c_str(), mu_println("{} -> <{}>", tcase.first,
to_string(res.value()).c_str()); to_string(res.value()));
g_assert_true(res.value() == tcase.second); g_assert_true(res.value() == tcase.second);
} }
/*LCOV_EXCL_STOP*/ /*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) && if (none_of(opts & Message::Options::AllowRelativePath) &&
!g_path_is_absolute(path.c_str())) !g_path_is_absolute(path.c_str()))
return Err(Error::Code::File, "path '%s' is not absolute", return Err(Error::Code::File, "path '{}' is not absolute", path);
path.c_str());
if (::access(path.c_str(), R_OK) != 0) if (::access(path.c_str(), R_OK) != 0)
return Err(Error::Code::File, "file @ '%s' is not readable", return Err(Error::Code::File, "file @ '{}' is not readable", path);
path.c_str());
struct stat statbuf{}; struct stat statbuf{};
if (::stat(path.c_str(), &statbuf) < 0) if (::stat(path.c_str(), &statbuf) < 0)
return Err(Error::Code::File, "cannot stat %s: %s", path.c_str(), return Err(Error::Code::File, "cannot stat {}: {}", path,
g_strerror(errno)); g_strerror(errno));
if (!S_ISREG(statbuf.st_mode)) 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)); return Ok(std::move(statbuf));
} }
@ -200,13 +198,13 @@ Message::set_maildir(const std::string& maildir)
maildir.at(0) != '/' || maildir.at(0) != '/' ||
(maildir.size() > 1 && maildir.at(maildir.length()-1) == '/')) (maildir.size() > 1 && maildir.at(maildir.length()-1) == '/'))
return Err(Error::Code::Message, 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)}; const auto path{document().string_value(Field::Id::Path)};
if (path == maildir || path.find(maildir) == std::string::npos) if (path == maildir || path.find(maildir) == std::string::npos)
return Err(Error::Code::Message, return Err(Error::Code::Message,
"'%s' is not a valid maildir for message @ %s", "'{}' is not a valid maildir for message @ {}",
maildir.c_str(), path.c_str()); maildir, path);
priv_->doc.remove(Field::Id::Maildir); priv_->doc.remove(Field::Id::Maildir);
priv_->doc.add(Field::Id::Maildir, 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)}; const auto path{document().string_value(Field::Id::Path)};
if (auto mime_msg{MimeMessage::make_from_file(path)}; !mime_msg) { if (auto mime_msg{MimeMessage::make_from_file(path)}; !mime_msg) {
g_warning("failed to load '%s': %s", mu_warning("failed to load '{}': {}",
path.c_str(), mime_msg.error().what()); path, mime_msg.error().what());
return false; return false;
} else { } else {
priv_->mime_msg = std::move(mime_msg.value()); 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> constexpr std::array<std::pair<std::string_view, Priority>, 10>
prio_alist = {{ prio_alist = {{
{"high", Priority::High}, {"high", Priority::High},
{"1", Priority::High}, {"1", Priority::High},
{"2", Priority::High}, {"2", Priority::High},
{"normal", Priority::Normal}, {"normal", Priority::Normal},
{"3", Priority::Normal}, {"3", Priority::Normal},
{"low", Priority::Low}, {"low", Priority::Low},
{"list", Priority::Low}, {"list", Priority::Low},
{"bulk", Priority::Low}, {"bulk", Priority::Low},
{"4", Priority::Low}, {"4", Priority::Low},
{"5", Priority::Low} {"5", Priority::Low}
}}; }};
const auto opt_str = mime_msg.header("Precedence") 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 proto{part.content_type_parameter("protocol").value_or("unknown")};
const auto ctx = MimeCryptoContext::make(proto); const auto ctx = MimeCryptoContext::make(proto);
if (!ctx) { if (!ctx) {
g_warning("failed to create context for protocol <%s>", mu_warning("failed to create context for protocol <{}>", proto);
proto.c_str());
return; return;
} }
auto res{part.decrypt(*ctx)}; auto res{part.decrypt(*ctx)};
if (!res) { if (!res) {
g_warning("failed to decrypt: %s", res.error().what()); mu_warning("failed to decrypt: {}", res.error().what());
return; 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 (info.body_txt) { /* attempt to get the body-language */
if (const auto lang{detect_language(info.body_txt.value())}; lang) { if (const auto lang{detect_language(info.body_txt.value())}; lang) {
info.language = lang->code; info.language = lang->code;
g_debug("detected language: %s", lang->code); mu_debug("detected language: {}", lang->code);
} else } 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")}; FILE *file{::fopen(path.c_str(), "r")};
if (!file) if (!file)
return Err(Error{Error::Code::File, "failed to open %s: %s", return Err(Error{Error::Code::File, "failed to open {}: {}",
path.c_str(), ::strerror(errno)}); path, ::strerror(errno)});
std::array<uint8_t, 4096> buf{}; std::array<uint8_t, 4096> buf{};
while (true) { while (true) {
@ -566,7 +563,7 @@ calculate_sha256(const std::string& path)
::fclose(file); ::fclose(file);
if (has_err) 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)); 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. // not a very good message-id, only for testing.
if (path.empty() || ::access(path.c_str(), R_OK) != 0) 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) 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 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 * however, there are some _extra_ values in the sexp-list that are not
* based on a field. So we add them here. * based on a field. So we add them here.
*/ */
static void static void
doc_add_list_post(Document& doc, const MimeMessage& mime_msg) doc_add_list_post(Document& doc, const MimeMessage& mime_msg)
{ {
@ -797,11 +795,10 @@ Message::cache_path(Option<size_t> index) const
if (index) { if (index) {
GError *err{}; 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) if (g_mkdir(tpath.c_str(), 0700) != 0)
return Err(Error::Code::File, &err, return Err(Error::Code::File, &err,
"failed to create cache dir '%s'; err=%d", "failed to create cache dir '{}'; err={}", tpath, errno);
tpath.c_str(), errno);
return Ok(std::move(tpath)); return Ok(std::move(tpath));
} else } else

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -43,7 +43,7 @@ using namespace Mu;
// <regex> -> [field:]/regex/ // <regex> -> [field:]/regex/
#define BUG(...) \ #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 * 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; WarningVec warns;
const auto tree{parser_.parse(expr, warns)}; const auto tree{parser_.parse(expr, warns)};
for (auto&& w : 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)); 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); sort_enquire(enq, sortfield_id, qflags);
@ -291,7 +291,7 @@ Query::parse(const std::string& expr, bool xapian) const
WarningVec warns; WarningVec warns;
const auto tree{priv_->parser_.parse(expr, warns)}; const auto tree{priv_->parser_.parse(expr, warns)};
for (auto&& w : warns) for (auto&& w : warns)
g_warning("query warning: %s", to_string(w).c_str()); mu_warning("query warning: {}", to_string(w));
if (xapian) if (xapian)
return xapian_query(tree).get_description(); 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 ** 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 ** under the terms of the GNU General Public License as published by the
@ -19,14 +19,6 @@
#include "config.h" #include "config.h"
#include "mu-script.hh" #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 "mu/mu-options.hh"
#include "utils/mu-utils.hh" #include "utils/mu-utils.hh"
#include "utils/mu-option.hh" #include "utils/mu-option.hh"
@ -34,6 +26,14 @@
#include <fstream> #include <fstream>
#include <iostream> #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; using namespace Mu;
static std::string static std::string
@ -58,7 +58,7 @@ get_info(std::string&& path, const std::string& prefix)
{ {
std::ifstream file{path}; std::ifstream file{path};
if (!file.is_open()) { if (!file.is_open()) {
g_warning ("failed to open %s", path.c_str()); mu_warning ("failed to open {}", path);
return Nothing; return Nothing;
} }
@ -93,7 +93,7 @@ script_infos_in_dir(const std::string& scriptdir, Mu::ScriptInfos& infos)
{ {
DIR *dir = opendir(scriptdir.c_str()); DIR *dir = opendir(scriptdir.c_str());
if (!dir) { if (!dir) {
g_debug("failed to open '%s': %s", scriptdir.c_str(), mu_debug("failed to open '{}': {}", scriptdir,
g_strerror(errno)); g_strerror(errno));
return; 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 ** 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 ** under the terms of the GNU General Public License as published by the
@ -337,23 +337,15 @@ Server::Private::make_command_map()
return cmap; 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 bool
Server::Private::invoke(const std::string& expr) noexcept 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_) if (!keep_going_)
return false; return false;
try { try {
@ -366,17 +358,20 @@ Server::Private::invoke(const std::string& expr) noexcept
throw res.error(); throw res.error();
} catch (const Mu::Error& me) { } 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; keep_going_ = true;
} catch (const Xapian::Error& xerr) { } catch (const Xapian::Error& xerr) {
output_sexp(make_error(Error::Code::Internal, "xapian error: %s: %s", output_sexp(make_error(Error::Code::Internal,
xerr.get_type(), xerr.get_description().c_str())); mu_format("xapian error: {}: {}",
xerr.get_type(), xerr.get_description())));
keep_going_ = false; keep_going_ = false;
} catch (const std::runtime_error& re) { } 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; keep_going_ = false;
} catch (...) { } 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; keep_going_ = false;
} }
@ -405,8 +400,7 @@ Server::Private::add_handler(const Command& cmd)
auto msg_res{store().find_message(docid)}; auto msg_res{store().find_message(docid)};
if (!msg_res) if (!msg_res)
throw Error(Error::Code::Store, throw Error(Error::Code::Store,
"failed to get message at %s (docid=%u): %s", "failed to get message at {} (docid={})", *path, docid);
path->c_str(), docid);
output_sexp(Sexp().put_props(":update", output_sexp(Sexp().put_props(":update",
build_message_sexp(msg_res.value(), docid, {}))); 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))}; const unsigned docid{static_cast<unsigned>(cmd.number_arg(":docid").value_or(0))};
auto msg{store().find_message(docid)}; auto msg{store().find_message(docid)};
if (!msg) 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, {})); 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") } else if (ctype != "new")
throw Error(Error::Code::InvalidArgument, "invalid compose type '%s'", throw Error(Error::Code::InvalidArgument, "invalid compose type '{}'", ctype);
ctype.c_str());
output_sexp(comp_lst); output_sexp(comp_lst);
} }
@ -510,10 +503,8 @@ Server::Private::contacts_handler(const Command& cmd)
parse_date_time(afterstr, true).value_or(0)}; parse_date_time(afterstr, true).value_or(0)};
const auto tstamp = g_ascii_strtoll(tstampstr.c_str(), NULL, 10); const auto tstamp = g_ascii_strtoll(tstampstr.c_str(), NULL, 10);
g_debug("find %s contacts last seen >= %s (tstamp: %zu)", mu_debug("find {} contacts last seen >= {} (tstamp: {})",
personal ? "personal" : "any", personal ? "personal" : "any", time_to_string("%c", after), tstamp);
time_to_string("%c", after).c_str(),
static_cast<size_t>(tstamp));
auto n{0}; auto n{0};
Sexp contacts; Sexp contacts;
@ -540,7 +531,7 @@ Server::Private::contacts_handler(const Command& cmd)
":tstamp", format("%" G_GINT64_FORMAT, g_get_monotonic_time())); ":tstamp", format("%" G_GINT64_FORMAT, g_get_monotonic_time()));
/* dump the contacts cache as a giant sexp */ /* 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); 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) docids_for_msgid(const Store& store, const std::string& msgid, size_t max = 100)
{ {
if (msgid.size() > MaxTermLength) { if (msgid.size() > MaxTermLength) {
throw Error(Error::Code::InvalidArgument, throw Error(Error::Code::InvalidArgument, "invalid message-id '{}'", msgid);
"invalid message-id '%s'", msgid.c_str());
} else if (msgid.empty()) } else if (msgid.empty())
return {}; return {};
@ -566,10 +556,10 @@ docids_for_msgid(const Store& store, const std::string& msgid, size_t max = 100)
g_free(expr); g_free(expr);
if (!res) if (!res)
throw Error(Error::Code::Store, &gerr, 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()) else if (res->empty())
throw Error(Error::Code::NotFound, 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{}; std::vector<Store::Id> docids{};
for (auto&& mi : *res) 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"); throw Error(Error::Code::Store, "could not get message from store");
if (auto path{msg->path()}; path.empty()) 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); docid);
else else
return path; return path;
@ -667,17 +657,17 @@ Server::Private::find_handler(const Command& cmd)
if (const auto arg = cmd.symbol_arg(":sortfield"); !arg) if (const auto arg = cmd.symbol_arg(":sortfield"); !arg)
return Field::Id::Date; return Field::Id::Date;
else if (arg->length() < 2) else if (arg->length() < 2)
throw Error{Error::Code::InvalidArgument, "invalid sort field '%s'", throw Error{Error::Code::InvalidArgument, "invalid sort field '{}'",
arg->c_str()}; *arg};
else if (const auto field{field_from_name(arg->substr(1))}; !field) else if (const auto field{field_from_name(arg->substr(1))}; !field)
throw Error{Error::Code::InvalidArgument, "invalid sort field '%s'", throw Error{Error::Code::InvalidArgument, "invalid sort field '{}'",
arg->c_str()}; *arg};
else else
return field->id; return field->id;
}); });
if (batch_size < 1) 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. auto qflags{QueryFlags::SkipUnreadable}; // don't show unreadables.
if (descending) if (descending)
@ -695,7 +685,7 @@ Server::Private::find_handler(const Command& cmd)
std::lock_guard l{store_.lock()}; std::lock_guard l{store_.lock()};
auto qres{store_.run_query(q, sort_field_id, qflags, maxnum)}; auto qres{store_.run_query(q, sort_field_id, qflags, maxnum)};
if (!qres) 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 /* before sending new results, send an 'erase' message, so the frontend
* knows it should erase the headers buffer. this will ensure that the * 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) if (!flags)
throw Error{Error::Code::InvalidArgument, throw Error{Error::Code::InvalidArgument,
"invalid flags '%s'", flagopt.value_or("").c_str()}; "invalid flags '{}'", flagopt.value_or("")};
else else
return flags.value(); return flags.value();
} }
@ -913,7 +903,7 @@ Server::Private::move_handler(const Command& cmd)
const auto docid{docids.at(0)}; const auto docid{docids.at(0)};
auto msg = store().find_message(docid) auto msg = store().find_message(docid)
.or_else([&]{throw Error{Error::Code::InvalidArgument, .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 was not specified, take the current one */
if (maildir.empty()) if (maildir.empty())
@ -982,12 +972,10 @@ Server::Private::remove_handler(const Command& cmd)
if (::unlink(path.c_str()) != 0 && errno != ENOENT) if (::unlink(path.c_str()) != 0 && errno != ENOENT)
throw Error(Error::Code::File, throw Error(Error::Code::File,
"could not delete %s: %s", "could not delete {}: {}", path, g_strerror(errno));
path.c_str(),
g_strerror(errno));
if (!store().remove_message(path)) 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. 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 path{cmd.string_arg(":path").value_or("")};
const auto docid = store().add_message(path); const auto docid = store().add_message(path);
if (!docid) if (!docid)
throw Error{Error::Code::Store, "failed to add path: %s", throw Error{Error::Code::Store, "failed to add path: {}: {}",
docid.error().what()}; path, docid.error().what()};
output_sexp(Sexp().put_props( output_sexp(Sexp().put_props(
":sent", Sexp::t_sym, ":sent", Sexp::t_sym,
":path", path, ":path", path,

View File

@ -71,18 +71,18 @@ struct Store::Private {
{} {}
~Private() try { ~Private() try {
g_debug("closing store @ %s", xapian_db_.path().c_str()); mu_debug("closing store @ {}", xapian_db_.path());
if (!xapian_db_.read_only()) { if (!xapian_db_.read_only()) {
transaction_maybe_commit(true /*force*/); transaction_maybe_commit(true /*force*/);
} }
} catch (...) { } 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. // If not started yet, start a transaction. Otherwise, just update the transaction size.
void transaction_inc() noexcept { void transaction_inc() noexcept {
if (transaction_size_ == 0) { if (transaction_size_ == 0) {
g_debug("starting transaction"); mu_debug("starting transaction");
xapian_db_.begin_transaction(); xapian_db_.begin_transaction();
} }
++transaction_size_; ++transaction_size_;
@ -102,16 +102,12 @@ struct Store::Private {
if (transaction_size_ == 0) if (transaction_size_ == 0)
return; // nothing more to do here. 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(); xapian_db_.commit_transaction();
transaction_size_ = 0; 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) { XapianDb make_db(const std::string& path, XapianDb::Flavor flavor) {
if (auto&& res{XapianDb::make(path, flavor)}; res) if (auto&& res{XapianDb::make(path, flavor)}; res)
return std::move(res.value()); 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 */ /* don't try to recover from version with an incompatible scheme */
if (s_version < 500) if (s_version < 500)
throw Mu::Error(Error::Code::CannotReinit, 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); s_version);
const auto old_root_maildir{root_maildir()}; 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. */ /* otherwise, the schema version should match. */
if (s_version != ExpectedSchemaVersion) if (s_version != ExpectedSchemaVersion)
throw Mu::Error(Error::Code::SchemaMismatch, throw Mu::Error(Error::Code::SchemaMismatch,
"expected schema-version %zu, but got %zu", "expected schema-version {}, but got {}",
ExpectedSchemaVersion, s_version); ExpectedSchemaVersion, s_version);
} }
@ -433,7 +429,7 @@ static Store::IdMessageVec
messages_with_msgid(const Store& store, const std::string& msgid, size_t max=100) messages_with_msgid(const Store& store, const std::string& msgid, size_t max=100)
{ {
if (msgid.size() > MaxTermLength) { if (msgid.size() > MaxTermLength) {
g_warning("invalid message-id '%s'", msgid.c_str()); mu_warning("invalid message-id '{}'", msgid.c_str());
return {}; return {};
} else if (msgid.empty()) } else if (msgid.empty())
return {}; 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)}; const auto res{store.run_query(expr, {}, QueryFlags::None, max)};
g_free(expr); g_free(expr);
if (!res) { 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 {}; return {};
} }
if (res->empty()) { 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 {}; return {};
} }
@ -483,7 +479,7 @@ Store::move_message(Store::Id id,
auto msg{priv_->find_message_unlocked(id)}; auto msg{priv_->find_message_unlocked(id)};
if (!msg) 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)}; auto res{priv_->move_message_unlocked(std::move(*msg), target_mdir, new_flags, opts)};
if (!res) if (!res)
@ -513,7 +509,7 @@ Store::move_message(Store::Id id,
if (dup_res) if (dup_res)
imvec.emplace_back(docid, std::move(*dup_res)); imvec.emplace_back(docid, std::move(*dup_res));
else 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)); 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); g_setenv("XAPIAN_FLUSH_THRESHOLD", "500000", 1);
/* create path if needed */ /* create path if needed */
if (g_mkdir_with_parents(db_path.c_str(), 0700) != 0) if (g_mkdir_with_parents(db_path.c_str(), 0700) != 0)
return Err(Error::Code::File, "failed to create database dir %s: %s", return Err(Error::Code::File, "failed to create database dir {}: {}",
db_path.c_str(), ::strerror(errno)); db_path, ::strerror(errno));
} }
switch (flavor) { switch (flavor) {
@ -125,12 +125,12 @@ XapianDb::make(const std::string& db_path, Flavor flavor) noexcept try {
} }
} catch (const Xapian::DatabaseLockError& xde) { } 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) { } 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) { } catch (const Mu::Error& me) {
return Err(me); return Err(me);
} catch (...) { } catch (...) {
return Err(Error::Code::Internal, 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 <xapian.h>
#include <utils/mu-result.hh> #include <utils/mu-result.hh>
#include <utils/mu-utils.hh>
namespace Mu { namespace Mu {
@ -42,13 +43,13 @@ xapian_try(Func&& func) noexcept
try { try {
func(); func();
} catch (const Xapian::Error& xerr) { } 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) { } 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) { } catch (const std::exception& e) {
g_critical("%s: caught std::exception: %s", __func__, e.what()); mu_critical("{}: caught std::exception: {}", __func__, e.what());
} catch (...) { } catch (...) {
g_critical("%s: caught exception", __func__); mu_critical("{}: caught exception", __func__);
} }
template <typename Func, typename Default = std::invoke_result<Func>> auto template <typename Func, typename Default = std::invoke_result<Func>> auto
@ -58,30 +59,29 @@ try {
} catch (const Xapian::DocNotFoundError& xerr) { } catch (const Xapian::DocNotFoundError& xerr) {
return static_cast<Default>(def); return static_cast<Default>(def);
} catch (const Xapian::Error& xerr) { } 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); return static_cast<Default>(def);
} catch (const std::runtime_error& re) { } 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); return static_cast<Default>(def);
} catch (const std::exception& e) { } 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); return static_cast<Default>(def);
} catch (...) { } catch (...) {
g_critical("%s: caught exception", __func__); mu_critical("{}: caught exception", __func__);
return static_cast<Default>(def); return static_cast<Default>(def);
} }
template <typename Func> auto template <typename Func> auto
xapian_try_result(Func&& func) noexcept -> std::decay_t<decltype(func())> xapian_try_result(Func&& func) noexcept -> std::decay_t<decltype(func())>
try { try {
return func(); return func();
} catch (const Xapian::Error& xerr) { } 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) { } 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) { } 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 (...) { } catch (...) {
return Err(Error::Code::Internal, "caught exception"); return Err(Error::Code::Internal, "caught exception");
} }

View File

@ -443,7 +443,7 @@ tear_down()
GError *err{}; GError *err{};
const auto cmd{format("/bin/rm -rf '%s' '%s'", BENCH_MAILDIRS, BENCH_STORE)}; 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)) { 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); g_clear_error(&err);
} }
} }

View File

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

View File

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

View File

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

View File

@ -1,15 +1,21 @@
/* /*
* Created on 2020-11-08 by Dirk-Jan C. Binnema <dbinnema@logitech.com> ** Copyright (C) 2023 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
* **
* Copyright (c) 2020 Logitech, Inc. All Rights Reserved ** This program is free software; you can redistribute it and/or modify it
* This program is a trade secret of LOGITECH, and it is not to be reproduced, ** under the terms of the GNU General Public License as published by the
* published, disclosed to others, copied, adapted, distributed or displayed ** Free Software Foundation; either version 3, or (at your option) any
* without the prior authorization of LOGITECH. ** later version.
* **
* Licensee agrees to attach or embed this notice on all copies of the program, ** This program is distributed in the hope that it will be useful,
* including partial copies or modified versions thereof. ** 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__ #ifndef MU_OPTION__
#define MU_OPTION__ #define MU_OPTION__
@ -28,7 +34,7 @@ Some(T&& t)
{ {
return std::move(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. * 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 * @param R some result
*/ */
#define assert_valid_result(R) do { \ #define assert_valid_result(R) do { \
if(!R) { \ if(!R) { \
g_printerr("%s:%u: error-result: %s\n", \ mu_printerrln("{}:{}: error-result: {}", \
__FILE__, __LINE__, \ __FILE__, __LINE__, \
(R).error().what()); \ (R).error().what()); \
g_assert_true(!!R); \ g_assert_true(!!R); \
} \ } \
} while(0) } while(0)
}// namespace Mu }// namespace Mu

View File

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

View File

@ -133,16 +133,16 @@ Mu::TempDir::~TempDir()
return; /* nothing to do */ return; /* nothing to do */
if (!autodelete_) { if (!autodelete_) {
g_debug("_not_ deleting %s", path_.c_str()); mu_debug("_not_ deleting {}", path_);
return; return;
} }
/* ugly */ /* ugly */
GError *err{}; 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)) { 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); g_clear_error(&err);
} else } 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); auto is_native = g_file_is_native(gf);
g_object_unref(gf); g_object_unref(gf);
if (!is_native) 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")}; const char *prog{g_getenv ("MU_PLAY_PROGRAM")};
if (!prog) { if (!prog) {
@ -73,7 +73,7 @@ Mu::play (const std::string& path)
const auto program_path{program_in_path(prog)}; const auto program_path{program_in_path(prog)};
if (!program_path) 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]{}; const gchar *argv[3]{};
argv[0] = program_path->c_str(); argv[0] = program_path->c_str();
@ -83,9 +83,8 @@ Mu::play (const std::string& path)
GError *err{}; GError *err{};
if (!g_spawn_async ({}, (gchar**)&argv, {}, G_SPAWN_SEARCH_PATH, maybe_setsid, if (!g_spawn_async ({}, (gchar**)&argv, {}, G_SPAWN_SEARCH_PATH, maybe_setsid,
{}, {}, &err)) {}, {}, &err))
return Err(Error::Code::File, &err/*consumes*/, "failed to open '%s' with '%s'", return Err(Error::Code::File, &err/*consumes*/,
path. c_str(), program_path->c_str()); "failed to open '{}' with '{}'", path, *program_path);
return Ok(); return Ok();
} }
@ -117,8 +116,8 @@ Mu::determine_dtype (const std::string& path, bool use_lstat)
res = ::stat(path.c_str(), &statbuf); res = ::stat(path.c_str(), &statbuf);
if (res != 0) { if (res != 0) {
g_warning ("%sstat failed on %s: %s", mu_warning ("{}stat failed on {}: {}",
use_lstat ? "l" : "", path.c_str(), g_strerror(errno)); use_lstat ? "l" : "", path, g_strerror(errno));
return DT_UNKNOWN; return DT_UNKNOWN;
} }

View File

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

View File

@ -47,7 +47,12 @@
namespace Mu { 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> 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()); 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>; 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; std::string time_to_string(const char *frm, time_t t, bool utc = false) G_GNUC_CONST;
/** /**
* Hack to avoid locale crashes * Hack to avoid locale crashes
* *

View File

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

View File

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

View File

@ -86,7 +86,7 @@ save_parts(const Message& message, const std::string& filename_rx,
if (saved_num == 0) if (saved_num == 0)
return Err(Error::Code::File, return Err(Error::Code::File,
"no %s extracted from this message", "no {} extracted from this message",
opts.extract.save_attachments ? "attachments" : "parts"); opts.extract.save_attachments ? "attachments" : "parts");
else else
return Ok(); return Ok();
@ -102,7 +102,7 @@ static void
show_part(const MessagePart& part, size_t index, bool color) show_part(const MessagePart& part, size_t index, bool color)
{ {
/* index */ /* index */
g_print(" %zu ", index); mu_print(" {} ", index);
/* filename */ /* filename */
color_maybe(MU_COLOR_GREEN); color_maybe(MU_COLOR_GREEN);
@ -122,7 +122,7 @@ show_part(const MessagePart& part, size_t index, bool color)
/* size */ /* size */
if (part.size() > 0) { if (part.size() > 0) {
color_maybe(MU_COLOR_CYAN); color_maybe(MU_COLOR_CYAN);
g_print(" (%zu bytes)", part.size()); mu_print(" ({} bytes)", part.size());
} }
color_maybe(MU_COLOR_DEFAULT); color_maybe(MU_COLOR_DEFAULT);
@ -133,7 +133,7 @@ static Mu::Result<void>
show_parts(const Message& message, const Options& opts) show_parts(const Message& message, const Options& opts)
{ {
size_t index{}; size_t index{};
g_print("MIME-parts in this message:\n"); mu_println("MIME-parts in this message:");
for (auto&& part: message.parts()) for (auto&& part: message.parts())
show_part(part, ++index, !opts.nocolor); 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*/)) if (!check_dir(opts.extract.targetdir, false/*!readable*/, true/*writeable*/))
return Err(Error::Code::File, return Err(Error::Code::File,
"target '%s' is not a writable directory", "target '{}' is not a writable directory",
opts.extract.targetdir.c_str()); opts.extract.targetdir);
return save_parts(*message, opts.extract.filename_rx, opts); 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()); auto bm = mu_bookmarks_new(bmfile.c_str());
if (!bm) if (!bm)
return Err(Error::Code::File, 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 bookmark{opts.find.bookmark};
const auto val = mu_bookmarks_lookup(bm, bookmark.c_str()); const auto val = mu_bookmarks_lookup(bm, bookmark.c_str());
if (!val) { if (!val) {
mu_bookmarks_destroy(bm); mu_bookmarks_destroy(bm);
return Err(Error::Code::NoMatches, return Err(Error::Code::NoMatches,
"bookmark '%s' not found", bookmark.c_str()); "bookmark '{}' not found", bookmark);
} }
mu_bookmarks_destroy(bm); 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))}; const auto summ{summarize(body->c_str(), opts.find.summary_len.value_or(0))};
g_print("Summary: "); mu_print("Summary: ");
fputs_encoded(summ, stdout); fputs_encoded(summ, stdout);
g_print("\n"); mu_println("");
} }
static void static void
@ -361,21 +361,19 @@ static bool
output_json(const Option<Message>& msg, const OutputInfo& info, const Options& opts, GError** err) output_json(const Option<Message>& msg, const OutputInfo& info, const Options& opts, GError** err)
{ {
if (info.header) { if (info.header) {
g_print("[\n"); mu_println("[");
return true; return true;
} }
if (info.footer) { if (info.footer) {
g_print("]\n"); mu_println("]");
return true; return true;
} }
if (!msg) if (!msg)
return true; return true;
g_print("%s%s\n", mu_println("{}{}", msg->sexp().to_json_string(), info.last ? "" : ",");
msg->sexp().to_json_string().c_str(),
info.last ? "" : ",");
return true; return true;
} }
@ -387,34 +385,34 @@ print_attr_xml(const std::string& elm, const std::string& str)
return; /* empty: don't include */ return; /* empty: don't include */
auto&& esc{to_string_opt_gchar(g_markup_escape_text(str.c_str(), -1))}; 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 static bool
output_xml(const Option<Message>& msg, const OutputInfo& info, const Options& opts, GError** err) output_xml(const Option<Message>& msg, const OutputInfo& info, const Options& opts, GError** err)
{ {
if (info.header) { if (info.header) {
g_print("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); mu_println("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
g_print("<messages>\n"); mu_println("<messages>");
return true; return true;
} }
if (info.footer) { if (info.footer) {
g_print("</messages>\n"); mu_println("</messages>");
return true; return true;
} }
g_print("\t<message>\n"); mu_println("\t<message>");
print_attr_xml("from", to_string(msg->from())); print_attr_xml("from", to_string(msg->from()));
print_attr_xml("to", to_string(msg->to())); print_attr_xml("to", to_string(msg->to()));
print_attr_xml("cc", to_string(msg->cc())); print_attr_xml("cc", to_string(msg->cc()));
print_attr_xml("subject", msg->subject()); print_attr_xml("subject", msg->subject());
g_print("\t\t<date>%u</date>\n", (unsigned)msg->date()); mu_println("\t\t<date>{}</date>", (unsigned)msg->date());
g_print("\t\t<size>%u</size>\n", (unsigned)msg->size()); mu_println("\t\t<size>{}</size>", (unsigned)msg->size());
print_attr_xml("msgid", msg->message_id()); print_attr_xml("msgid", msg->message_id());
print_attr_xml("path", msg->path()); print_attr_xml("path", msg->path());
print_attr_xml("maildir", msg->maildir()); print_attr_xml("maildir", msg->maildir());
g_print("\t</message>\n"); mu_println("\t</message>");
return true; return true;
} }

View File

@ -55,7 +55,7 @@ install_sig_handler(void)
for (i = 0; i != G_N_ELEMENTS(sigs); ++i) for (i = 0; i != G_N_ELEMENTS(sigs); ++i)
if (sigaction(sigs[i], &action, NULL) != 0) 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)); sigs[i], g_strerror(errno));
} }
@ -79,7 +79,7 @@ Mu::mu_cmd_index(Store& store, const Options& opts)
{ {
const auto mdir{store.root_maildir()}; const auto mdir{store.root_maildir()};
if (G_UNLIKELY(access(mdir.c_str(), R_OK) != 0)) 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)); mdir.c_str(), g_strerror(errno));
MaybeAnsi col{!opts.nocolor}; 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) { for (auto&& file: opts.remove.files) {
const auto res = store.remove_message(file); const auto res = store.remove_message(file);
if (!res) 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 else
g_debug("removed message @ %s", file.c_str()); g_debug("removed message @ %s", file.c_str());
} }
return Ok(); return Ok();
} }

View File

@ -36,7 +36,7 @@ Mu::mu_cmd_script(const Options& opts)
if (script_it == scriptinfos.cend()) if (script_it == scriptinfos.cend())
return Err(Error::Code::InvalidArgument, 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}; std::vector<std::string> params{opts.script.params};
if (!opts.muhome.empty()) { if (!opts.muhome.empty()) {

View File

@ -57,7 +57,7 @@ install_sig_handler(void)
for (i = 0; i != G_N_ELEMENTS(sigs); ++i) for (i = 0; i != G_N_ELEMENTS(sigs); ++i)
if (sigaction(sigs[i], &action, NULL) != 0) 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)); 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)}; const auto str{sexp.to_string(fopts)};
cookie(str.size() + 1); cookie(str.size() + 1);
if (G_UNLIKELY(::puts(str.c_str()) < 0)) { 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 */ ::raise(SIGTERM); /* terminate ourselves */
} }
@ -118,12 +118,11 @@ Mu::mu_cmd_server(const Mu::Options& opts) try {
return Err(store.error()); return Err(store.error());
Server server{*store, output_sexp_stdout}; Server server{*store, output_sexp_stdout};
g_message("created server with store @ %s; maildir @ %s; debug-mode %s;" mu_message("created server with store @ {}; maildir @ {}; debug-mode {};"
"readline: %s", "readline: {}",
store->path().c_str(), store->path(), store->root_maildir(),
store->root_maildir().c_str(), opts.debug ? "yes" : "no",
opts.debug ? "yes" : "no", have_readline() ? "yes" : "no");
have_readline() ? "yes" : "no");
tty = ::isatty(::fileno(stdout)); tty = ::isatty(::fileno(stdout));
const auto eval = std::string{opts.server.commands ? "(help :full t)" : opts.server.eval}; 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) if (MuTerminate != 0)
g_message ("shutting down due to signal %d", MuTerminate.load()); mu_message ("shutting down due to signal {}", MuTerminate.load());
shutdown_readline(); shutdown_readline();
return Ok(); return Ok();
} catch (const Error& er) { } catch (const Error& er) { /* note: user-level error, "OK" for mu */
/* note: user-level error, "OK" for mu */
report_error(er); report_error(er);
g_warning("server caught exception: %s", er.what()); mu_warning("server caught exception: {}", er.what());
return Ok(); return Ok();
} catch (...) { } catch (...) {
g_critical("server caught exception"); mu_critical("server caught exception");
return Err(Error::Code::Internal, "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; using Color = Mu::MaybeAnsi::Color;
std::cout << col.fg(Color::BrightBlue) << std::left << std::setw(18) << key << col.reset() mu_println("{}{:<18}{}: {}{}{}",
<< ": "; col.fg(Color::BrightBlue), key, col.reset(),
col.fg(Color::Green), val, col.reset());
std::cout << col.fg(Color::Green) << val << col.reset() << "\n";
} }
static void static void
print_signature(const Mu::MimeSignature& sig, const Options& opts) 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 (!sigs || sigs->empty()) {
if (!opts.quiet) if (!opts.quiet)
g_print("cannot find signatures in part\n"); mu_println("cannot find signatures in part");
return true; 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 (none_of(message.flags() & Flags::Signed)) {
if (!opts.quiet) if (!opts.quiet)
g_print("%s: no signed parts found\n", name.c_str()); mu_println("{}: no signed parts found", name);
return false; return false;
} }
@ -155,7 +153,7 @@ Mu::mu_cmd_verify(const Options& opts)
return Err(message.error()); return Err(message.error());
if (!opts.quiet && opts.verify.files.size() > 1) 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)) if (!verify_message(*message, opts, file))
all_ok = false; all_ok = false;

View File

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

View File

@ -47,13 +47,14 @@ using namespace Mu;
static Result<void> static Result<void>
cmd_fields(const Options& opts) 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 fields\n"
" mu info flags\n"); " mu info flags");
return Ok(); return Ok();
} }
static Result<void> static Result<void>
cmd_find(const Options& opts) cmd_find(const Options& opts)
{ {
@ -64,14 +65,15 @@ cmd_find(const Options& opts)
return mu_cmd_find(*store, opts); return mu_cmd_find(*store, opts);
} }
static void static void
show_usage(void) show_usage(void)
{ {
g_print("usage: mu command [options] [parameters]\n"); mu_println("usage: mu command [options] [parameters]");
g_print("where command is one of index, find, cfind, view, mkdir, " mu_println("where command is one of index, find, cfind, view, mkdir, "
"extract, add, remove, script, verify or server\n"); "extract, add, remove, script, verify or server");
g_print("see the mu, mu-<command> or mu-easy manpages for " mu_println("see the mu, mu-<command> or mu-easy manpages for "
"more information\n"); "more information");
} }
@ -157,9 +159,9 @@ Mu::mu_cmd_execute(const Options& opts) try {
} catch (const Mu::Error& er) { } catch (const Mu::Error& er) {
return Err(er); return Err(er);
} catch (const std::runtime_error& re) { } 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) { } catch (const std::exception& ex) {
return Err(Error::Code::Internal, "error: %s", ex.what()); return Err(Error::Code::Internal, "error: {}", ex.what());
} catch (...) { } catch (...) {
return Err(Error::Code::Internal, "caught exception"); 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 show_manpage(opts, "mu-" + opts.help.command);
return Err(Error::Code::Command, return Err(Error::Code::Command,
"no help available for '%s'", opts.help.command.c_str()); "no help available for '{}'", opts.help.command);
} }
bool bool
@ -660,7 +660,7 @@ Options::make(int argc, char *argv[])
CLI::App app{"mu mail indexer/searcher", "mu"}; CLI::App app{"mu mail indexer/searcher", "mu"};
app.description(R"(mu mail indexer/searcher 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>. 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. 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&) { } catch (const CLI::CallForVersion&) {
std::cout << "version " << PACKAGE_VERSION << "\n"; std::cout << "version " << PACKAGE_VERSION << "\n";
} catch (const CLI::ParseError& pe) { } catch (const CLI::ParseError& pe) {
return Err(Error::Code::InvalidArgument, "%s", pe.what()); return Err(Error::Code::InvalidArgument, "{}", pe.what());
} catch (...) { } catch (...) {
return Err(Error::Code::Internal, "error parsing arguments"); return Err(Error::Code::Internal, "error parsing arguments");
} }

View File

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

View File

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