Skip to content

Commit

Permalink
Add home_dir function
Browse files Browse the repository at this point in the history
  • Loading branch information
utkarshgupta137 committed Apr 22, 2023
1 parent babe10e commit 7664806
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 28 deletions.
3 changes: 3 additions & 0 deletions src/app_strategy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ pub trait AppStrategy: Sized {
/// The constructor requires access to some basic information about your application.
fn new(args: AppStrategyArgs) -> Result<Self, Self::CreationError>;

/// Gets the home directory of the current user.
fn home_dir(&self) -> &Path;

/// Gets the configuration directory for your application.
fn config_dir(&self) -> PathBuf;

Expand Down
10 changes: 9 additions & 1 deletion src/app_strategy/apple.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::base_strategy;
use crate::base_strategy::BaseStrategy;
use std::path::PathBuf;
use std::path::{Path, PathBuf};

/// This is the strategy created by Apple for use on macOS and iOS devices. It is always used by GUI apps on macOS, and is sometimes used by command-line applications there too. iOS only has GUIs, so all iOS applications follow this strategy. The specification is available [here](https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW1).
///
Expand All @@ -19,6 +19,10 @@ use std::path::PathBuf;
/// let home_dir = etcetera::home_dir().unwrap();
///
/// assert_eq!(
/// app_strategy.home_dir(),
/// &home_dir
/// );
/// assert_eq!(
/// app_strategy.config_dir().strip_prefix(&home_dir),
/// Ok(Path::new("Library/Preferences/org.acmecorp.FrobnicatorPlus/"))
/// );
Expand Down Expand Up @@ -55,6 +59,10 @@ impl super::AppStrategy for Apple {
})
}

fn home_dir(&self) -> &Path {
self.base_strategy.home_dir()
}

fn config_dir(&self) -> PathBuf {
self.base_strategy.config_dir().join(&self.bundle_id)
}
Expand Down
29 changes: 19 additions & 10 deletions src/app_strategy/unix.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::path::PathBuf;
use std::path::{Path, PathBuf};

/// This strategy has no standard or official specification. It has arisen over time through hundreds of Unixy tools. Vim and Cargo are notable examples whose configuration/data/cache directory layouts are similar to those created by this strategy.
///
Expand All @@ -17,6 +17,10 @@ use std::path::PathBuf;
/// let home_dir = etcetera::home_dir().unwrap();
///
/// assert_eq!(
/// app_strategy.home_dir(),
/// &home_dir
/// );
/// assert_eq!(
/// app_strategy.config_dir().strip_prefix(&home_dir),
/// Ok(Path::new(".frobnicator-plus/"))
/// );
Expand All @@ -40,36 +44,41 @@ use std::path::PathBuf;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Unix {
// This is `.frobnicator-plus` in the above example.
root_dir: PathBuf,
home_dir: PathBuf,
unixy_name: String,
}

impl super::AppStrategy for Unix {
type CreationError = crate::HomeDirError;

fn new(args: super::AppStrategyArgs) -> Result<Self, Self::CreationError> {
let mut root_dir = crate::home_dir()?;
root_dir.push(format!(".{}", args.unixy_name()));
Ok(Self {
home_dir: crate::home_dir()?,
unixy_name: format!(".{}", args.unixy_name()),
})
}

Ok(Self { root_dir })
fn home_dir(&self) -> &Path {
&self.home_dir
}

fn config_dir(&self) -> PathBuf {
self.root_dir.clone()
self.home_dir.join(&self.unixy_name)
}

fn data_dir(&self) -> PathBuf {
self.root_dir.join("data/")
self.home_dir.join(&self.unixy_name).join("data/")
}

fn cache_dir(&self) -> PathBuf {
self.root_dir.join("cache/")
self.home_dir.join(&self.unixy_name).join("cache/")
}

fn state_dir(&self) -> Option<PathBuf> {
Some(self.root_dir.join("state/"))
Some(self.home_dir.join(&self.unixy_name).join("state/"))
}

fn runtime_dir(&self) -> Option<PathBuf> {
Some(self.root_dir.join("runtime/"))
Some(self.home_dir.join(&self.unixy_name).join("runtime/"))
}
}
10 changes: 9 additions & 1 deletion src/app_strategy/windows.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::base_strategy;
use crate::base_strategy::BaseStrategy;
use std::path::PathBuf;
use std::path::{Path, PathBuf};

