fix#2254: if the DB was closed without calling stop_io() and then an interrupt arrives (e.g. incoming message), the db was corrupted.
* Add result.log() for logging with less boilerplate code
* Bugfix: Resultify housekeeping() to make it abort if the db is closed instead of just deleting everything
* Require the UI to call dc_stop_io() before backup export
* Prepare a bit better for closed-db: Resultify get_uidvalidity and get_uid_next and let job::load_next() wait until the db is open
About the bug (before this PR):
if the DB was closed without calling stop_io() and then an interrupt arrives (e.g. incoming message):
- I don't know if it downloads the message, but of course at some point the process of receiving the message will fail
- In my test, DC is just in the process of moving a message when the imex starts, but then can't delete the job or update the msg server_uid
- Then, when job::load_next() is called, no job can be loaded. That's why it calls `load_housekeeping_job()`. As `load_housekeeping_job()` can't load the time of the last housekeeping, it assumes we never ran housekeeping and returns a new Housekeeping job, which is immediately executed.
- housekeeping can't find any blobs referenced in the db and therefore deletes almost all blobs.
This changes the internal stock strings API to be more strongly typed,
ensuring that the caller can not construct the stock string in the
wrong way.
The old approach left it to the callers to figure out how a stock
string should be created, now each stock string has their specific
arguments and callers can not make mistakes. In particular all the
subtleties and different ways of calling stock_system_msg() disappear.
This could not use a trait for stock strings, as this would not allow
having per-message typed arguments. So we needed a type per message
with a custom method, only by convention this method is .stock_str().
The type is a enum without variants to avoid allowing someone to
create the type.
Sadly the fallback string and substitutions are still far away from
each other, but it is now only one place which needs to know how to
construct the string instead of many.
This removes the proxy via crate::error to depend on anyhow directly.
There is no benefit to this indirection and this makes it simpler to
see which error types are used.
Lots of new clippy lints due to toolchain upgrade.
Made the Message::error field pub(crate) again, it was the odd one out
and it seemed a reasonable way to shut up clippy.
This tidies up our testing tools a little bit. We had several
functions which through various changes ended up doing the same and
some more which did very similar stuff, so I merged them to have
things simpler. Also moved towards methods on the TestContext struct
while cleaning this up anyway, seems like this structure is going to
stay around for a bit anyway.
The intersting change is in `test_utils.rs`, everything else is just
updating callers. A few tests used example.org which I moved to
example.com to be able to re-use more configuration of the test
context.
This means all key conversions/serialisation/deserialisation can be
done with DcKey rather than Key. Also migrate all key conversion
tests to DcKey rather than Key.
This moves the loading of the keys from the database to the trait and
thus with types differing between public and secret keys. This
fetches the Config::ConfiguredAddr (configured_addr) directly from the
database in the SQL to simplify the API and consistency instead of
making this the responsiblity of all callers to get this right.
Since anyone invoking these methods also wants to be sure the keys
exist, move key generation here as well. This already simplifies some
code in contact.rs and will eventually replace all manual checks for
existing keys.
To make errors more manageable this gives EmailAddress it's own error
type and adds some conversions for it. Otherwise the general error
type leaks to far. The EmailAddress type also gets its ToSql trait impl
to be able to save it to the database directly.