1pub mod cli;
5pub mod logger;
6
7use crate::cli_shared::cli::{Config, ConfigPath, find_config_path};
8use crate::networks::NetworkChain;
9use crate::utils::io::read_toml;
10use std::path::PathBuf;
11
12cfg_if::cfg_if! {
13 if #[cfg(feature = "rustalloc")] {
14 } else if #[cfg(feature = "jemalloc")] {
15 pub use tikv_jemallocator;
16 }
17}
18
19pub const FOREST_DATA_DIR_ENV: &str = "FOREST_PATH";
23
24pub fn chain_path(config: &Config) -> PathBuf {
26 PathBuf::from(&config.client.data_dir).join(config.chain().to_string())
27}
28
29pub fn read_config(
30 config_path_opt: Option<&PathBuf>,
31 chain_opt: Option<NetworkChain>,
32) -> anyhow::Result<(Option<ConfigPath>, Config)> {
33 let (path, mut config) = match find_config_path(config_path_opt) {
34 Some(path) => {
35 let toml = std::fs::read_to_string(path.to_path_buf())?;
37 (Some(path), read_toml(&toml)?)
39 }
40 None => (None, Config::default()),
41 };
42 if let Some(chain) = chain_opt {
43 config.chain = chain;
44 }
45 if let Some(data_dir) = data_dir_from_env() {
48 config.client.data_dir = data_dir;
49 }
50 Ok((path, config))
51}
52
53fn data_dir_from_env() -> Option<PathBuf> {
56 match std::env::var(FOREST_DATA_DIR_ENV) {
57 Ok(s) if !s.trim().is_empty() => Some(PathBuf::from(s)),
58 _ => None,
59 }
60}
61
62pub fn default_data_dir() -> PathBuf {
68 data_dir_from_env().unwrap_or_else(|| crate::cli_shared::cli::Client::default().data_dir)
69}
70
71pub fn default_token_path() -> PathBuf {
75 default_data_dir().join(crate::cli_shared::cli::Client::RPC_TOKEN_FILENAME)
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn read_config_default() {
84 let (config_path, config) = read_config(None, None).unwrap();
85
86 assert!(config_path.is_none());
87 assert_eq!(config.chain(), &NetworkChain::Mainnet);
88 }
89
90 #[test]
91 fn read_config_calibnet_override() {
92 let (config_path, config) = read_config(None, Some(NetworkChain::Calibnet)).unwrap();
93
94 assert!(config_path.is_none());
95 assert_eq!(config.chain(), &NetworkChain::Calibnet);
96 }
97
98 #[test]
99 fn read_config_butterflynet_override() {
100 let (config_path, config) = read_config(None, Some(NetworkChain::Butterflynet)).unwrap();
101
102 assert!(config_path.is_none());
103 assert_eq!(config.chain(), &NetworkChain::Butterflynet);
104 }
105
106 fn with_data_dir_env<T>(value: &str, f: impl FnOnce() -> T) -> T {
109 unsafe { std::env::set_var(FOREST_DATA_DIR_ENV, value) };
110 let result = f();
111 unsafe { std::env::remove_var(FOREST_DATA_DIR_ENV) };
112 result
113 }
114
115 #[test]
116 #[serial_test::serial]
117 fn read_config_data_dir_env_override() {
118 let data_dir = "/tmp/forest-path-env-override-test";
119 let (_, config) = with_data_dir_env(data_dir, || read_config(None, None).unwrap());
120
121 assert_eq!(config.client.data_dir, std::path::Path::new(data_dir));
123 }
124
125 #[test]
126 #[serial_test::serial]
127 fn default_data_dir_honors_env_override() {
128 let data_dir = "/tmp/forest-path-default-data-dir-test";
129 let resolved = with_data_dir_env(data_dir, default_data_dir);
130 assert_eq!(resolved, std::path::Path::new(data_dir));
131
132 assert_eq!(default_data_dir(), Config::default().client.data_dir);
134 }
135
136 #[test]
137 #[serial_test::serial]
138 fn read_config_data_dir_env_empty_is_ignored() {
139 let (_, config) = with_data_dir_env("", || read_config(None, None).unwrap());
140
141 assert_eq!(config.client.data_dir, Config::default().client.data_dir);
143 }
144
145 #[test]
146 #[serial_test::serial]
147 fn read_config_with_path() {
148 let default_config = Config::default();
149 let temp_dir = tempfile::tempdir().expect("couldn't create temp dir");
150 let config_file = temp_dir.path().join("config.toml");
151 let serialized_config = toml::to_string(&default_config).unwrap();
152 std::fs::write(&config_file, serialized_config).unwrap();
153
154 let (config_path, config) = read_config(Some(&config_file), None).unwrap();
155
156 assert_eq!(config_path.unwrap(), ConfigPath::Cli(config_file));
157 assert_eq!(config.chain(), &NetworkChain::Mainnet);
158 assert_eq!(config, default_config);
159 }
160}
161
162pub mod snapshot;