/// This strategy follows Windows’ conventions. It seems that all Windows GUI apps, and some command-line ones follow this pattern. The specification is available [here](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
///
Expand All @@ -19,6 +19,10 @@ use std::path::PathBuf;
/// let home_dir = etcetera::home_dir().unwrap();
///
/// assert_eq!(
/// app_strategy.home_dir(),
/// &home_dir
/// );
/// assert_eq!(
/// app_strategy.config_dir().strip_prefix(&home_dir),
/// Ok(Path::new("AppData/Roaming/Acme Corp/Frobnicator Plus/config"))
/// );
Expand Down Expand Up @@ -65,6 +69,10 @@ impl super::AppStrategy for Windows {
})
}

fn home_dir(&self) -> &Path {
self.base_strategy.home_dir()
}

fn config_dir(&self) -> PathBuf {
dir_method!(self, config_dir, "config/")
}
Expand Down
10 changes: 9 additions & 1 deletion src/app_strategy/xdg.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::base_strategy;
use crate::base_strategy::BaseStrategy;
use std::path::PathBuf;
use std::path::{Path, PathBuf};

/// This strategy implements the [XDG Base Directories Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html). It is the most common on Linux, but is increasingly being adopted elsewhere.
///
Expand Down Expand Up @@ -28,6 +28,10 @@ use std::path::PathBuf;
/// let home_dir = etcetera::home_dir().unwrap();
///
/// assert_eq!(
/// app_strategy.home_dir(),
/// &home_dir
/// );
/// assert_eq!(
/// app_strategy.config_dir().strip_prefix(&home_dir),
/// Ok(Path::new(".config/frobnicator-plus/"))
/// );
Expand Down Expand Up @@ -179,6 +183,10 @@ impl super::AppStrategy for Xdg {
})
}

fn home_dir(&self) -> &Path {
self.base_strategy.home_dir()
}

fn config_dir(&self) -> PathBuf {
self.base_strategy.config_dir().join(&self.unixy_name)
}
Expand Down
5 changes: 4 additions & 1 deletion src/base_strategy.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! These strategies simply provide the user’s configuration, data, and cache directories, without knowing about the application specifically.

use std::path::PathBuf;
use std::path::{Path, PathBuf};

