kellnr_settings/
settings.rs1use std::convert::TryFrom;
2use std::env;
3use std::path::{Path, PathBuf};
4
5use config::{Config, ConfigError, Environment, File};
6use serde::{Deserialize, Serialize};
7
8use crate::compile_time_config;
9use crate::docs::Docs;
10use crate::local::Local;
11use crate::log::Log;
12use crate::origin::Origin;
13use crate::postgresql::Postgresql;
14use crate::proxy::Proxy;
15use crate::registry::Registry;
16use crate::s3::S3;
17use crate::setup::Setup;
18
19#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Default, Clone)]
20#[serde(default)]
21pub struct Settings {
22 pub setup: Setup,
23 pub registry: Registry,
24 pub docs: Docs,
25 pub proxy: Proxy,
26 pub log: Log,
27 pub local: Local,
28 pub origin: Origin,
29 pub postgresql: Postgresql,
30 pub s3: S3,
31}
32
33impl TryFrom<Option<&Path>> for Settings {
34 type Error = ConfigError;
35
36 fn try_from(config_path: Option<&Path>) -> Result<Self, Self::Error> {
37 let env = env::var("RUN_MODE").unwrap_or_else(|_| "development".into());
38 let builder = Config::builder();
39
40 let builder = match config_path {
42 Some(config_path) => {
43 let default_file = Settings::join_path(config_path, "default")?;
44 let env_file = Settings::join_path(config_path, &env)?;
45 let local_file = Settings::join_path(config_path, "local")?;
46
47 builder
48 .add_source(File::with_name(&default_file).required(false))
50 .add_source(File::with_name(&env_file).required(false))
54 .add_source(File::with_name(&local_file).required(false))
57 }
58 None => builder,
59 };
60
61 let s = builder
62 .add_source(
64 Environment::with_prefix("KELLNR")
65 .list_separator(",")
66 .with_list_parse_key("registry.required_crate_fields")
67 .try_parsing(true)
68 .prefix_separator("_")
69 .separator("__"),
70 )
71 .build()?;
72
73 s.try_deserialize()
75 }
76}
77
78impl Settings {
79 fn join_path(config_path: &Path, file: &str) -> Result<String, ConfigError> {
80 config_path
81 .join(file)
82 .to_str()
83 .map(ToString::to_string)
84 .ok_or_else(|| ConfigError::Message("Invalid UTF-8 string".to_string()))
85 }
86
87 pub fn bin_path(&self) -> PathBuf {
88 PathBuf::from(&self.registry.data_dir).join("crates")
89 }
90
91 pub fn doc_queue_path(&self) -> PathBuf {
92 PathBuf::from(&self.registry.data_dir).join("doc_queue")
93 }
94
95 pub fn sqlite_path(&self) -> PathBuf {
96 PathBuf::from(&self.registry.data_dir).join("db.sqlite")
97 }
98
99 pub fn docs_path(&self) -> PathBuf {
100 PathBuf::from(&self.registry.data_dir).join("docs")
101 }
102
103 pub fn base_path(&self) -> PathBuf {
104 PathBuf::from(&self.registry.data_dir).join("git")
105 }
106
107 pub fn crates_io_bin_path(&self) -> PathBuf {
108 PathBuf::from(&self.registry.data_dir).join("cratesio")
109 }
110
111 pub fn crates_io_path(&self) -> String {
112 format!("{}/cratesio", self.registry.data_dir)
113 }
114
115 pub fn crates_path(&self) -> String {
116 format!("{}/crates", self.registry.data_dir)
117 }
118
119 pub fn crates_path_or_bucket(&self) -> String {
120 if self.s3.enabled
121 && let Some(bucket) = &self.s3.crates_bucket
122 {
123 bucket.clone()
124 } else {
125 self.crates_path()
126 }
127 }
128
129 pub fn crates_io_path_or_bucket(&self) -> String {
130 if self.s3.enabled
131 && let Some(bucket) = &self.s3.cratesio_bucket
132 {
133 bucket.clone()
134 } else {
135 self.crates_io_path()
136 }
137 }
138}
139
140pub fn get_settings() -> Result<Settings, ConfigError> {
141 let path = if Path::new(compile_time_config::KELLNR_CONFIG_DIR).exists() {
142 Some(Path::new(compile_time_config::KELLNR_CONFIG_DIR))
143 } else if Path::new("./config").exists() {
144 Some(Path::new("./config"))
145 } else if Path::new("../config").exists() {
146 Some(Path::new("../config"))
147 } else if Path::new("../../config").exists() {
148 Some(Path::new("../../config"))
149 } else {
150 None
151 };
152
153 Settings::try_from(path)
154}
155
156pub fn test_settings() -> Settings {
158 Settings {
159 registry: Registry {
160 data_dir: "/tmp/kdata_test".to_string(),
161 ..Registry::default()
162 },
163 ..Settings::default()
164 }
165}