Before we created an empty file and asked the OS to copy the file.
The OS is very good at this so this is a good idea generally. However
it seems that in some cases, possibly an Android Dowload folder, we
might be able to create a file but not overwrite it. Thus refactor
this a bit so we are copying the file ourselves.
There are no new tests here since the behaviour remains identical.
The good news is that the existing tests were good enough to catch
some bugs already.
This more strongly types the ubiquitous message id type by no longer
making it an integer. It keeps the actual ID opaque. Only for the
generic job API the number keeps being used. Some locations also need
to create it from an integer and call MsgId::new().
Turns out that anyone that uses these either justs wants a file or
wants a blob. Consolidate those patterns into one place and simplify
all the callers.
This creates a specific type for blobs, with well defined conversions
at the borders. It also introduces a strong type for the Param::File
value since that param is often used used by the public API to set
filenames using absolute paths, but then core changes the param to a
blob before it gets to the database.
This eliminates a few more functions with very mallable C-like
arguments behaviour which combine a number of operations in one.
Because blob filenames are stored so often in arbitrary strings this
does add more code when receiving those, until the storage is fixed.
File name sanitisation is now deletated to the sanitize-filename crate
which should do a slightly better job at this.
There is very little API guarantees about this, but clients seem to
expect *something* to work on a closed context. So split this up into
static info an more dynamic context-related info, but let's not
provide any guarantees about what keys are available when.
Fixes#599
This adopts the FFI API to use the new Context::new() and
Contest::drop() Rust-style APIs while preserving the semantics of the
existing FFI API. It introduces a wrapper around the context which
keeps an optional reference to the actual context, changing dc_open()
and dc_close() to create/destroy the actual reference.
This changes the events emitted on closing slightly: they only get
emitted when dc_close() was called while the context was open. While
dc_close() remains idempotent in that it can still be called safely
multiple times, the close events will only occur if the context is
actually closed.
A new context is now created by calling Context::new and therefore you
always have a valid context. This is much more in Rust style and will
allow a lot of furture simplifications on the context itself.
The FFI layer has not yet been adjusted in this commit and thus will
fail.
The Message struct had a reference to the context which made a few
APIs a little easier. However it has surprising consequences a long
way down the line as shown in #335: it means any object which has such
a reference needs to keep open a lock if we want to do this refactor
of no longer having a "closed" Context struct on the Rust API (which
has many benefits which will simply that Context struct and is more
the Rust way - RAII etc).
By refactoring away the context reference on the rust API as done in
here however, we push this behaviour of how these references are
handled back to the C-API pointer behaviour: that is unsafe but just
works in a C-like way. The resulting complexity in the FFI layer is
also notably less than in the #335 alternative.
As a consequence all APIs which require the context, now explicitly
need to get the context passed in as an argument. It looks like this
is certainly no downside and maybe even beneficial for further API
refactors.
For this strategy to work out the same should be done to
dc_chatlist_t, dc_chat_t and dc_contact_t. But this working for
dc_msg_t give a reasonable confidence that this is a good approach.
The function is made safe and now returns Result. Functionally it now
fails when it can not write the newly generated key to the database
whereas before it still returned the key but logged a warning. There
is no reason this shouldn't be able to store the key and silently not
storing the key may result in later operations assuming the key is
available, so failing seems like a better choice.
The function now also uses a proper mutex to guard against multiple
threads generating keys. And this mutex is Context-scoped rather than
fully global (static).
This removes the dc_context_unref function from the Rust API which was
just an alias for dc_close. It still exists on the C API where it
makes sure to free the memory.
It also implements Drop for the context which just calls dc_close to
make sure all the memory is freed. Since you can call dc_close as
many times as you like this ensures that at the Rust level you can't
Drop the struct without releasing the memory.
Finally since memory is now freed by dropping the struct this removes
the #[repr(C)] for the struct. This struct is fully opaque to the C
API.
This marks the function safe and returns Result, it also now returns
the ConfiguredAddr since it has to look this up anyway and it makes
testing more easy. Turns out it reduces some duplicate SQL query in
some callers too.
More test code has been moved from dc_imex to test_utils as it's
more genrally applicable.
Mostly safe string usage, but some other minor cleanups:
- This isn't used from any C code, so no extern C.
- Use Config enums rather than strings.
- Clean up old unused sql statements.
Add a trait for str.strdup() to replace to_cstring() which avoid the
signature ambiguity with .to_string().
Also instruduce CString::yolo() as a shortcut to
CString::new().unwrap() and use it whenever the variable does can be
deallocated by going out of scope. This is less error prone.
Use some Path.to_c_string() functions where possible.
This is writes pkg-config/deltachat.pc file in the target directory,
using the PREFIX environment variable at build time. If this is
undefined at build time /usr/local is used.
For a few of the locations where error handling is done correctly this
does the right thing. For most other places it gracefully ignores any
issues which is what the original code did as well. Errors are
already logged by the called functions in those cases.
- Pass extra_link_args when using an installed libdeltachat
- Allow setting the liveconfig by envvar
- Show lifeconfig path in the pytest summary line
- Pass required envvars through tox
- Fix broken liveconfig passing in run-integration-test.sh
This clears the way to start working on making the functions safe.
But small PRs are good PRs so let's get this rename out of the way and
have future PRs less noisy.
Also stop making this #[repr(C)] and start making fields that are not
used private. Lastly clean up some comments by moving them or
deleting them, so they make sense again after the translation.
This makes interactively running the tests a much more pleasant
experience rather than something one dreads. These tests will still
be run on the CI. To run these manually run:
cargo test [TESTNAME] -- --ignored
With the API changes already done, notably .is_open(), the
implementation of the sqlite can and should now be private.
This also doesn't need to be #[repr(C)] anymore since the C API does
not need to access the fields in the struct.
Experiment with refactoring the internal sql interface a bit. My
original goal was to modify the schema and thus refactor to a state
where it would be sane to write tests for dc_sqlite_open() (and/or
however it ends up refactored) to assert schame changes before/after.
The C API allows passing a NULL pointer is for the callback function.
However when calling the callback nothing checks for this null pointer
and thus things fail badly. Even worse since the C API is defined
using an "fn pointer" rather than a "*-ptr" or raw pointer to the
function rust does not realise this can be invalid and therefore the
typechecker does not catch this even though there are no unsafe casts.
Fix this by making the callback an Option in rust, this can be easily
checked when calling. Also add a Context.call_cb() function which
simplifies calling the callback, hides the weird syntax due to the
function pointer and makes the call a little easier. Finally it also
means the option checking is only needed in one place.
For the C API this needs to check if this is a NULL pointer or not,
this is implicitly done by rust using the "nullable pointer
optimisation":
https://doc.rust-lang.org/nomicon/ffi.html#the-nullable-pointer-optimization
This stops using the deprecated libc::uint32_t and libc::uint64_t
types in favour of the native u32 and u64 types.
It also uses a newer nightly compiler to get rid of the incorrect
"unused no_mangle" warning when compiling incrementally.
Finally the newer compiler prefers us to be explicit when implementing
traits using the new dyn keyword.
This links the python bindings statically to libdeltachat.a if the
DCC_RS_DEV environment variable is set to the project's root. This is
a little simpler then requiring the manual CFLAGS and LD_LIBRARY_PATH
tweaking.
It also adds a script to easily invoke the integration tests locally
without forgetting steps.
The function does a cast and does not create a new objects. The
stdlib convention is to use to_*() for functions which return new
objects and as_*() for functions which keep referring to the same data
but using a different type. Follow that convention.