diff --git a/cli/src/invocation/mod.rs b/cli/src/invocation/mod.rs index d7bcaef0a..9b9d7029c 100644 --- a/cli/src/invocation/mod.rs +++ b/cli/src/invocation/mod.rs @@ -106,15 +106,25 @@ fn get_replica(settings: &Config) -> Fallible { /// Get the server for this invocation fn get_server(settings: &Config) -> Fallible> { - let client_id = settings.get_str("server_client_id")?; - let client_id = Uuid::parse_str(&client_id)?; - let origin = settings.get_str("server_origin")?; - log::debug!("Using sync-server with origin {}", origin); - log::debug!("Sync client ID: {}", client_id); - Ok(server::from_config(ServerConfig::Remote { - origin, - client_id, - })?) + // if server_client_id and server_origin are both set, use + // the remote server + if let (Ok(client_id), Ok(origin)) = ( + settings.get_str("server_client_id"), + settings.get_str("server_origin"), + ) { + let client_id = Uuid::parse_str(&client_id)?; + + log::debug!("Using sync-server with origin {}", origin); + log::debug!("Sync client ID: {}", client_id); + Ok(server::from_config(ServerConfig::Remote { + origin, + client_id, + })?) + } else { + let server_dir = settings.get_str("server_dir")?.into(); + log::debug!("Using local sync-server at `{:?}`", server_dir); + Ok(server::from_config(ServerConfig::Local { server_dir })?) + } } /// Get a WriteColor implementation based on whether the output is a tty. diff --git a/cli/src/settings.rs b/cli/src/settings.rs index 02e554c76..4d59b00be 100644 --- a/cli/src/settings.rs +++ b/cli/src/settings.rs @@ -7,12 +7,21 @@ pub(crate) fn read_settings() -> Fallible { let mut settings = Config::default(); // set up defaults - if let Some(mut dir) = dirs::data_local_dir() { - dir.push("taskchampion"); + if let Some(dir) = dirs::data_local_dir() { + let mut tc_dir = dir.clone(); + tc_dir.push("taskchampion"); settings.set_default( "data_dir", // the config crate does not support non-string paths - dir.to_str().expect("data_local_dir is not utf-8"), + tc_dir.to_str().expect("data_local_dir is not utf-8"), + )?; + + let mut server_dir = dir; + server_dir.push("taskchampion-sync-server"); + settings.set_default( + "server_dir", + // the config crate does not support non-string paths + server_dir.to_str().expect("data_local_dir is not utf-8"), )?; } diff --git a/docs/src/usage.md b/docs/src/usage.md index 84ee5626c..5ddc60c91 100644 --- a/docs/src/usage.md +++ b/docs/src/usage.md @@ -17,15 +17,33 @@ On OS X, it's `~/Library/Preferences`. On Windows, it's `AppData/Roaming` in your home directory. The path can be overridden by setting `$TASKCHAMPION_CONFIG`. -Individual configuration parameters can be overridden by environemnt variables, converted to upper-case and prefixed with `TASKCHAMPION_`, e.g., `TASKCHAMPION_DATA_DIR`. +Individual configuration parameters can be overridden by environment variables, converted to upper-case and prefixed with `TASKCHAMPION_`, e.g., `TASKCHAMPION_DATA_DIR`. Nested configuration parameters cannot be overridden by environment variables. The following configuration parameters are available: * `data_dir` - path to a directory containing the replica's task data (which will be created if necessary). - Default: `taskchampion` in the local data directory -* `server_origin` - Origin of the taskchampion sync server, e.g., `https://taskchampion.example.com` + Default: `taskchampion` in the local data directory. +* `server_dir` - path to a directory containing the local server's data. + This is only used if `server_origin` or `server_client_id` are not set. + Default: `taskchampion-sync-server` in the local data directory. +* `server_origin` - Origin of the TaskChampion sync server, e.g., `https://taskchampion.example.com`. + If not set, then sync is done to a local server. * `server_client_id` - Client ID to identify this replica to the sync server (a UUID) + If not set, then sync is done to a local server. + +### Synchronization + +A TaskChampion replica "synchronizes" its local task database with other replicas via a sync server. +This operation is triggered by running `task sync`. +Typically this runs frequently in a cron task. +The operation is quick, especially if no changes have occurred. + +The replica expects to be synchronized frequently, even if no server is involved. +Without periodic syncs, the storage space used for the task database will grow quickly, and performance will suffer. + +By default, TaskChampion syncs to a "local server", as specified by the `server_dir` configuration parameter. +It is possible to switch to a remote server later by setting `server_origin` and `server_client_id` appropriately. ## `taskchampion-sync-server`