/// Provides configuration, data, and cache directories of the current user.
pub trait BaseStrategy: Sized {
Expand All @@ -10,6 +10,9 @@ pub trait BaseStrategy: Sized {
/// Base strategies are constructed without knowledge of the application.
fn new() -> Result<Self, Self::CreationError>;

/// Gets the home directory of the current user.
fn home_dir(&self) -> &Path;

/// Gets the user’s configuration directory.
fn config_dir(&self) -> PathBuf;

Expand Down
23 changes: 15 additions & 8 deletions src/base_strategy/apple.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::path::PathBuf;
use std::path::{Path, PathBuf};

/// This is the strategy created by Apple for use on macOS and iOS devices. It is always used by GUI apps on macOS, and is sometimes used by command-line applications there too. iOS only has GUIs, so all iOS applications follow this strategy. The specification is available [here](https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW1).
///
Expand All @@ -12,6 +12,10 @@ use std::path::PathBuf;
/// let home_dir = etcetera::home_dir().unwrap();
///
/// assert_eq!(
/// base_strategy.home_dir(),
/// &home_dir
/// );
/// assert_eq!(
/// base_strategy.config_dir().strip_prefix(&home_dir),
/// Ok(Path::new("Library/Preferences/"))
/// );
Expand All @@ -34,29 +38,32 @@ use std::path::PathBuf;
/// ```
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Apple {
library_path: PathBuf,
home_dir: PathBuf,
}

impl super::BaseStrategy for Apple {
type CreationError = crate::HomeDirError;

fn new() -> Result<Self, Self::CreationError> {
let mut library_path = crate::home_dir()?;
library_path.push("Library/");
Ok(Self {
home_dir: crate::home_dir()?,
})
}

Ok(Self { library_path })
fn home_dir(&self) -> &Path {
&self.home_dir
}

fn config_dir(&self) -> PathBuf {
self.library_path.join("Preferences/")
self.home_dir.join("Library/Preferences/")
}

fn data_dir(&self) -> PathBuf {
self.library_path.join("Application Support/")
self.home_dir.join("Library/Application Support/")
}

fn cache_dir(&self) -> PathBuf {
self.library_path.join("Caches/")
self.home_dir.join("Library/Caches/")
}

fn state_dir(&self) -> Option<PathBuf> {
Expand Down
20 changes: 14 additions & 6 deletions src/base_strategy/windows.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::path::PathBuf;
use std::path::{Path, PathBuf};

/// This strategy follows Windows’ conventions. It seems that all Windows GUI apps, and some command-line ones follow this pattern. The specification is available [here](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
///
Expand All @@ -12,6 +12,10 @@ use std::path::PathBuf;
/// let home_dir = etcetera::home_dir().unwrap();
///
/// assert_eq!(
/// base_strategy.home_dir(),
/// &home_dir
/// );
/// assert_eq!(
/// base_strategy.config_dir().strip_prefix(&home_dir),
/// Ok(Path::new("AppData/Roaming/"))
/// );
Expand All @@ -34,28 +38,32 @@ use std::path::PathBuf;
/// ```
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Windows {
appdata: PathBuf,
home_dir: PathBuf,
}

impl super::BaseStrategy for Windows {
type CreationError = crate::HomeDirError;

fn new() -> Result<Self, Self::CreationError> {
Ok(Self {
appdata: crate::home_dir()?.join("AppData/"),
home_dir: crate::home_dir()?,
})
}

fn home_dir(&self) -> &Path {
&self.home_dir
}

fn config_dir(&self) -> PathBuf {
self.appdata.join("Roaming/")
self.home_dir.join("AppData/Roaming/")
}

fn data_dir(&self) -> PathBuf {
self.appdata.join("Roaming/")
self.home_dir.join("AppData/Roaming/")
}

fn cache_dir(&self) -> PathBuf {
self.appdata.join("Local/")
self.home_dir.join("AppData/Local/")
}

fn state_dir(&self) -> Option<PathBuf> {
Expand Down
16 changes: 16 additions & 0 deletions src/base_strategy/xdg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ use std::path::PathBuf;
/// let home_dir = etcetera::home_dir().unwrap();
///
/// assert_eq!(
/// base_strategy.home_dir(),
/// &home_dir
/// );
/// assert_eq!(
/// base_strategy.config_dir().strip_prefix(&home_dir),
/// Ok(Path::new(".config/"))
/// );
Expand Down Expand Up @@ -86,6 +90,10 @@ use std::path::PathBuf;
/// let base_strategy = Xdg::new().unwrap();
///
/// assert_eq!(
/// base_strategy.home_dir(),
/// etcetera::home_dir().unwrap()
/// );
/// assert_eq!(
/// base_strategy.config_dir(),
/// Path::new(config_path)
/// );
Expand Down Expand Up @@ -127,6 +135,10 @@ use std::path::PathBuf;
///
/// // We still get the default values.
/// assert_eq!(
/// base_strategy.home_dir(),
/// &home_dir
/// );
/// assert_eq!(
/// base_strategy.config_dir().strip_prefix(&home_dir),
/// Ok(Path::new(".config/"))
/// );
Expand Down Expand Up @@ -180,6 +192,10 @@ impl super::BaseStrategy for Xdg {
})
}

fn home_dir(&self) -> &Path {
&self.home_dir
}

fn config_dir(&self) -> PathBuf {
self.env_var_or_default("XDG_CONFIG_HOME", ".config/")
}
Expand Down

0 comments on commit 7664806

Please sign in to comment.