mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
add tc_replica_undo
This commit is contained in:
parent
ce56127bbf
commit
e590dc7c98
5 changed files with 33 additions and 14 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -3031,6 +3031,7 @@ dependencies = [
|
|||
name = "taskchampion-lib"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cbindgen",
|
||||
"libc",
|
||||
"taskchampion",
|
||||
|
|
|
@ -5,8 +5,14 @@
|
|||
TEST_CASE("creating an in-memory Replica does not crash") {
|
||||
Replica *rep = tc_replica_new(NULL);
|
||||
CHECK(tc_replica_error(rep) == NULL);
|
||||
uhoh(rep);
|
||||
REQUIRE(tc_replica_error(rep) != NULL);
|
||||
CHECK(strcmp(tc_replica_error(rep), "uhoh!") == 0);
|
||||
tc_replica_free(rep);
|
||||
}
|
||||
|
||||
TEST_CASE("undo on an empty in-memory Replica does nothing") {
|
||||
Replica *rep = tc_replica_new(NULL);
|
||||
CHECK(tc_replica_error(rep) == NULL);
|
||||
int rv = tc_replica_undo(rep);
|
||||
CHECK(rv == 0);
|
||||
CHECK(tc_replica_error(rep) == NULL);
|
||||
tc_replica_free(rep);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ crate-type = ["cdylib"]
|
|||
[dependencies]
|
||||
libc = "0.2.113"
|
||||
taskchampion = { path = "../taskchampion" }
|
||||
anyhow = "1.0"
|
||||
|
||||
[build-dependencies]
|
||||
cbindgen = "0.20.0"
|
||||
|
|
|
@ -10,6 +10,7 @@ use std::os::unix::ffi::OsStrExt;
|
|||
/// A replica represents an instance of a user's task data, providing an easy interface
|
||||
/// for querying and modifying that data.
|
||||
pub struct Replica {
|
||||
// TODO: make this an option so that it can be take()n when holding a mut ref
|
||||
inner: TCReplica,
|
||||
error: Option<CString>,
|
||||
}
|
||||
|
@ -51,25 +52,32 @@ fn rep_ref(rep: *mut Replica) -> &'static mut Replica {
|
|||
unsafe { &mut *rep }
|
||||
}
|
||||
|
||||
fn wrap<T, F>(rep: *mut Replica, f: F, err_value: T) -> T
|
||||
fn wrap<'a, T, F>(rep: *mut Replica, f: F, err_value: T) -> T
|
||||
where
|
||||
F: FnOnce(&mut Replica) -> Result<T, &'static str>,
|
||||
F: FnOnce(&mut TCReplica) -> anyhow::Result<T>,
|
||||
{
|
||||
debug_assert!(!rep.is_null());
|
||||
let rep = unsafe { &mut *rep };
|
||||
match f(rep) {
|
||||
let rep: &'a mut Replica = rep_ref(rep);
|
||||
match f(&mut rep.inner) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
rep.error = Some(CString::new(e.as_bytes()).unwrap());
|
||||
let error = e.to_string();
|
||||
let error = match CString::new(error.as_bytes()) {
|
||||
Ok(e) => e,
|
||||
Err(_) => CString::new("(invalid error message)".as_bytes()).unwrap(),
|
||||
};
|
||||
rep.error = Some(error);
|
||||
err_value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// temporary (testing errors)
|
||||
/// Undo local operations until the most recent UndoPoint.
|
||||
///
|
||||
/// Returns -1 on error, 0 if there are no local operations to undo, and 1 if operations were
|
||||
/// undone.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn uhoh<'a>(rep: *mut Replica) -> u32 {
|
||||
wrap(rep, |rep| Err("uhoh!"), 0)
|
||||
pub extern "C" fn tc_replica_undo<'a>(rep: *mut Replica) -> i32 {
|
||||
wrap(rep, |rep| Ok(if rep.undo()? { 1 } else { 0 }), -1)
|
||||
}
|
||||
|
||||
/// Get the latest error for a replica, or NULL if the last operation succeeded.
|
||||
|
|
|
@ -20,8 +20,11 @@ extern "C" {
|
|||
/// Replicas are not threadsafe.
|
||||
Replica *tc_replica_new(const char *path);
|
||||
|
||||
/// temporary (testing errors)
|
||||
uint32_t uhoh(Replica *rep);
|
||||
/// Undo local operations until the most recent UndoPoint.
|
||||
///
|
||||
/// Returns -1 on error, 0 if there are no local operations to undo, and 1 if operations were
|
||||
/// undone.
|
||||
int32_t tc_replica_undo(Replica *rep);
|
||||
|
||||
/// Get the latest error for a replica, or NULL if the last operation succeeded.
|
||||
///
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue