From 0d8094967d7b07c832f798756e2b6d5609e7babc Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Thu, 22 Apr 2021 18:01:09 +0300 Subject: feat: expand tilde notation in configuration file Backup roots and log file can now say ~/foo/bar to refer to files relative to the user's home directory. --- obnam.md | 23 +++++++++++++++++++++++ src/config.rs | 37 +++++++++++++++++++++++++++++-------- subplot/client.py | 9 +++++++++ subplot/client.yaml | 3 +++ 4 files changed, 64 insertions(+), 8 deletions(-) diff --git a/obnam.md b/obnam.md index e788d96..3050463 100644 --- a/obnam.md +++ b/obnam.md @@ -1122,6 +1122,29 @@ encrypt: false ~~~ +## Client expands tildes in its configuration file + +This scenario verifies that the client expands tildes in pathnames in +its configuration file. + + +~~~scenario +given an installed obnam +and file tilde.yaml +when I run obnam --config tilde.yaml config +then stdout contains home directory followed by /important +then stdout contains home directory followed by /obnam.log +~~~ + +~~~{#tilde.yaml .file .yaml .numberLines} +roots: [~/important] +log: ~/obnam.log +server_url: https://backup.example.com +verify_tls_cert: true +encrypt: false +~~~ + + ## Client requires https This scenario verifies that the client rejects a configuration with a diff --git a/src/config.rs b/src/config.rs index 6881959..b30cfa3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -91,21 +91,26 @@ impl ClientConfigWithoutPasswords { trace!("read_config: filename={:?}", filename); let config = std::fs::read_to_string(filename)?; let tentative: TentativeClientConfig = serde_yaml::from_str(&config)?; - + let roots = tentative + .roots + .iter() + .map(|path| expand_tilde(path)) + .collect(); + let log = tentative + .log + .map(|path| expand_tilde(&path)) + .unwrap_or_else(|| PathBuf::from(DEVNULL)); let encrypt = tentative.encrypt.or(Some(false)).unwrap(); let exclude_cache_tag_directories = tentative.exclude_cache_tag_directories.unwrap_or(true); let config = Self { + chunk_size: tentative.chunk_size.or(Some(DEFAULT_CHUNK_SIZE)).unwrap(), + encrypt, filename: filename.to_path_buf(), + roots, server_url: tentative.server_url, - roots: tentative.roots, verify_tls_cert: tentative.verify_tls_cert.or(Some(false)).unwrap(), - chunk_size: tentative.chunk_size.or(Some(DEFAULT_CHUNK_SIZE)).unwrap(), - log: tentative - .log - .or_else(|| Some(PathBuf::from(DEVNULL))) - .unwrap(), - encrypt, + log, exclude_cache_tag_directories, }; @@ -126,3 +131,19 @@ impl ClientConfigWithoutPasswords { Ok(()) } } + +fn expand_tilde(path: &Path) -> PathBuf { + if path.starts_with("~/") { + if let Some(home) = std::env::var_os("HOME") { + let mut expanded = PathBuf::from(home); + for comp in path.components().skip(1) { + expanded.push(comp); + } + expanded + } else { + path.to_path_buf() + } + } else { + path.to_path_buf() + } +} diff --git a/subplot/client.py b/subplot/client.py index 1ddc772..be0a6d6 100644 --- a/subplot/client.py +++ b/subplot/client.py @@ -102,3 +102,12 @@ def stdout_matches_file(ctx, filename=None): stdout = runcmd_get_stdout(ctx) data = open(filename).read() assert_eq(stdout, data) + + +def stdout_contains_home_dir_path(ctx, path=None): + runcmd_get_stdout = globals()["runcmd_get_stdout"] + stdout = runcmd_get_stdout(ctx) + wanted = os.path.abspath(os.path.normpath("./" + path)) + logging.debug(f"stdout_contains_home_dir_path: stdout={stdout!r}") + logging.debug(f"stdout_contains_home_dir_path: wanted={wanted!r}") + assert wanted in stdout diff --git a/subplot/client.yaml b/subplot/client.yaml index 8c76e9f..6de04c9 100644 --- a/subplot/client.yaml +++ b/subplot/client.yaml @@ -28,3 +28,6 @@ - then: "stdout matches file {filename}" function: stdout_matches_file + +- then: "stdout contains home directory followed by {path}" + function: stdout_contains_home_dir_path -- cgit v1.2.1