mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-09-07 21:07:20 +02:00
Use TaskChampion 0.7.0, now via cxx instead of hand-rolled FFI (#3588)
TC 0.7.0 introduces a new `TaskData` type that maps to Taskwarrior's `Task` type more cleanly. It also introduces the idea of gathering lists of operations and "committing" them to a replica. A consequence of this change is that TaskChampion no longer automatically maintains dependency information, so Taskwarrior must do so, with its `TDB2::dependency_sync` method. This method does a very similar thing to what TaskChampion had been doing, so this is a shift of responsibility but not a major performance difference. Cxx is .. not great. It is missing a lot of useful things that make a general-purpose bridge impractical: - no support for trait objects - no support for `Option<T>` (https://github.com/dtolnay/cxx/issues/87) - no support for `Vec<Box<..>>` As a result, some creativity is required in writing the bridge, for example returning a `Vec<OptionTaskData>` from `all_task_data` to allow individual `TaskData` values to be "taken" from the vector. That said, Cxx is the current state-of-the-art, and does a good job of ensuring memory safety, at the cost of some slightly awkward APIs. Subsequent work can remove the "TDB2" layer and allow commands and other parts of Taskwarrior to interface directly with the `Replica`.
This commit is contained in:
parent
0f96fd31bf
commit
4ff63a7960
59 changed files with 1531 additions and 7631 deletions
|
@ -1,8 +1,6 @@
|
|||
cmake_minimum_required (VERSION 3.22)
|
||||
include_directories (${CMAKE_SOURCE_DIR}
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_SOURCE_DIR}/src/tc
|
||||
${CMAKE_SOURCE_DIR}/src/tc/lib
|
||||
${CMAKE_SOURCE_DIR}/src/commands
|
||||
${CMAKE_SOURCE_DIR}/src/columns
|
||||
${CMAKE_SOURCE_DIR}/src/libshared/src
|
||||
|
@ -61,6 +59,7 @@ set (commands_SRCS Command.cpp Command.h
|
|||
CmdVersion.cpp CmdVersion.h)
|
||||
|
||||
add_library (commands STATIC ${commands_SRCS})
|
||||
target_link_libraries(commands taskchampion-cpp)
|
||||
|
||||
#SET(CMAKE_BUILD_TYPE gcov)
|
||||
#SET(CMAKE_CXX_FLAGS_GCOV "--coverage")
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <JSON.h>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class CmdImport : public Command {
|
||||
public:
|
||||
|
|
|
@ -35,12 +35,11 @@
|
|||
#include <inttypes.h>
|
||||
#include <shared.h>
|
||||
#include <signal.h>
|
||||
#include <taskchampion-cpp/lib.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "tc/Server.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CmdSync::CmdSync() {
|
||||
_keyword = "synchronize";
|
||||
|
@ -60,56 +59,53 @@ CmdSync::CmdSync() {
|
|||
int CmdSync::execute(std::string& output) {
|
||||
int status = 0;
|
||||
|
||||
tc::Server server;
|
||||
std::string server_ident;
|
||||
Context& context = Context::getContext();
|
||||
auto& replica = context.tdb2.replica();
|
||||
std::stringstream out;
|
||||
bool avoid_snapshots = false;
|
||||
bool verbose = Context::getContext().verbose("sync");
|
||||
|
||||
// If no server is set up, quit.
|
||||
std::string origin = Context::getContext().config.get("sync.server.origin");
|
||||
std::string url = Context::getContext().config.get("sync.server.url");
|
||||
std::string server_dir = Context::getContext().config.get("sync.local.server_dir");
|
||||
std::string client_id = Context::getContext().config.get("sync.server.client_id");
|
||||
std::string gcp_credential_path = Context::getContext().config.get("sync.gcp.credential_path");
|
||||
std::string gcp_bucket = Context::getContext().config.get("sync.gcp.bucket");
|
||||
std::string encryption_secret = Context::getContext().config.get("sync.encryption_secret");
|
||||
|
||||
// sync.server.origin is a deprecated synonym for sync.server.url
|
||||
std::string server_url = url == "" ? origin : url;
|
||||
|
||||
if (server_dir != "") {
|
||||
server = tc::Server::new_local(server_dir);
|
||||
server_ident = server_dir;
|
||||
} else if (gcp_bucket != "") {
|
||||
if (encryption_secret == "") {
|
||||
throw std::string("sync.encryption_secret is required");
|
||||
}
|
||||
server = tc::Server::new_gcp(gcp_bucket, gcp_credential_path, encryption_secret);
|
||||
std::ostringstream os;
|
||||
os << "GCP bucket " << gcp_bucket;
|
||||
server_ident = os.str();
|
||||
} else if (server_url != "") {
|
||||
std::string client_id = Context::getContext().config.get("sync.server.client_id");
|
||||
if (client_id == "" || encryption_secret == "") {
|
||||
throw std::string("sync.server.client_id and sync.encryption_secret are required");
|
||||
}
|
||||
server = tc::Server::new_sync(server_url, client_id, encryption_secret);
|
||||
std::ostringstream os;
|
||||
os << "Sync server at " << server_url;
|
||||
server_ident = os.str();
|
||||
} else {
|
||||
throw std::string("No sync.* settings are configured. See task-sync(5).");
|
||||
}
|
||||
|
||||
std::stringstream out;
|
||||
if (origin != "") {
|
||||
out << "sync.server.origin is deprecated. Use sync.server.url instead.\n";
|
||||
}
|
||||
|
||||
if (Context::getContext().verbose("sync")) {
|
||||
out << format("Syncing with {1}", server_ident) << '\n';
|
||||
if (server_dir != "") {
|
||||
if (verbose) {
|
||||
out << format("Syncing with {1}", server_dir) << '\n';
|
||||
}
|
||||
replica->sync_to_local(server_dir, avoid_snapshots);
|
||||
} else if (gcp_bucket != "") {
|
||||
if (encryption_secret == "") {
|
||||
throw std::string("sync.encryption_secret is required");
|
||||
}
|
||||
if (verbose) {
|
||||
out << format("Syncing with GCP bucket {1}", gcp_bucket) << '\n';
|
||||
}
|
||||
replica->sync_to_gcp(gcp_bucket, gcp_credential_path, encryption_secret, avoid_snapshots);
|
||||
} else if (server_url != "") {
|
||||
if (client_id == "" || encryption_secret == "") {
|
||||
throw std::string("sync.server.client_id and sync.encryption_secret are required");
|
||||
}
|
||||
if (verbose) {
|
||||
out << format("Syncing with sync server at {1}", server_url) << '\n';
|
||||
}
|
||||
replica->sync_to_remote(server_url, tc::uuid_from_string(client_id), encryption_secret,
|
||||
avoid_snapshots);
|
||||
} else {
|
||||
throw std::string("No sync.* settings are configured. See task-sync(5).");
|
||||
}
|
||||
|
||||
Context& context = Context::getContext();
|
||||
context.tdb2.sync(std::move(server), false);
|
||||
|
||||
if (context.config.getBoolean("purge.on-sync")) {
|
||||
context.tdb2.expire_tasks();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue