Add functions to return XDG base directories (#1822)
This commit is contained in:
parent
6d320f77af
commit
c2af5a1dd6
17
README.md
17
README.md
@ -1415,6 +1415,23 @@ which will halt execution.
|
||||
`requirement`, e.g., `">=0.1.0"`, returning `"true"` if so and `"false"`
|
||||
otherwise.
|
||||
|
||||
##### XDG Directories
|
||||
|
||||
These functions return paths to user-specific directories for things like
|
||||
configuration, data, caches, executables, and the user's home directory. These
|
||||
functions follow the
|
||||
[XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html),
|
||||
and are implemented with the
|
||||
[`dirs`](https://docs.rs/dirs/latest/dirs/index.html) crate.
|
||||
|
||||
- `cache_directory()` - The user-specific cache directory.
|
||||
- `config_directory()` - The user-specific configuration directory.
|
||||
- `config_local_directory()` - The local user-specific configuration directory.
|
||||
- `data_directory()` - The user-specific data directory.
|
||||
- `data_local_directory()` - The local user-specific data directory.
|
||||
- `executable_directory()` - The user-specific executable directory.
|
||||
- `home_directory()` - The user's home directory.
|
||||
|
||||
### Recipe Attributes
|
||||
|
||||
Recipes may be annotated with attributes that change their behavior.
|
||||
|
@ -21,15 +21,22 @@ pub(crate) fn get(name: &str) -> Option<Function> {
|
||||
let function = match name {
|
||||
"absolute_path" => Unary(absolute_path),
|
||||
"arch" => Nullary(arch),
|
||||
"cache_directory" => Nullary(|_| dir("cache", dirs::cache_dir)),
|
||||
"capitalize" => Unary(capitalize),
|
||||
"clean" => Unary(clean),
|
||||
"config_directory" => Nullary(|_| dir("config", dirs::config_dir)),
|
||||
"config_local_directory" => Nullary(|_| dir("local config", dirs::config_local_dir)),
|
||||
"data_directory" => Nullary(|_| dir("data", dirs::data_dir)),
|
||||
"data_local_directory" => Nullary(|_| dir("local data", dirs::data_local_dir)),
|
||||
"env" => UnaryOpt(env),
|
||||
"env_var" => Unary(env_var),
|
||||
"env_var_or_default" => Binary(env_var_or_default),
|
||||
"error" => Unary(error),
|
||||
"executable_directory" => Nullary(|_| dir("executable", dirs::executable_dir)),
|
||||
"extension" => Unary(extension),
|
||||
"file_name" => Unary(file_name),
|
||||
"file_stem" => Unary(file_stem),
|
||||
"home_directory" => Nullary(|_| dir("home", dirs::home_dir)),
|
||||
"invocation_directory" => Nullary(invocation_directory),
|
||||
"invocation_directory_native" => Nullary(invocation_directory_native),
|
||||
"join" => BinaryPlus(join),
|
||||
@ -114,6 +121,22 @@ fn clean(_context: &FunctionContext, path: &str) -> Result<String, String> {
|
||||
Ok(Path::new(path).lexiclean().to_str().unwrap().to_owned())
|
||||
}
|
||||
|
||||
fn dir(name: &'static str, f: fn() -> Option<PathBuf>) -> Result<String, String> {
|
||||
match f() {
|
||||
Some(path) => path
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.map(str::to_string)
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"unable to convert {name} directory path to string: {}",
|
||||
path.display(),
|
||||
)
|
||||
}),
|
||||
None => Err(format!("{name} directory not found")),
|
||||
}
|
||||
}
|
||||
|
||||
fn env_var(context: &FunctionContext, key: &str) -> Result<String, String> {
|
||||
use std::env::VarError::*;
|
||||
|
||||
@ -433,3 +456,23 @@ fn semver_matches(
|
||||
.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn dir_not_found() {
|
||||
assert_eq!(dir("foo", || None).unwrap_err(), "foo directory not found");
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn dir_not_unicode() {
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
assert_eq!(
|
||||
dir("foo", || Some(OsStr::from_bytes(b"\xe0\x80\x80").into())).unwrap_err(),
|
||||
"unable to convert foo directory path to string: <20><><EFBFBD>",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
85
tests/directories.rs
Normal file
85
tests/directories.rs
Normal file
@ -0,0 +1,85 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn cache_directory() {
|
||||
Test::new()
|
||||
.justfile("x := cache_directory()")
|
||||
.args(["--evaluate", "x"])
|
||||
.stdout(dirs::cache_dir().unwrap_or_default().to_string_lossy())
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn config_directory() {
|
||||
Test::new()
|
||||
.justfile("x := config_directory()")
|
||||
.args(["--evaluate", "x"])
|
||||
.stdout(dirs::config_dir().unwrap_or_default().to_string_lossy())
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn config_local_directory() {
|
||||
Test::new()
|
||||
.justfile("x := config_local_directory()")
|
||||
.args(["--evaluate", "x"])
|
||||
.stdout(
|
||||
dirs::config_local_dir()
|
||||
.unwrap_or_default()
|
||||
.to_string_lossy(),
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn data_directory() {
|
||||
Test::new()
|
||||
.justfile("x := data_directory()")
|
||||
.args(["--evaluate", "x"])
|
||||
.stdout(dirs::data_dir().unwrap_or_default().to_string_lossy())
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn data_local_directory() {
|
||||
Test::new()
|
||||
.justfile("x := data_local_directory()")
|
||||
.args(["--evaluate", "x"])
|
||||
.stdout(dirs::data_local_dir().unwrap_or_default().to_string_lossy())
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn executable_directory() {
|
||||
if let Some(executable_dir) = dirs::executable_dir() {
|
||||
Test::new()
|
||||
.justfile("x := executable_directory()")
|
||||
.args(["--evaluate", "x"])
|
||||
.stdout(executable_dir.to_string_lossy())
|
||||
.run();
|
||||
} else {
|
||||
Test::new()
|
||||
.justfile("x := executable_directory()")
|
||||
.args(["--evaluate", "x"])
|
||||
.stderr(
|
||||
"
|
||||
error: Call to function `executable_directory` failed: executable directory not found
|
||||
——▶ justfile:1:6
|
||||
│
|
||||
1 │ x := executable_directory()
|
||||
│ ^^^^^^^^^^^^^^^^^^^^
|
||||
",
|
||||
)
|
||||
.status(EXIT_FAILURE)
|
||||
.run();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn home_directory() {
|
||||
Test::new()
|
||||
.justfile("x := home_directory()")
|
||||
.args(["--evaluate", "x"])
|
||||
.stdout(dirs::home_dir().unwrap_or_default().to_string_lossy())
|
||||
.run();
|
||||
}
|
@ -44,6 +44,7 @@ mod completions;
|
||||
mod conditional;
|
||||
mod confirm;
|
||||
mod delimiters;
|
||||
mod directories;
|
||||
mod dotenv;
|
||||
mod edit;
|
||||
mod equals;
|
||||
|
Loading…
Reference in New Issue
Block a user