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"`
|
`requirement`, e.g., `">=0.1.0"`, returning `"true"` if so and `"false"`
|
||||||
otherwise.
|
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
|
### Recipe Attributes
|
||||||
|
|
||||||
Recipes may be annotated with attributes that change their behavior.
|
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 {
|
let function = match name {
|
||||||
"absolute_path" => Unary(absolute_path),
|
"absolute_path" => Unary(absolute_path),
|
||||||
"arch" => Nullary(arch),
|
"arch" => Nullary(arch),
|
||||||
|
"cache_directory" => Nullary(|_| dir("cache", dirs::cache_dir)),
|
||||||
"capitalize" => Unary(capitalize),
|
"capitalize" => Unary(capitalize),
|
||||||
"clean" => Unary(clean),
|
"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" => UnaryOpt(env),
|
||||||
"env_var" => Unary(env_var),
|
"env_var" => Unary(env_var),
|
||||||
"env_var_or_default" => Binary(env_var_or_default),
|
"env_var_or_default" => Binary(env_var_or_default),
|
||||||
"error" => Unary(error),
|
"error" => Unary(error),
|
||||||
|
"executable_directory" => Nullary(|_| dir("executable", dirs::executable_dir)),
|
||||||
"extension" => Unary(extension),
|
"extension" => Unary(extension),
|
||||||
"file_name" => Unary(file_name),
|
"file_name" => Unary(file_name),
|
||||||
"file_stem" => Unary(file_stem),
|
"file_stem" => Unary(file_stem),
|
||||||
|
"home_directory" => Nullary(|_| dir("home", dirs::home_dir)),
|
||||||
"invocation_directory" => Nullary(invocation_directory),
|
"invocation_directory" => Nullary(invocation_directory),
|
||||||
"invocation_directory_native" => Nullary(invocation_directory_native),
|
"invocation_directory_native" => Nullary(invocation_directory_native),
|
||||||
"join" => BinaryPlus(join),
|
"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())
|
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> {
|
fn env_var(context: &FunctionContext, key: &str) -> Result<String, String> {
|
||||||
use std::env::VarError::*;
|
use std::env::VarError::*;
|
||||||
|
|
||||||
@ -433,3 +456,23 @@ fn semver_matches(
|
|||||||
.to_string(),
|
.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 conditional;
|
||||||
mod confirm;
|
mod confirm;
|
||||||
mod delimiters;
|
mod delimiters;
|
||||||
|
mod directories;
|
||||||
mod dotenv;
|
mod dotenv;
|
||||||
mod edit;
|
mod edit;
|
||||||
mod equals;
|
mod equals;
|
||||||
|
Loading…
Reference in New Issue
Block a user