mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
Add support for cloud sync, specifically GCP (#3223)
* Add support for cloud sync, specifically GCP This adds generic support for sync to cloud services, with specific spuport for GCP. Adding others -- so long as they support a compare-and-set operation -- should be comparatively straightforward. The cloud support includes cleanup of unnecessary data, and should keep total space usage roughly proportional to the number of tasks. Co-authored-by: ryneeverett <ryneeverett@gmail.com>
This commit is contained in:
parent
6f1c16fecd
commit
9566c929e2
36 changed files with 4012 additions and 401 deletions
|
@ -56,9 +56,10 @@ target_link_libraries (task_executable task tc tc-rust commands tc columns libsh
|
|||
target_link_libraries (calc_executable task tc tc-rust commands tc columns libshared task libshared ${TASK_LIBRARIES})
|
||||
target_link_libraries (lex_executable task tc tc-rust commands tc columns libshared task libshared ${TASK_LIBRARIES})
|
||||
if (DARWIN)
|
||||
target_link_libraries (task_executable "-framework CoreFoundation -framework Security")
|
||||
target_link_libraries (calc_executable "-framework CoreFoundation -framework Security")
|
||||
target_link_libraries (lex_executable "-framework CoreFoundation -framework Security")
|
||||
# SystemConfiguration is required by Rust libraries like reqwest, to get proxy configuration.
|
||||
target_link_libraries (task_executable "-framework CoreFoundation -framework Security -framework SystemConfiguration")
|
||||
target_link_libraries (calc_executable "-framework CoreFoundation -framework Security -framework SystemConfiguration")
|
||||
target_link_libraries (lex_executable "-framework CoreFoundation -framework Security -framework SystemConfiguration")
|
||||
endif (DARWIN)
|
||||
|
||||
set_property (TARGET task_executable PROPERTY OUTPUT_NAME "task")
|
||||
|
@ -71,4 +72,4 @@ set_property (TARGET lex_executable PROPERTY OUTPUT_NAME "lex")
|
|||
#SET(CMAKE_BUILD_TYPE gcov)
|
||||
#SET(CMAKE_CXX_FLAGS_GCOV "--coverage")
|
||||
#SET(CMAKE_C_FLAGS_GCOV "--coverage")
|
||||
#SET(CMAKE_EXE_LINKER_FLAGS_GCOV "--coverage")
|
||||
#SET(CMAKE_EXE_LINKER_FLAGS_GCOV "--coverage")
|
||||
|
|
|
@ -283,6 +283,7 @@ std::string configurationDefaults =
|
|||
"#sync.server.encryption_secret # Encryption secret for sync to a server\n"
|
||||
"#sync.server.origin # Origin of the sync server\n"
|
||||
"#sync.local.server_dir # Directory for local sync\n"
|
||||
"#sync.gcp.bucket # Bucket for sync to GCP\n"
|
||||
"\n"
|
||||
"# Aliases - alternate names for commands\n"
|
||||
"alias.rm=delete # Alias for the delete command\n"
|
||||
|
|
|
@ -193,6 +193,7 @@ int CmdShow::execute (std::string& output)
|
|||
" sugar"
|
||||
" summary.all.projects"
|
||||
" sync.local.server_dir"
|
||||
" sync.gcp.bucket"
|
||||
" sync.server.client_id"
|
||||
" sync.server.encryption_secret"
|
||||
" sync.server.origin"
|
||||
|
|
|
@ -63,17 +63,32 @@ int CmdSync::execute (std::string& output)
|
|||
|
||||
// If no server is set up, quit.
|
||||
std::string origin = Context::getContext ().config.get ("sync.server.origin");
|
||||
std::string client_id = Context::getContext ().config.get ("sync.server.client_id");
|
||||
std::string encryption_secret = Context::getContext ().config.get ("sync.server.encryption_secret");
|
||||
std::string server_dir = Context::getContext ().config.get ("sync.local.server_dir");
|
||||
std::string gcp_bucket = Context::getContext ().config.get ("sync.gcp.bucket");
|
||||
if (server_dir != "") {
|
||||
server = tc::Server (server_dir);
|
||||
server = tc::Server::new_local (server_dir);
|
||||
server_ident = server_dir;
|
||||
} else if (origin != "" && client_id != "" && encryption_secret != "") {
|
||||
server = tc::Server (origin, client_id, encryption_secret);
|
||||
server_ident = origin;
|
||||
} else if (gcp_bucket != "") {
|
||||
std::string encryption_secret = Context::getContext ().config.get ("sync.gcp.encryption_secret");
|
||||
if (encryption_secret == "") {
|
||||
throw std::string ("sync.gcp.encryption_secret is required");
|
||||
}
|
||||
server = tc::Server::new_gcp (gcp_bucket, encryption_secret);
|
||||
std::ostringstream os;
|
||||
os << "GCP bucket " << gcp_bucket;
|
||||
server_ident = os.str();
|
||||
} else if (origin != "") {
|
||||
std::string client_id = Context::getContext ().config.get ("sync.server.client_id");
|
||||
std::string encryption_secret = Context::getContext ().config.get ("sync.server.encryption_secret");
|
||||
if (client_id == "" || encryption_secret == "") {
|
||||
throw std::string ("sync.server.client_id and encryption_secret are required");
|
||||
}
|
||||
server = tc::Server::new_sync (origin, client_id, encryption_secret);
|
||||
std::ostringstream os;
|
||||
os << "Sync server at " << origin;
|
||||
server_ident = os.str();
|
||||
} else {
|
||||
throw std::string ("Neither sync.server nor sync.local are configured.");
|
||||
throw std::string ("No sync.* settings are configured.");
|
||||
}
|
||||
|
||||
std::stringstream out;
|
||||
|
|
|
@ -32,7 +32,8 @@
|
|||
using namespace tc::ffi;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
tc::Server::Server (const std::string &server_dir)
|
||||
tc::Server
|
||||
tc::Server::new_local (const std::string &server_dir)
|
||||
{
|
||||
TCString tc_server_dir = tc_string_borrow (server_dir.c_str ());
|
||||
TCString error;
|
||||
|
@ -43,18 +44,17 @@ tc::Server::Server (const std::string &server_dir)
|
|||
tc_string_free (&error);
|
||||
throw errmsg;
|
||||
}
|
||||
inner = unique_tcserver_ptr (
|
||||
return Server (unique_tcserver_ptr (
|
||||
tcserver,
|
||||
[](TCServer* rep) { tc_server_free (rep); });
|
||||
[](TCServer* rep) { tc_server_free (rep); }));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
tc::Server::Server (const std::string &origin, const std::string &client_id, const std::string &encryption_secret)
|
||||
tc::Server
|
||||
tc::Server::new_sync (const std::string &origin, const std::string &client_id, const std::string &encryption_secret)
|
||||
{
|
||||
TCString tc_origin = tc_string_borrow (origin.c_str ());
|
||||
|
||||
TCString tc_client_id = tc_string_borrow (client_id.c_str ());
|
||||
|
||||
TCString tc_encryption_secret = tc_string_borrow (encryption_secret.c_str ());
|
||||
|
||||
TCUuid tc_client_uuid;
|
||||
|
@ -65,16 +65,36 @@ tc::Server::Server (const std::string &origin, const std::string &client_id, con
|
|||
}
|
||||
|
||||
TCString error;
|
||||
auto tcserver = tc_server_new_remote (tc_origin, tc_client_uuid, tc_encryption_secret, &error);
|
||||
auto tcserver = tc_server_new_sync (tc_origin, tc_client_uuid, tc_encryption_secret, &error);
|
||||
if (!tcserver) {
|
||||
auto errmsg = format ("Could not configure connection to server at {1}: {2}",
|
||||
origin, tc_string_content (&error));
|
||||
tc_string_free (&error);
|
||||
throw errmsg;
|
||||
}
|
||||
inner = unique_tcserver_ptr (
|
||||
return Server (unique_tcserver_ptr (
|
||||
tcserver,
|
||||
[](TCServer* rep) { tc_server_free (rep); });
|
||||
[](TCServer* rep) { tc_server_free (rep); }));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
tc::Server
|
||||
tc::Server::new_gcp (const std::string &bucket, const std::string &encryption_secret)
|
||||
{
|
||||
TCString tc_bucket = tc_string_borrow (bucket.c_str ());
|
||||
TCString tc_encryption_secret = tc_string_borrow (encryption_secret.c_str ());
|
||||
|
||||
TCString error;
|
||||
auto tcserver = tc_server_new_gcp (tc_bucket, tc_encryption_secret, &error);
|
||||
if (!tcserver) {
|
||||
auto errmsg = format ("Could not configure connection to GCP bucket {1}: {2}",
|
||||
bucket, tc_string_content (&error));
|
||||
tc_string_free (&error);
|
||||
throw errmsg;
|
||||
}
|
||||
return Server (unique_tcserver_ptr (
|
||||
tcserver,
|
||||
[](TCServer* rep) { tc_server_free (rep); }));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace tc {
|
|||
|
||||
// Server wraps the TCServer type, managing its memory, errors, and so on.
|
||||
//
|
||||
// Except as noted, method names match the suffix to `tc_replica_..`.
|
||||
// Except as noted, method names match the suffix to `tc_server_..`.
|
||||
class Server
|
||||
{
|
||||
public:
|
||||
|
@ -51,10 +51,13 @@ namespace tc {
|
|||
Server () = default;
|
||||
|
||||
// Construct a local server (tc_server_new_local).
|
||||
Server (const std::string& server_dir);
|
||||
static Server new_local (const std::string& server_dir);
|
||||
|
||||
// Construct a remote server (tc_server_new_remote).
|
||||
Server (const std::string &origin, const std::string &client_id, const std::string &encryption_secret);
|
||||
// Construct a remote server (tc_server_new_sync).
|
||||
static Server new_sync (const std::string &origin, const std::string &client_id, const std::string &encryption_secret);
|
||||
|
||||
// Construct a GCP server (tc_server_new_gcp).
|
||||
static Server new_gcp (const std::string &bucket, const std::string &encryption_secret);
|
||||
|
||||
// This object "owns" inner, so copy is not allowed.
|
||||
Server (const Server &) = delete;
|
||||
|
@ -65,6 +68,8 @@ namespace tc {
|
|||
Server &operator=(Server &&) noexcept;
|
||||
|
||||
protected:
|
||||
Server (unique_tcserver_ptr inner) : inner(std::move(inner)) {};
|
||||
|
||||
unique_tcserver_ptr inner;
|
||||
|
||||
// Replica accesses the inner pointer to call tc_replica_sync
|
||||
|
|
1299
src/tc/rust/Cargo.lock
generated
1299
src/tc/rust/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -6,4 +6,5 @@ version = "0.1.0"
|
|||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
taskchampion-lib = {path = "../../../taskchampion/lib"}
|
||||
taskchampion = { path = "../../../taskchampion/taskchampion", features = ["server-gcp", "server-sync"] }
|
||||
taskchampion-lib = { path = "../../../taskchampion/lib" }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue