From ef036c3224f1d3b94db0b52db4d38e47fd395d88 Mon Sep 17 00:00:00 2001 From: Ulrich Kautz Date: Fri, 11 Feb 2022 17:12:23 +0000 Subject: [PATCH 1/2] Allow compile time default paths for cheats and config This CL makes it easier to install navi on multi-tenant Linux systems, by allowing to provide pre-install cheatsheets in shared folders (and potentially pre-installed config in shared folders). This does not break or change the existing behaviour. The shared directory / config file is only used if - There is not already a directory / config file in the user XDG location - Navi is compiled with NAVI_CONFIG_FILE and/or NAVI_CHEATS_DIRECTORY env var set - The paths defined in above env vars exist --- .github/workflows/ci.yml | 14 ++++++++++ src/filesystem.rs | 59 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6251041..c1dcef1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,6 +43,20 @@ jobs: toolchain: stable override: true + - name: Prep environment to test compiled-in paths + run: | + mkdir /tmp/cheats-dir + touch /tmp/config-file + + - name: Run cargo test (with compiled-in paths) + uses: actions-rs/cargo@v1 + continue-on-error: false + env: + NAVI_CHEATS_DIRECTORY: /tmp/cheats-dir + NAVI_CONFIG_FILE: /tmp/config-file + with: + command: test + - name: Run cargo test uses: actions-rs/cargo@v1 continue-on-error: false diff --git a/src/filesystem.rs b/src/filesystem.rs index de669d8..407942d 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -26,12 +26,30 @@ fn paths_from_path_param(env_var: &str) -> impl Iterator { env_var.split(':').filter(|folder| folder != &"") } +fn compiled_default_path(path: Option<&str>) -> Option { + match path { + Some(path) => { + let path = Path::new(path); + if path.exists() { + Some(path.to_path_buf()) + } else { + None + } + } + None => None, + } +} + pub fn default_cheat_pathbuf() -> Result { let base_dirs = BaseDirs::new().ok_or_else(|| anyhow!("Unable to get base dirs"))?; - let mut pathbuf = PathBuf::from(base_dirs.data_dir()); pathbuf.push("navi"); pathbuf.push("cheats"); + if !pathbuf.exists() { + if let Some(path) = compiled_default_path(option_env!("NAVI_CHEATS_DIRECTORY")) { + pathbuf = path; + } + } Ok(pathbuf) } @@ -41,6 +59,11 @@ pub fn default_config_pathbuf() -> Result { let mut pathbuf = PathBuf::from(base_dirs.config_dir()); pathbuf.push("navi"); pathbuf.push("config.yaml"); + if !pathbuf.exists() { + if let Some(path) = compiled_default_path(option_env!("NAVI_CONFIG_FILE")) { + pathbuf = path; + } + } Ok(pathbuf) } @@ -247,4 +270,38 @@ mod tests { assert_eq!(found, expected) } } + + #[test] + fn test_default_config_pathbuf() { + let base_dirs = BaseDirs::new() + .ok_or(anyhow!("bad")) + .expect("could not determine base directories"); + let mut expect = base_dirs.config_dir().to_path_buf(); + expect.push("navi"); + expect.push("config.yaml"); + let expect = match option_env!("NAVI_CONFIG_FILE") { + Some(path) => path.to_string(), + None => expect.to_string_lossy().to_string(), + }; + let config = default_config_pathbuf().expect("could not find default config path"); + + assert_eq!(expect, config.to_string_lossy().to_string()) + } + + #[test] + fn test_default_cheat_pathbuf() { + let base_dirs = BaseDirs::new() + .ok_or(anyhow!("bad")) + .expect("could not determine base directories"); + let mut expect = base_dirs.data_dir().to_path_buf(); + expect.push("navi"); + expect.push("cheats"); + let expect = match option_env!("NAVI_CHEATS_DIRECTORY") { + Some(path) => path.to_string(), + None => expect.to_string_lossy().to_string(), + }; + let cheats = default_cheat_pathbuf().expect("could not find default config path"); + + assert_eq!(expect, cheats.to_string_lossy().to_string()) + } } From 87f0ac0aeccc72e22dfce4afd5b94ecd7c2f26d7 Mon Sep 17 00:00:00 2001 From: Ulrich Kautz Date: Mon, 14 Feb 2022 13:51:46 +0000 Subject: [PATCH 2/2] Use already existing env var names --- .github/workflows/ci.yml | 4 ++-- docs/installation.md | 7 +++++++ src/filesystem.rs | 15 ++++++++++----- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1dcef1..630d42f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,8 +52,8 @@ jobs: uses: actions-rs/cargo@v1 continue-on-error: false env: - NAVI_CHEATS_DIRECTORY: /tmp/cheats-dir - NAVI_CONFIG_FILE: /tmp/config-file + NAVI_PATH: /tmp/cheats-dir + NAVI_CONFIG: /tmp/config-file with: command: test diff --git a/docs/installation.md b/docs/installation.md index b40f3f7..88032fb 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -65,6 +65,13 @@ make install # make BIN_DIR=/usr/local/bin install ``` +##### Compile time environment variables + +**navi** supports environment variables at compile time that modify the behavior of the binary at runtime: + +- `NAVI_PATH` (directory path value): If the `cheats` directory in the user's directory does not exist, **navi** uses this path (if it exists), as a fallback location to look for cheat files. Use case: system-wide installed, shared used cheatsheets folder. +- `NAVI_CONFIG` (file path value): If the `config.yaml` file in the user's directory does not exist, **navi** uses this path (if it exists), as a fallback location to look for a configuration file. Use case: system-wide installed, shared used configuration file. + #### Other package managers You can find **navi** for more package managers by clicking on the image below: diff --git a/src/filesystem.rs b/src/filesystem.rs index 407942d..85b8c62 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -9,7 +9,7 @@ use anyhow::Result; use directories_next::BaseDirs; use regex::Regex; use std::collections::HashSet; -use std::path::{Path, PathBuf}; +use std::path::{Path, PathBuf, MAIN_SEPARATOR}; use walkdir::WalkDir; pub fn all_cheat_files(path: &Path) -> Vec { @@ -29,6 +29,11 @@ fn paths_from_path_param(env_var: &str) -> impl Iterator { fn compiled_default_path(path: Option<&str>) -> Option { match path { Some(path) => { + let path = if path.contains(MAIN_SEPARATOR) { + path.split(MAIN_SEPARATOR).next().unwrap() + } else { + path + }; let path = Path::new(path); if path.exists() { Some(path.to_path_buf()) @@ -46,7 +51,7 @@ pub fn default_cheat_pathbuf() -> Result { pathbuf.push("navi"); pathbuf.push("cheats"); if !pathbuf.exists() { - if let Some(path) = compiled_default_path(option_env!("NAVI_CHEATS_DIRECTORY")) { + if let Some(path) = compiled_default_path(option_env!("NAVI_PATH")) { pathbuf = path; } } @@ -60,7 +65,7 @@ pub fn default_config_pathbuf() -> Result { pathbuf.push("navi"); pathbuf.push("config.yaml"); if !pathbuf.exists() { - if let Some(path) = compiled_default_path(option_env!("NAVI_CONFIG_FILE")) { + if let Some(path) = compiled_default_path(option_env!("NAVI_CONFIG")) { pathbuf = path; } } @@ -279,7 +284,7 @@ mod tests { let mut expect = base_dirs.config_dir().to_path_buf(); expect.push("navi"); expect.push("config.yaml"); - let expect = match option_env!("NAVI_CONFIG_FILE") { + let expect = match option_env!("NAVI_CONFIG") { Some(path) => path.to_string(), None => expect.to_string_lossy().to_string(), }; @@ -296,7 +301,7 @@ mod tests { let mut expect = base_dirs.data_dir().to_path_buf(); expect.push("navi"); expect.push("cheats"); - let expect = match option_env!("NAVI_CHEATS_DIRECTORY") { + let expect = match option_env!("NAVI_PATH") { Some(path) => path.to_string(), None => expect.to_string_lossy().to_string(), };