Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

helper: add fs #67

Merged
merged 10 commits into from
Feb 21, 2024
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions helper/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,20 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/consensus"

[features]
# All features on by default.
default = ["std", "atomic", "asynch", "num", "time", "thread", "constants"]
default = ["std", "atomic", "asynch", "fs", "num", "time", "thread", "constants"]
std = []
atomic = ["dep:crossbeam"]
asynch = ["dep:futures", "dep:rayon"]
constants = []
fs = ["dep:dirs"]
num = []
time = ["dep:chrono", "std"]
thread = ["std", "dep:target_os_lib"]

[dependencies]
crossbeam = { workspace = true, optional = true }
chrono = { workspace = true, optional = true, features = ["std", "clock"] }
dirs = { workspace = true, optional = true }
futures = { workspace = true, optional = true, features = ["std"] }
rayon = { workspace = true, optional = true }

Expand All @@ -34,4 +36,4 @@ target_os_lib = { package = "windows", version = ">=0.51", features = ["Win32_Sy
target_os_lib = { package = "libc", version = "0.2.151", optional = true }

[dev-dependencies]
tokio = { workspace = true }
tokio = { workspace = true, features = ["full"] }
2 changes: 1 addition & 1 deletion helper/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! `#[no_std]` compatible.

//---------------------------------------------------------------------------------------------------- Use
//---------------------------------------------------------------------------------------------------- Commit
/// The current commit hash of the root Cuprate repository.
///
/// # Case & length
Expand Down
189 changes: 189 additions & 0 deletions helper/src/fs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
//! Cuprate directories and filenames.
//!
//! # TODO
//! Document how environment variables can change these.
//!
//! # Reference
//! <https://github.com/Cuprate/cuprate/issues/46>
//! <https://docs.rs/dirs>

//---------------------------------------------------------------------------------------------------- Use
use std::{
path::{Path, PathBuf},
sync::OnceLock,
};

//---------------------------------------------------------------------------------------------------- Const
/// Cuprate's main directory.
///
/// This is the head PATH node used for any top-level Cuprate directories.
///
/// | OS | PATH |
/// |---------|-----------------------------------------------------|
/// | Windows | `C:\Users\Alice\AppData\Roaming\Cuprate\` |
/// | macOS | `/Users/Alice/Library/Application Support/Cuprate/` |
/// | Linux | `/home/alice/.config/cuprate/` |
///
/// This is shared between all Cuprate programs.
///
/// # Value
/// This is `Cuprate` on `Windows|macOS` and `cuprate` on everything else.
///
/// # Monero Equivalent
/// `.bitmonero`
pub const CUPRATE_DIR: &str = {
if cfg!(target_os = "windows") || cfg!(target_os = "macos") {
// The standard for main directories is capitalized.
"Cuprate"
} else {
// Standard on Linux + BSDs is lowercase.
"cuprate"
}
};

//---------------------------------------------------------------------------------------------------- Directories
/// Create a (private) `OnceLock` and accessor function for common PATHs used by Cuprate.
///
/// This currently creates these directories:
/// - [`cuprate_cache_dir()`]
/// - [`cuprate_config_dir()`]
/// - [`cuprate_data_dir()`]
///
/// FIXME: Use `LazyLock` when stabilized.
/// <https://github.com/rust-lang/rust/issues/109736>.
/// <https://doc.rust-lang.org/std/sync/struct.LazyLock.html>.
macro_rules! impl_dir_oncelock_and_fn {
($(
$(#[$attr:meta])* // Documentation and any `derive`'s.
$fn:ident, // Name of the corresponding access function.
$dirs_fn:ident, // Name of the `dirs` function to use, the PATH prefix.
$once_lock:ident // Name of the `OnceLock`.
),* $(,)?) => {$(
/// Local `OnceLock` containing the Path.
static $once_lock: OnceLock<PathBuf> = OnceLock::new();

// Create the `OnceLock` if needed, append
// the Cuprate directory string and return.
$(#[$attr])*
pub fn $fn() -> &'static Path {
$once_lock.get_or_init(|| {
// There's nothing we can do but panic if
// we cannot acquire critical system directories.
//
// Although, this realistically won't panic on
// normal systems for all OS's supported by `dirs`.
let mut path = dirs::$dirs_fn().unwrap();

// FIXME:
// Consider a user who does `HOME=/ ./cuprated`
//
// Should we say "that's stupid" and panic here?
// Or should it be respected?
// We really don't want a `rm -rf /` type of situation...
assert!(
path.parent().is_some(),
"SAFETY: returned OS PATH was either root or empty, aborting"
);

// Returned OS PATH should be absolute, not relative.
assert!(path.is_absolute(), "SAFETY: returned OS PATH was not absolute");

path.push(CUPRATE_DIR);
path
})
}
)*};
}

impl_dir_oncelock_and_fn! {
/// Cuprate's cache directory.
///
/// This is the PATH used for any Cuprate cache files.
///
/// | OS | PATH |
/// |---------|-----------------------------------------|
/// | Windows | `C:\Users\Alice\AppData\Local\Cuprate\` |
/// | macOS | `/Users/Alice/Library/Caches/Cuprate/` |
/// | Linux | `/home/alice/.cache/cuprate/` |
cuprate_cache_dir,
cache_dir,
CUPRATE_CACHE_DIR,

/// Cuprate's config directory.
///
/// This is the PATH used for any Cuprate configuration files.
///
/// | OS | PATH |
/// |---------|-----------------------------------------------------|
/// | Windows | `C:\Users\Alice\AppData\Roaming\Cuprate\` |
/// | macOS | `/Users/Alice/Library/Application Support/Cuprate/` |
/// | Linux | `/home/alice/.config/cuprate/` |
cuprate_config_dir,
config_dir,
CUPRATE_CONFIG_DIR,

/// Cuprate's data directory.
///
/// This is the PATH used for any Cuprate data files.
///
/// | OS | PATH |
/// |---------|-----------------------------------------------------|
/// | Windows | `C:\Users\Alice\AppData\Roaming\Cuprate\` |
/// | macOS | `/Users/Alice/Library/Application Support/Cuprate/` |
/// | Linux | `/home/alice/.local/share/cuprate/` |
cuprate_data_dir,
data_dir,
CUPRATE_DATA_DIR,
}

//---------------------------------------------------------------------------------------------------- Tests
#[cfg(test)]
mod test {
use super::*;

#[test]
fn dir_sanity_check() {
assert!(cuprate_cache_dir().is_absolute());
assert!(cuprate_config_dir().is_absolute());
assert!(cuprate_data_dir().is_absolute());

if cfg!(target_os = "windows") {
let dir = cuprate_cache_dir();
println!("cuprate_cache_dir: {dir:?}");
assert!(dir.ends_with(r"AppData\Local\Cuprate"));

let dir = cuprate_config_dir();
println!("cuprate_config_dir: {dir:?}");
assert!(dir.ends_with(r"AppData\Roaming\Cuprate"));

let dir = cuprate_data_dir();
println!("cuprate_data_dir: {dir:?}");
assert!(dir.ends_with(r"AppData\Roaming\Cuprate"));
} else if cfg!(target_os = "macos") {
let dir = cuprate_cache_dir();
println!("cuprate_cache_dir: {dir:?}");
assert!(dir.ends_with("Library/Caches/Cuprate"));

let dir = cuprate_config_dir();
println!("cuprate_config_dir: {dir:?}");
assert!(dir.ends_with("Library/Application Support/Cuprate"));

let dir = cuprate_data_dir();
println!("cuprate_data_dir: {dir:?}");
assert!(dir.ends_with("Library/Application Support/Cuprate"));
} else {
// Assumes Linux.
let dir = cuprate_cache_dir();
println!("cuprate_cache_dir: {dir:?}");
assert!(dir.ends_with(".cache/cuprate"));

let dir = cuprate_config_dir();
println!("cuprate_config_dir: {dir:?}");
assert!(dir.ends_with(".config/cuprate"));

let dir = cuprate_data_dir();
println!("cuprate_data_dir: {dir:?}");
assert!(dir.ends_with(".local/share/cuprate"));
}
}
}
3 changes: 3 additions & 0 deletions helper/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ pub mod atomic;
#[cfg(feature = "constants")]
pub mod constants;

#[cfg(feature = "fs")]
pub mod fs;

pub mod network;

#[cfg(feature = "num")]
Expand Down
Loading