mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
show undo diff (#3213)
Exposes undo operations via the C API, and uses those to show a (new, differently formatted) diff before committing the undo.
This commit is contained in:
parent
89df80c9f0
commit
34c0e67469
18 changed files with 646 additions and 66 deletions
51
src/TDB2.cpp
51
src/TDB2.cpp
|
@ -42,6 +42,7 @@
|
|||
#include <main.h>
|
||||
#include <util.h>
|
||||
#include "tc/Server.h"
|
||||
#include "tc/util.h"
|
||||
|
||||
bool TDB2::debug_mode = false;
|
||||
static void dependency_scan (std::vector<Task> &);
|
||||
|
@ -207,10 +208,58 @@ void TDB2::get_changes (std::vector <Task>& changes)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB2::revert ()
|
||||
{
|
||||
replica.undo (NULL);
|
||||
auto undo_ops = replica.get_undo_ops();
|
||||
if (undo_ops.len == 0) {
|
||||
std::cout << "No operations to undo.";
|
||||
return;
|
||||
}
|
||||
if (confirm_revert(undo_ops)) {
|
||||
// Has the side-effect of freeing undo_ops.
|
||||
replica.commit_undo_ops(undo_ops, NULL);
|
||||
} else {
|
||||
replica.free_replica_ops(undo_ops);
|
||||
}
|
||||
replica.rebuild_working_set (false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool TDB2::confirm_revert (struct tc::ffi::TCReplicaOpList undo_ops)
|
||||
{
|
||||
// TODO Use show_diff rather than this basic listing of operations, though
|
||||
// this might be a worthy undo.style itself.
|
||||
std::cout << "The following " << undo_ops.len << " operations would be reverted:\n";
|
||||
for (size_t i = 0; i < undo_ops.len; i++) {
|
||||
std::cout << "- ";
|
||||
tc::ffi::TCReplicaOp op = undo_ops.items[i];
|
||||
switch(op.operation_type) {
|
||||
case tc::ffi::TCReplicaOpType::Create:
|
||||
std::cout << "Create " << replica.get_op_uuid(op);
|
||||
break;
|
||||
case tc::ffi::TCReplicaOpType::Delete:
|
||||
std::cout << "Delete " << replica.get_op_old_task_description(op);
|
||||
break;
|
||||
case tc::ffi::TCReplicaOpType::Update:
|
||||
std::cout << "Update " << replica.get_op_uuid(op) << "\n";
|
||||
std::cout << " " << replica.get_op_property(op) << ": " << option_string(replica.get_op_old_value(op)) << " -> " << option_string(replica.get_op_value(op));
|
||||
break;
|
||||
case tc::ffi::TCReplicaOpType::UndoPoint:
|
||||
throw std::string ("Can't undo UndoPoint.");
|
||||
break;
|
||||
default:
|
||||
throw std::string ("Can't undo non-operation.");
|
||||
break;
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
return ! Context::getContext ().config.getBoolean ("confirmation") ||
|
||||
confirm ("The undo command is not reversible. Are you sure you want to revert to the previous state?");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string TDB2::option_string(std::string input) {
|
||||
return input == "" ? "<empty>" : input;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB2::show_diff (
|
||||
const std::string& current,
|
||||
|
|
|
@ -78,13 +78,15 @@ public:
|
|||
void dump ();
|
||||
|
||||
void sync (tc::Server server, bool avoid_snapshots);
|
||||
bool confirm_revert(struct tc::ffi::TCReplicaOpList);
|
||||
|
||||
private:
|
||||
tc::Replica replica;
|
||||
std::optional<tc::WorkingSet> _working_set;
|
||||
|
||||
const tc::WorkingSet &working_set ();
|
||||
void show_diff (const std::string&, const std::string&, const std::string&);
|
||||
static std::string option_string (std::string input);
|
||||
static void show_diff (const std::string&, const std::string&, const std::string&);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "tc/Server.h"
|
||||
#include "tc/WorkingSet.h"
|
||||
#include "tc/util.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace tc::ffi;
|
||||
|
||||
|
@ -154,14 +155,68 @@ void tc::Replica::sync (Server server, bool avoid_snapshots)
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void tc::Replica::undo (int32_t *undone_out)
|
||||
TCReplicaOpList tc::Replica::get_undo_ops ()
|
||||
{
|
||||
auto res = tc_replica_undo (&*inner, undone_out);
|
||||
return tc_replica_get_undo_ops(&*inner);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void tc::Replica::commit_undo_ops (TCReplicaOpList tc_undo_ops, int32_t *undone_out)
|
||||
{
|
||||
auto res = tc_replica_commit_undo_ops (&*inner, tc_undo_ops, undone_out);
|
||||
if (res != TC_RESULT_OK) {
|
||||
throw replica_error ();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void tc::Replica::free_replica_ops (TCReplicaOpList tc_undo_ops)
|
||||
{
|
||||
tc_replica_op_list_free(&tc_undo_ops);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string tc::Replica::get_op_uuid(TCReplicaOp &tc_replica_op) const
|
||||
{
|
||||
TCString uuid = tc_replica_op_get_uuid(&tc_replica_op);
|
||||
return tc2string(uuid);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string tc::Replica::get_op_property(TCReplicaOp &tc_replica_op) const
|
||||
{
|
||||
TCString property = tc_replica_op_get_property(&tc_replica_op);
|
||||
return tc2string(property);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string tc::Replica::get_op_value(TCReplicaOp &tc_replica_op) const
|
||||
{
|
||||
TCString value = tc_replica_op_get_value(&tc_replica_op);
|
||||
return tc2string(value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string tc::Replica::get_op_old_value(TCReplicaOp &tc_replica_op) const
|
||||
{
|
||||
TCString old_value = tc_replica_op_get_old_value(&tc_replica_op);
|
||||
return tc2string(old_value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string tc::Replica::get_op_timestamp(TCReplicaOp &tc_replica_op) const
|
||||
{
|
||||
TCString timestamp = tc_replica_op_get_timestamp(&tc_replica_op);
|
||||
return tc2string(timestamp);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string tc::Replica::get_op_old_task_description(TCReplicaOp &tc_replica_op) const
|
||||
{
|
||||
TCString description = tc_replica_op_get_old_task_description(&tc_replica_op);
|
||||
return tc2string(description);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int64_t tc::Replica::num_local_operations ()
|
||||
{
|
||||
|
|
|
@ -93,7 +93,15 @@ namespace tc {
|
|||
tc::Task import_task_with_uuid (const std::string &uuid);
|
||||
// TODO: struct TCTask *tc_replica_import_task_with_uuid(struct TCReplica *rep, struct TCUuid tcuuid);
|
||||
void sync(Server server, bool avoid_snapshots);
|
||||
void undo (int32_t *undone_out);
|
||||
tc::ffi::TCReplicaOpList get_undo_ops ();
|
||||
void commit_undo_ops (tc::ffi::TCReplicaOpList tc_undo_ops, int32_t *undone_out);
|
||||
void free_replica_ops (tc::ffi::TCReplicaOpList tc_undo_ops);
|
||||
std::string get_op_uuid(tc::ffi::TCReplicaOp &tc_replica_op) const;
|
||||
std::string get_op_property(tc::ffi::TCReplicaOp &tc_replica_op) const;
|
||||
std::string get_op_value(tc::ffi::TCReplicaOp &tc_replica_op) const;
|
||||
std::string get_op_old_value(tc::ffi::TCReplicaOp &tc_replica_op) const;
|
||||
std::string get_op_timestamp(tc::ffi::TCReplicaOp &tc_replica_op) const;
|
||||
std::string get_op_old_task_description(tc::ffi::TCReplicaOp &tc_replica_op) const;
|
||||
int64_t num_local_operations ();
|
||||
int64_t num_undo_points ();
|
||||
// TODO: TCResult tc_replica_add_undo_point(struct TCReplica *rep, bool force);
|
||||
|
|
4
src/tc/rust/Cargo.lock
generated
4
src/tc/rust/Cargo.lock
generated
|
@ -1758,9 +1758,9 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
|||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.6.1"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560"
|
||||
checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"serde",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue