Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
toolchain: [beta, stable, 1.81.0]
toolchain: [beta, stable, 1.87.0]

name: Test on ${{ matrix.os }} with Rust ${{ matrix.toolchain }}
runs-on: ${{ matrix.os }}
Expand Down
7 changes: 3 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@ name = "etcetera"
version = "0.10.0"
categories = ["config"]
documentation = "https://docs.rs/etcetera"
edition = "2021"
edition = "2024"
homepage = "https://github.com/lunacookies/etcetera"
keywords = ["xdg", "dirs", "directories", "basedir", "path"]
license = "MIT OR Apache-2.0"
readme = "README.md"
repository = "https://github.com/lunacookies/etcetera"
rust-version = "1.70.0"
rust-version = "1.87.0"
description = "An unopinionated library for obtaining configuration, data, cache, & other directories"

[dependencies]
cfg-if = "1"
home = "0.5"

# We should keep this in sync with the `home` crate.
[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.59", features = ["Win32_Foundation", "Win32_System_Com", "Win32_UI_Shell"] }
windows-sys = { version = "0.61", features = ["Win32_Foundation", "Win32_System_Com", "Win32_UI_Shell"] }
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ This is a Rust library that allows you to determine the locations of configurati
Existing Rust libraries generally do not give you a choice in terms of which standards/conventions they follow.
Etcetera, on the other hand, gives you the choice.

MSRV: 1.70.0 (You need to pin `home` dependency to <0.5.11, otherwise it is 1.81.0)
MSRV: 1.87.0

Note: The MSRV was raised to 1.87.0 in v0.11 to remove the dependency on the `home` crate & instead use the undeprecated `std::env::home_dir`.
If you want, you can use v0.9 with an MSRV of 1.70.0 or v0.10 with an MSRV of 1.81.0 instead.

## Conventions

Expand All @@ -35,7 +38,7 @@ Etcetera has 2 modes of operation: `BaseStrategy` & `AppStrategy`:
- Apple: `~/Library/Preferences/org.acme-corp.Frobnicator-Plus`
- Windows: `~\AppData\Roaming\Acme Corp\Frobnicator Plus`

Note: the location of the home (~) is determined by the [`home`](https://docs.rs/home/0.5.4/home/fn.home_dir.html) crate.
Note: the location of the home (~) is determined by [`std::env::home_dir`](https://doc.rust-lang.org/std/env/fn.home_dir.html).

### Convenience functions

Expand Down
5 changes: 5 additions & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
edition = "2024"
fn_params_layout = "Compressed"
style_edition = "2024"
use_field_init_shorthand = true
use_try_shorthand = true
2 changes: 1 addition & 1 deletion src/app_strategy/apple.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::base_strategy::BaseStrategy;
use crate::{base_strategy, HomeDirError};
use crate::{HomeDirError, base_strategy};
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 Down
6 changes: 5 additions & 1 deletion src/app_strategy/windows.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::base_strategy::BaseStrategy;
use crate::{base_strategy, HomeDirError};
use crate::{HomeDirError, base_strategy};
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 @@ -15,9 +15,11 @@ use std::path::{Path, PathBuf};
/// use std::path::Path;
///
/// // Remove the environment variables that the strategy reads from.
/// unsafe {
/// std::env::remove_var("USERPROFILE");
/// std::env::remove_var("APPDATA");
/// std::env::remove_var("LOCALAPPDATA");
/// }
///
/// let app_strategy = Windows::new(AppStrategyArgs {
/// top_level_domain: "org".to_string(),
Expand Down Expand Up @@ -77,9 +79,11 @@ use std::path::{Path, PathBuf};
/// "/my_cache_location/"
/// };
///
/// unsafe {
/// std::env::set_var("USERPROFILE", &home_path);
/// std::env::set_var("APPDATA", data_path);
/// std::env::set_var("LOCALAPPDATA", cache_path);
/// }
///
/// let app_strategy = Windows::new(AppStrategyArgs {
/// top_level_domain: "org".to_string(),
Expand Down
8 changes: 7 additions & 1 deletion src/app_strategy/xdg.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::base_strategy::BaseStrategy;
use crate::{base_strategy, HomeDirError};
use crate::{HomeDirError, base_strategy};
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 All @@ -13,11 +13,13 @@ use std::path::{Path, PathBuf};
/// use std::path::Path;
///
/// // Remove the environment variables that the strategy reads from.
/// unsafe {
/// std::env::remove_var("XDG_CONFIG_HOME");
/// 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: "org".to_string(),
Expand Down Expand Up @@ -88,11 +90,13 @@ use std::path::{Path, PathBuf};
/// "/my_runtime_location/"
/// };
///
/// unsafe {
/// 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: "org".to_string(),
Expand Down Expand Up @@ -131,11 +135,13 @@ use std::path::{Path, PathBuf};
/// use std::path::Path;
///
/// // Remove the environment variables that the strategy reads from.
/// unsafe {
/// std::env::set_var("XDG_CONFIG_HOME", "relative_path/");
/// 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: "org".to_string(),
Expand Down
10 changes: 7 additions & 3 deletions src/base_strategy/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ use crate::HomeDirError;
/// use std::path::Path;
///
/// // Remove the environment variables that the strategy reads from.
/// unsafe {
/// std::env::remove_var("USERPROFILE");
/// std::env::remove_var("APPDATA");
/// std::env::remove_var("LOCALAPPDATA");
/// }
///
/// let base_strategy = Windows::new().unwrap();
///
Expand Down Expand Up @@ -71,9 +73,11 @@ use crate::HomeDirError;
/// "/baz/"
/// };
///
/// unsafe {
/// std::env::set_var("USERPROFILE", &home_path);
/// std::env::set_var("APPDATA", data_path);
/// std::env::set_var("LOCALAPPDATA", cache_path);
/// }
///
/// let base_strategy = Windows::new().unwrap();
///
Expand Down Expand Up @@ -135,11 +139,11 @@ impl Windows {
use windows_sys::Win32::Foundation::S_OK;
use windows_sys::Win32::System::Com::CoTaskMemFree;
use windows_sys::Win32::UI::Shell::{
FOLDERID_LocalAppData, FOLDERID_RoamingAppData, SHGetKnownFolderPath,
KF_FLAG_DONT_VERIFY,
FOLDERID_LocalAppData, FOLDERID_RoamingAppData, KF_FLAG_DONT_VERIFY,
SHGetKnownFolderPath,
};

extern "C" {
unsafe extern "C" {
fn wcslen(buf: *const u16) -> usize;
}

Expand Down
12 changes: 7 additions & 5 deletions src/base_strategy/xdg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ use crate::HomeDirError;
/// use std::path::Path;
///
/// // Remove the environment variables that the strategy reads from.
/// unsafe {
/// std::env::remove_var("XDG_CONFIG_HOME");
/// 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 Down Expand Up @@ -83,11 +85,13 @@ use crate::HomeDirError;
/// "/qux/"
/// };
///
/// unsafe {
/// 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();
///
Expand Down Expand Up @@ -121,11 +125,13 @@ use crate::HomeDirError;
/// use std::path::Path;
///
/// // Remove the environment variables that the strategy reads from.
/// unsafe {
/// std::env::set_var("XDG_CONFIG_HOME", "foo/");
/// 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 Down Expand Up @@ -171,11 +177,7 @@ impl Xdg {
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
}
if path.is_absolute() { Some(path) } else { None }
})
}

Expand Down
8 changes: 4 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,12 @@
pub mod app_strategy;
pub mod base_strategy;

pub use app_strategy::{choose_app_strategy, AppStrategy, AppStrategyArgs};
pub use base_strategy::{choose_base_strategy, BaseStrategy};
pub use app_strategy::{AppStrategy, AppStrategyArgs, choose_app_strategy};
pub use base_strategy::{BaseStrategy, choose_base_strategy};

/// A convenience function that wraps the [`home_dir`](https://docs.rs/home/0.5.4/home/fn.home_dir.html) function from the [home](https://docs.rs/home) crate.
/// A convenience function that wraps the [`home_dir`](https://doc.rust-lang.org/std/env/fn.home_dir.html) function from the standard library.
pub fn home_dir() -> Result<std::path::PathBuf, HomeDirError> {
home::home_dir().ok_or(HomeDirError)
std::env::home_dir().ok_or(HomeDirError)
}

/// This error occurs when the home directory cannot be located.
Expand Down