diff --git a/lib/mu-msg-file.c b/lib/mu-msg-file.c index c242a6fa..bdd9d2e5 100644 --- a/lib/mu-msg-file.c +++ b/lib/mu-msg-file.c @@ -652,7 +652,7 @@ get_msgid (MuMsgFile *self, gboolean *do_free) return (char*)msgid; } else { /* if there is none, fake it */ *do_free = TRUE; - return g_strdup_printf ("%016 " PRIx64 "@fake-msgid", + return g_strdup_printf ("%016" PRIx64 "@fake-msgid", mu_util_get_hash (self->_path)); } } diff --git a/lib/mu-query.cc b/lib/mu-query.cc index aeb8fa6c..cc3ea0de 100644 --- a/lib/mu-query.cc +++ b/lib/mu-query.cc @@ -39,6 +39,8 @@ #include #include +using namespace Mu; + struct MuProc: public Mu::ProcIface { MuProc (const Xapian::Database& db): db_{db} {} @@ -185,7 +187,7 @@ public: const auto db = reinterpret_cast (mu_store_get_read_only_database (_store)); if (!db) - throw std::runtime_error ("no database"); + throw Mu::Error(Error::Code::NotFound, "no database"); return *db; } private: diff --git a/lib/mu-store.cc b/lib/mu-store.cc index ab900d4c..244cb387 100644 --- a/lib/mu-store.cc +++ b/lib/mu-store.cc @@ -28,6 +28,8 @@ #include "mu-store.hh" #include "utils/mu-str.h" +#include "utils/mu-error.hh" + #include "mu-msg-part.h" #include "utils/mu-utils.hh" @@ -112,8 +114,7 @@ struct Store::Private { writable_db()->set_metadata(SchemaVersionKey, schema_version_); writable_db()->set_metadata(MaildirKey, maildir_); - writable_db()->set_metadata(CreatedKey, - Mu::format("%" PRId64, (int64_t)created_)); + writable_db()->set_metadata(CreatedKey, Mu::format("%" PRId64, (int64_t)created_)); } ~Private() { @@ -123,7 +124,7 @@ struct Store::Private { std::shared_ptr db() const { if (!db_) - throw std::runtime_error ("no db"); + throw Mu::Error(Error::Code::NotFound, "no database found"); return db_; } @@ -134,7 +135,7 @@ struct Store::Private { std::shared_ptr writable_db() const { auto w_db{wdb()}; if (!w_db) - throw std::runtime_error ("database is read-only"); + throw Mu::Error(Error::Code::AccessDenied, "database is read-only"); else return w_db; } @@ -148,7 +149,9 @@ struct Store::Private { // very basic check; just ensure there's no ',' in the address. // we don't insist on full RFC5322 if (addr.find(",") != std::string::npos) - throw std::runtime_error ("e-mail address with ',': " + addr); + throw Mu::Error::make(Error::Code::InvalidArgument, + "e-mail address '%s' contains comma", + addr.c_str()); if (!all_addresses.empty()) all_addresses += ','; all_addresses += addr; @@ -188,10 +191,6 @@ struct Store::Private { #undef LOCKED #define LOCKED std::lock_guard l(priv_->lock_); -struct NeedsReIndex: public std::runtime_error { - using std::runtime_error::runtime_error; -}; - Store::Store (const std::string& path, bool readonly): priv_{std::make_unique(path, readonly)} { @@ -199,7 +198,7 @@ Store::Store (const std::string& path, bool readonly): return; // All is good; nothing further to do if (readonly || maildir().empty()) - throw NeedsReIndex("database needs reindexing"); + throw Mu::Error(Error::Code::SchemaMismatch, "database needs reindexing"); g_debug ("upgrading database"); const auto addresses{personal_addresses()}; @@ -416,9 +415,13 @@ mu_store_new_readable (const char* xpath, GError **err) try { return reinterpret_cast(new Store (xpath)); - } catch (const NeedsReIndex& nri) { - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN_NEEDS_REINDEX, - "database @ %s needs (re)indexing", xpath); + } catch (const Mu::Error& me) { + if (me.code() == Mu::Error::Code::SchemaMismatch) + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN_NEEDS_REINDEX, + "database @ %s needs (re)indexing", xpath); + else + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN, + "error opening database @ %s: %s", xpath, me.what()); // } catch (const Xapian::DatabaseNotFoundError& dbe) { // Xapian 1.4.10 // g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN_NEEDS_REINDEX, // "database @ %s not found", xpath); @@ -442,9 +445,13 @@ mu_store_new_writable (const char* xpath, GError **err) try { return reinterpret_cast(new Store (xpath, false/*!readonly*/)); - } catch (const NeedsReIndex& nri) { - g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN_NEEDS_REINDEX, - "database @ %s needs (re)indexing", xpath); + } catch (const Mu::Error& me) { + if (me.code() == Mu::Error::Code::SchemaMismatch) + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN_NEEDS_REINDEX, + "database @ %s needs (re)indexing", xpath); + else + g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN, + "error opening database @ %s: %s", xpath, me.what()); // } catch (const Xapian::DatabaseNotFoundError& dbe) { // Xapian 1.4.10 // g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_XAPIAN_NEEDS_REINDEX, // "database @ %s not found", xpath); @@ -600,7 +607,8 @@ mu_store_get_docid_for_path (const MuStore *store, const char* path, GError **er Xapian::MSet mset (enq.get_mset (0,1)); if (mset.empty()) - throw std::runtime_error ("message not found"); + throw Mu::Error::make(Error::Code::NotFound, + "message @ %s not found in store", path); return *mset.begin(); diff --git a/lib/parser/parser.cc b/lib/parser/parser.cc index 5ac5c36f..f62aab52 100644 --- a/lib/parser/parser.cc +++ b/lib/parser/parser.cc @@ -19,6 +19,7 @@ #include "parser.hh" #include "tokenizer.hh" #include "utils/mu-utils.hh" +#include "utils/mu-error.hh" using namespace Mu; @@ -36,7 +37,7 @@ using namespace Mu; // -> [field:]/regex/ -#define BUG(...) std::runtime_error (format("%u: BUG: ",__LINE__) \ +#define BUG(...) Mu::Error (Error::Code::Internal, format("%u: BUG: ",__LINE__) \ + format(__VA_ARGS__)) static Token diff --git a/lib/parser/tree.hh b/lib/parser/tree.hh index 5ff02559..51e276c7 100644 --- a/lib/parser/tree.hh +++ b/lib/parser/tree.hh @@ -25,6 +25,7 @@ #include #include +#include namespace Mu { @@ -62,7 +63,7 @@ struct Node { case Type::Range: return "range"; break; case Type::Invalid: return ""; break; default: - throw std::runtime_error ("bug"); + throw Mu::Error(Error::Code::Internal, "unexpected type"); } } diff --git a/lib/parser/xapian.cc b/lib/parser/xapian.cc index 19afb663..5c87efe0 100644 --- a/lib/parser/xapian.cc +++ b/lib/parser/xapian.cc @@ -23,6 +23,7 @@ #include #include "parser/xapian.hh" +#include using namespace Mu; @@ -42,7 +43,7 @@ xapian_query_op (const Mu::Tree& tree) case Node::Type::OpOr: op = Xapian::Query::OP_OR; break; case Node::Type::OpXor: op = Xapian::Query::OP_XOR; break; case Node::Type::OpAndNot: op = Xapian::Query::OP_AND_NOT; break; - default: throw std::runtime_error ("invalid op"); // bug + default: throw Mu::Error (Error::Code::Internal, "invalid op"); // bug } std::vector childvec; @@ -114,6 +115,6 @@ Mu::xapian_query (const Mu::Tree& tree) case Node::Type::Range: return xapian_query_range (tree); default: - throw std::runtime_error ("invalid query"); // bug + throw Mu::Error (Error::Code::Internal, "invalid query"); // bug } } diff --git a/lib/utils/mu-util.c b/lib/utils/mu-util.c index 4dfb4af3..b896ea57 100644 --- a/lib/utils/mu-util.c +++ b/lib/utils/mu-util.c @@ -428,7 +428,7 @@ mu_util_g_set_error (GError **err, MuError errcode, const char *frm, ...) -static gboolean +__attribute__((format(printf, 2, 0))) static gboolean print_args (FILE *stream, const char *frm, va_list args) { gchar *str;