From 7bf094a5521a622bb8162ca32b7ac8c22b591371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=A4iv=C3=A4rinta?= Date: Mon, 29 Dec 2025 23:59:37 +0100 Subject: [PATCH] cap-directories: Support XDG_STATE_HOME --- README.md | 2 +- cap-directories/Cargo.toml | 2 +- cap-directories/README.md | 4 ++-- cap-directories/src/project_dirs.rs | 31 +++++++++++++++++++---------- cap-directories/src/user_dirs.rs | 30 ++++++++++++++-------------- 5 files changed, 40 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index ebaee5f4..b426cff1 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Linux. [`cap-rand`]: https://github.com/bytecodealliance/cap-std/blob/main/cap-rand/README.md [`cap-net-ext`]: https://github.com/bytecodealliance/cap-std/blob/main/cap-net-ext/README.md [`cap_std::fs`]: https://docs.rs/cap-std/latest/cap_std/fs/index.html -[standard application directories]: https://docs.rs/directories-next/ +[standard application directories]: https://docs.rs/directories/ [temporary directories]: https://docs.rs/tempfile/ [random number generators]: https://docs.rs/rand/ diff --git a/cap-directories/Cargo.toml b/cap-directories/Cargo.toml index bfaf05ac..2a37470b 100644 --- a/cap-directories/Cargo.toml +++ b/cap-directories/Cargo.toml @@ -14,7 +14,7 @@ edition = "2021" [dependencies] cap-std = { path = "../cap-std", version = "^4.0.0" } -directories-next = "2.0.0" +directories = "6.0.0" [target.'cfg(not(windows))'.dependencies] rustix = { version = "1.0.0" } diff --git a/cap-directories/README.md b/cap-directories/README.md index 692fb8d0..74bb839d 100644 --- a/cap-directories/README.md +++ b/cap-directories/README.md @@ -13,8 +13,8 @@ The `cap-directories` crate provides utilities for accessing standard -directories via the [`directories-next`] crate, but which provide [`Dir`]s instead of +directories via the [`directories`] crate, but which provide [`Dir`]s instead of `Path`s. -[`directories-next`]: https://crates.io/crates/directories-next +[`directories`]: https://crates.io/crates/directories [`Dir`]: https://docs.rs/cap-std/latest/cap_std/fs/struct.Dir.html diff --git a/cap-directories/src/project_dirs.rs b/cap-directories/src/project_dirs.rs index 0c5ff6c1..9510428a 100644 --- a/cap-directories/src/project_dirs.rs +++ b/cap-directories/src/project_dirs.rs @@ -7,24 +7,24 @@ use std::{fs, io}; /// application, which are derived from the standard directories and the name /// of the project/organization. /// -/// This corresponds to [`directories_next::ProjectDirs`], except that the +/// This corresponds to [`directories::ProjectDirs`], except that the /// functions create the directories if they don't exist, open them, and return /// `Dir`s instead of returning `Path`s. /// -/// Unlike `directories_next::ProjectDirs`, this API has no +/// Unlike `directories::ProjectDirs`, this API has no /// `ProjectDirs::from_path`, `ProjectDirs::path` or /// `ProjectDirs::project_path`, and the `*_dir` functions return `Dir`s rather /// than `Path`s, because absolute paths don't interoperate well with the /// capability model. #[derive(Clone)] pub struct ProjectDirs { - inner: directories_next::ProjectDirs, + inner: directories::ProjectDirs, } impl ProjectDirs { /// Creates a `ProjectDirs` struct from values describing the project. /// - /// This corresponds to [`directories_next::ProjectDirs::from`]. + /// This corresponds to [`directories::ProjectDirs::from`]. /// /// # Ambient Authority /// @@ -37,13 +37,13 @@ impl ProjectDirs { ambient_authority: AmbientAuthority, ) -> Option { let _ = ambient_authority; - let inner = directories_next::ProjectDirs::from(qualifier, organization, application)?; + let inner = directories::ProjectDirs::from(qualifier, organization, application)?; Some(Self { inner }) } /// Returns the project's cache directory. /// - /// This corresponds to [`directories_next::ProjectDirs::cache_dir`]. + /// This corresponds to [`directories::ProjectDirs::cache_dir`]. pub fn cache_dir(&self) -> io::Result { let path = self.inner.cache_dir(); fs::create_dir_all(path)?; @@ -52,7 +52,7 @@ impl ProjectDirs { /// Returns the project's config directory. /// - /// This corresponds to [`directories_next::ProjectDirs::config_dir`]. + /// This corresponds to [`directories::ProjectDirs::config_dir`]. pub fn config_dir(&self) -> io::Result { let path = self.inner.config_dir(); fs::create_dir_all(path)?; @@ -61,7 +61,7 @@ impl ProjectDirs { /// Returns the project's data directory. /// - /// This corresponds to [`directories_next::ProjectDirs::data_dir`]. + /// This corresponds to [`directories::ProjectDirs::data_dir`]. pub fn data_dir(&self) -> io::Result { let path = self.inner.data_dir(); fs::create_dir_all(path)?; @@ -70,7 +70,7 @@ impl ProjectDirs { /// Returns the project's local data directory. /// - /// This corresponds to [`directories_next::ProjectDirs::data_local_dir`]. + /// This corresponds to [`directories::ProjectDirs::data_local_dir`]. pub fn data_local_dir(&self) -> io::Result { let path = self.inner.data_local_dir(); fs::create_dir_all(path)?; @@ -79,10 +79,21 @@ impl ProjectDirs { /// Returns the project's runtime directory. /// - /// This corresponds to [`directories_next::ProjectDirs::runtime_dir`]. + /// This corresponds to [`directories::ProjectDirs::runtime_dir`]. pub fn runtime_dir(&self) -> io::Result { let path = self.inner.runtime_dir().ok_or_else(not_found)?; fs::create_dir_all(path)?; Dir::open_ambient_dir(path, ambient_authority()) } + + /// Returns the project's state directory. + /// + /// This corresponds to [`directories::ProjectDirs::state_dir`]. + pub fn state_dir(&self) -> io::Result> { + let Some(path) = self.inner.state_dir() else { + return Ok(None); + }; + fs::create_dir_all(path)?; + Dir::open_ambient_dir(path, ambient_authority()).map(Some) + } } diff --git a/cap-directories/src/user_dirs.rs b/cap-directories/src/user_dirs.rs index 4ae8b35b..f50f5e79 100644 --- a/cap-directories/src/user_dirs.rs +++ b/cap-directories/src/user_dirs.rs @@ -6,31 +6,31 @@ use std::io; /// `UserDirs` provides paths of user-facing standard directories, following /// the conventions of the operating system the library is running on. /// -/// This corresponds to [`directories_next::UserDirs`], except that the +/// This corresponds to [`directories::UserDirs`], except that the /// functions open the directories and returns `Dir`s instead of returning /// `Path`s. /// -/// Unlike `directories_next::UserDirs`, the `*_dir` functions return `Dir`s +/// Unlike `directories::UserDirs`, the `*_dir` functions return `Dir`s /// rather than `Path`s, because absolute paths don't interoperate well with /// the capability model. #[derive(Clone)] pub struct UserDirs { - inner: directories_next::UserDirs, + inner: directories::UserDirs, } impl UserDirs { /// Creates a `UserDirs` struct which holds the paths to user-facing /// directories for audio, font, video, etc. data on the system. /// - /// This corresponds to [`directories_next::UserDirs::new`]. + /// This corresponds to [`directories::UserDirs::new`]. pub fn new() -> Option { - let inner = directories_next::UserDirs::new()?; + let inner = directories::UserDirs::new()?; Some(Self { inner }) } /// Returns the user's home directory. /// - /// This corresponds to [`directories_next::UserDirs::home_dir`]. + /// This corresponds to [`directories::UserDirs::home_dir`]. /// /// # Ambient Authority /// @@ -42,7 +42,7 @@ impl UserDirs { /// Returns the user's audio directory. /// - /// This corresponds to [`directories_next::UserDirs::audio_dir`]. + /// This corresponds to [`directories::UserDirs::audio_dir`]. /// /// # Ambient Authority /// @@ -57,7 +57,7 @@ impl UserDirs { /// Returns the user's desktop directory. /// - /// This corresponds to [`directories_next::UserDirs::desktop_dir`]. + /// This corresponds to [`directories::UserDirs::desktop_dir`]. /// /// # Ambient Authority /// @@ -72,7 +72,7 @@ impl UserDirs { /// Returns the user's document directory. /// - /// This corresponds to [`directories_next::UserDirs::document_dir`]. + /// This corresponds to [`directories::UserDirs::document_dir`]. /// /// # Ambient Authority /// @@ -87,7 +87,7 @@ impl UserDirs { /// Returns the user's download directory. /// - /// This corresponds to [`directories_next::UserDirs::download_dir`]. + /// This corresponds to [`directories::UserDirs::download_dir`]. /// /// # Ambient Authority /// @@ -102,7 +102,7 @@ impl UserDirs { /// Returns the user's font directory. /// - /// This corresponds to [`directories_next::UserDirs::font_dir`]. + /// This corresponds to [`directories::UserDirs::font_dir`]. /// /// # Ambient Authority /// @@ -117,7 +117,7 @@ impl UserDirs { /// Returns the user's picture directory. /// - /// This corresponds to [`directories_next::UserDirs::picture_dir`]. + /// This corresponds to [`directories::UserDirs::picture_dir`]. /// /// # Ambient Authority /// @@ -132,7 +132,7 @@ impl UserDirs { /// Returns the user's public directory. /// - /// This corresponds to [`directories_next::UserDirs::public_dir`]. + /// This corresponds to [`directories::UserDirs::public_dir`]. /// /// # Ambient Authority /// @@ -147,7 +147,7 @@ impl UserDirs { /// Returns the user's template directory. /// - /// This corresponds to [`directories_next::UserDirs::template_dir`]. + /// This corresponds to [`directories::UserDirs::template_dir`]. /// /// # Ambient Authority /// @@ -162,7 +162,7 @@ impl UserDirs { /// Returns the user's video directory. /// - /// This corresponds to [`directories_next::UserDirs::video_dir`]. + /// This corresponds to [`directories::UserDirs::video_dir`]. /// /// # Ambient Authority ///