Skip to content

Commit

Permalink
Support runtime directory (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
utkarshgupta137 committed Apr 15, 2023
1 parent f5b253e commit 139aed6
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 13 deletions.
4 changes: 4 additions & 0 deletions src/app_strategy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ pub trait AppStrategy: Sized {
/// State directory may not to exist for all platforms.
fn state_dir(&self) -> Option<PathBuf>;

/// Gets the runtime directory for your application.
/// Runtime directory may not to exist for all platforms.
fn runtime_dir(&self) -> Option<PathBuf>;

/// Constructs a path inside your application’s configuration directory to which a path of your choice has been appended.
fn in_config_dir<P: AsRef<OsStr>>(&self, path: P) -> PathBuf {
in_dir_method!(self, path, config_dir)
Expand Down
8 changes: 8 additions & 0 deletions src/app_strategy/apple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ use std::path::PathBuf;
/// app_strategy.state_dir(),
/// None
/// );
/// assert_eq!(
/// app_strategy.runtime_dir(),
/// None
/// );
/// ```
#[derive(Debug)]
pub struct Apple {
Expand Down Expand Up @@ -66,4 +70,8 @@ impl super::AppStrategy for Apple {
fn state_dir(&self) -> Option<PathBuf> {
None
}

fn runtime_dir(&self) -> Option<PathBuf> {
None
}
}
8 changes: 8 additions & 0 deletions src/app_strategy/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ use std::path::PathBuf;
/// app_strategy.state_dir().unwrap().strip_prefix(&home_dir),
/// Ok(Path::new(".vim/state/")
/// ));
/// assert_eq!(
/// app_strategy.runtime_dir().unwrap().strip_prefix(&home_dir),
/// Ok(Path::new(".vim/runtime/")
/// ));
/// ```
#[derive(Debug)]
pub struct Unix {
Expand Down Expand Up @@ -64,4 +68,8 @@ impl super::AppStrategy for Unix {
fn state_dir(&self) -> Option<PathBuf> {
Some(self.root_dir.join("state/"))
}

fn runtime_dir(&self) -> Option<PathBuf> {
Some(self.root_dir.join("runtime/"))
}
}
8 changes: 8 additions & 0 deletions src/app_strategy/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ use std::path::PathBuf;
/// app_strategy.state_dir(),
/// None
/// );
/// assert_eq!(
/// app_strategy.runtime_dir(),
/// None
/// );
/// ```
#[derive(Debug)]
pub struct Windows {
Expand Down Expand Up @@ -76,4 +80,8 @@ impl super::AppStrategy for Windows {
fn state_dir(&self) -> Option<PathBuf> {
None
}

fn runtime_dir(&self) -> Option<PathBuf> {
None
}
}
23 changes: 23 additions & 0 deletions src/app_strategy/xdg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::path::PathBuf;
/// std::env::remove_var("XDG_DATA_HOME");
/// std::env::remove_var("XDG_CACHE_HOME");
/// std::env::remove_var("XDG_STATE_HOME");
/// std::env::remove_var("XDG_RUNTIME_DIR");
///
/// let app_strategy = Xdg::new(AppStrategyArgs {
/// top_level_domain: "hm".to_string(),
Expand All @@ -42,6 +43,10 @@ use std::path::PathBuf;
/// app_strategy.state_dir().unwrap().strip_prefix(&home_dir),
/// Ok(Path::new(".local/state/htop/")
/// ));
/// assert_eq!(
/// app_strategy.runtime_dir(),
/// None
/// );
/// ```
///
/// This next example gives the environment variables values:
Expand Down Expand Up @@ -73,11 +78,17 @@ use std::path::PathBuf;
/// } else {
/// "/my_state_location/"
/// };
/// let runtime_path = if cfg!(windows) {
/// "C:\\my_runtime_location\\"
/// } else {
/// "/my_runtime_location/"
/// };
///
/// std::env::set_var("XDG_CONFIG_HOME", config_path);
/// std::env::set_var("XDG_DATA_HOME", data_path);
/// std::env::set_var("XDG_CACHE_HOME", cache_path);
/// std::env::set_var("XDG_STATE_HOME", state_path);
/// std::env::set_var("XDG_RUNTIME_DIR", runtime_path);
///
/// let app_strategy = Xdg::new(AppStrategyArgs {
/// top_level_domain: "hm".to_string(),
Expand All @@ -89,6 +100,7 @@ use std::path::PathBuf;
/// assert_eq!(app_strategy.data_dir(), Path::new(&format!("{}/htop/", data_path)));
/// assert_eq!(app_strategy.cache_dir(), Path::new(&format!("{}/htop/", cache_path)));
/// assert_eq!(app_strategy.state_dir().unwrap(), Path::new(&format!("{}/htop/", state_path)));
/// assert_eq!(app_strategy.runtime_dir().unwrap(), Path::new(&format!("{}/htop/", runtime_path)));
/// ```
///
/// The XDG spec requires that when the environment variables’ values are not absolute paths, their values should be ignored. This example exemplifies this behaviour:
Expand All @@ -104,6 +116,7 @@ use std::path::PathBuf;
/// std::env::set_var("XDG_DATA_HOME", "./another_one/");
/// std::env::set_var("XDG_CACHE_HOME", "yet_another/");
/// std::env::set_var("XDG_STATE_HOME", "./and_another");
/// std::env::set_var("XDG_RUNTIME_DIR", "relative_path/");
///
/// let app_strategy = Xdg::new(AppStrategyArgs {
/// top_level_domain: "hm".to_string(),
Expand All @@ -130,6 +143,10 @@ use std::path::PathBuf;
/// app_strategy.state_dir().unwrap().strip_prefix(&home_dir),
/// Ok(Path::new(".local/state/htop/")
/// ));
/// assert_eq!(
/// app_strategy.runtime_dir(),
/// None
/// );
/// ```
#[derive(Debug)]
pub struct Xdg {
Expand Down Expand Up @@ -167,4 +184,10 @@ impl super::AppStrategy for Xdg {
.join(&self.unixy_name),
)
}

fn runtime_dir(&self) -> Option<PathBuf> {
self.base_strategy
.runtime_dir()
.map(|runtime_dir| runtime_dir.join(&self.unixy_name))
}
}
4 changes: 4 additions & 0 deletions src/base_strategy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ pub trait BaseStrategy: Sized {
/// Gets the user’s state directory.
/// State directory may not exist for all platforms.
fn state_dir(&self) -> Option<PathBuf>;

/// Gets the user’s runtime directory.
/// Runtime directory may not exist for all platforms.
fn runtime_dir(&self) -> Option<PathBuf>;
}

macro_rules! create_choose_base_strategy {
Expand Down
8 changes: 8 additions & 0 deletions src/base_strategy/apple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ use std::path::PathBuf;
/// base_strategy.state_dir(),
/// None
/// );
/// assert_eq!(
/// base_strategy.runtime_dir(),
/// None
/// );
/// ```
#[derive(Debug)]
pub struct Apple {
Expand Down Expand Up @@ -58,4 +62,8 @@ impl super::BaseStrategy for Apple {
fn state_dir(&self) -> Option<PathBuf> {
None
}

fn runtime_dir(&self) -> Option<PathBuf> {
None
}
}
8 changes: 8 additions & 0 deletions src/base_strategy/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ use std::path::PathBuf;
/// base_strategy.state_dir(),
/// None
/// );
/// assert_eq!(
/// base_strategy.runtime_dir(),
/// None
/// );
/// ```
#[derive(Debug)]
pub struct Windows {
Expand Down Expand Up @@ -57,4 +61,8 @@ impl super::BaseStrategy for Windows {
fn state_dir(&self) -> Option<PathBuf> {
None
}

fn runtime_dir(&self) -> Option<PathBuf> {
None
}
}
48 changes: 35 additions & 13 deletions src/base_strategy/xdg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use std::path::PathBuf;
/// std::env::remove_var("XDG_DATA_HOME");
/// std::env::remove_var("XDG_CACHE_HOME");
/// std::env::remove_var("XDG_STATE_HOME");
/// std::env::remove_var("XDG_RUNTIME_DIR");
///
/// let base_strategy = Xdg::new().unwrap();
///
Expand All @@ -35,6 +36,10 @@ use std::path::PathBuf;
/// base_strategy.state_dir().unwrap().strip_prefix(&home_dir),
/// Ok(Path::new(".local/state")
/// ));
/// assert_eq!(
/// base_strategy.runtime_dir(),
/// None
/// );
/// ```
///
/// And here is another example with the environment variables set to demonstrate that the strategy really does read them:
Expand Down Expand Up @@ -65,18 +70,25 @@ use std::path::PathBuf;
/// } else {
/// "/foobar/"
/// };
/// let runtime_path = if cfg!(windows) {
/// "C:\\qux\\"
/// } else {
/// "/qux/"
/// };
///
/// std::env::set_var("XDG_CONFIG_HOME", config_path);
/// std::env::set_var("XDG_DATA_HOME", data_path);
/// std::env::set_var("XDG_CACHE_HOME", cache_path);
/// std::env::set_var("XDG_STATE_HOME", state_path);
/// std::env::set_var("XDG_RUNTIME_DIR", runtime_path);
///
/// let base_strategy = Xdg::new().unwrap();
///
/// assert_eq!(base_strategy.config_dir(), Path::new(config_path));
/// assert_eq!(base_strategy.data_dir(), Path::new(data_path));
/// assert_eq!(base_strategy.cache_dir(), Path::new(cache_path));
/// assert_eq!(base_strategy.state_dir().unwrap(), Path::new(state_path));
/// assert_eq!(base_strategy.runtime_dir().unwrap(), Path::new(runtime_path));
/// ```
///
/// The specification states that:
Expand All @@ -94,6 +106,7 @@ use std::path::PathBuf;
/// std::env::set_var("XDG_DATA_HOME", "bar/");
/// std::env::set_var("XDG_CACHE_HOME", "baz/");
/// std::env::set_var("XDG_STATE_HOME", "foobar/");
/// std::env::set_var("XDG_RUNTIME_DIR", "qux/");
///
/// let base_strategy = Xdg::new().unwrap();
///
Expand All @@ -115,27 +128,32 @@ use std::path::PathBuf;
/// base_strategy.state_dir().unwrap().strip_prefix(&home_dir),
/// Ok(Path::new(".local/state/")
/// ));
/// assert_eq!(
/// base_strategy.runtime_dir(),
/// None
/// );
/// ```
#[derive(Debug)]
pub struct Xdg {
home_dir: PathBuf,
}

impl Xdg {
fn env_var_or_default(&self, env_var: &str, default: impl AsRef<Path>) -> PathBuf {
std::env::var(env_var)
.ok()
.and_then(|path| {
let path = PathBuf::from(path);
fn env_var_or_none(env_var: &str) -> Option<PathBuf> {
std::env::var(env_var).ok().and_then(|path| {
let path = PathBuf::from(path);

// Return None if the path obtained from the environment variable isn’t absolute.
if path.is_absolute() {
Some(path)
} else {
None
}
})
.unwrap_or_else(|| self.home_dir.join(default))
// Return None if the path obtained from the environment variable isn’t absolute.
if path.is_absolute() {
Some(path)
} else {
None
}
})
}

fn env_var_or_default(&self, env_var: &str, default: impl AsRef<Path>) -> PathBuf {
Self::env_var_or_none(env_var).unwrap_or_else(|| self.home_dir.join(default))
}
}

Expand Down Expand Up @@ -163,4 +181,8 @@ impl super::BaseStrategy for Xdg {
fn state_dir(&self) -> Option<PathBuf> {
Some(self.env_var_or_default("XDG_STATE_HOME", ".local/state/"))
}

fn runtime_dir(&self) -> Option<PathBuf> {
Self::env_var_or_none("XDG_RUNTIME_DIR")
}
}

0 comments on commit 139aed6

Please sign in to comment.