Skip to content

Commit 135af26

Browse files
committed
feat(crate): init soar-config crate (#108)
1 parent 8be00ab commit 135af26

31 files changed

Lines changed: 963 additions & 371 deletions

Cargo.lock

Lines changed: 40 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[workspace]
22
resolver = "2"
33
members = [
4+
"crates/soar-config",
45
"crates/soar-db",
56
"crates/soar-dl",
67
"crates/soar-utils",
@@ -25,6 +26,7 @@ diesel = { version = "2.3.2", features = [
2526
"sqlite"
2627
] }
2728
diesel_migrations = { version = "2.3.0", features = ["sqlite"] }
29+
documented = "0.9.2"
2830
fast-glob = "1.0.0"
2931
miette = { version = "7.6.0", features = ["fancy"] }
3032
percent-encoding = "2.3.2"
@@ -38,11 +40,14 @@ rusqlite = { version = "0.37.0", features = ["bundled", "rusqlite-macros"] }
3840
serde = { version = "1.0.225", features = ["derive"] }
3941
serde_json = { version = "1.0.145", features = ["indexmap"] }
4042
serial_test = "3.2.0"
43+
soar-config = { path = "crates/soar-config" }
4144
soar-core = { path = "soar-core" }
4245
soar-dl = { path = "crates/soar-dl" }
4346
soar-utils = { path = "crates/soar-utils" }
4447
tempfile = "3.10.1"
4548
thiserror = "2.0.17"
49+
toml = "0.9.8"
50+
toml_edit = "0.23.7"
4651
tracing = { version = "0.1.41", default-features = false }
4752
ureq = { version = "3.1.2", features = ["json"] }
4853
url = "2.5.7"

crates/soar-config/Cargo.toml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[package]
2+
name = "soar-config"
3+
version = "0.1.0"
4+
description = "Configuration management for soar package manager"
5+
authors.workspace = true
6+
edition.workspace = true
7+
readme.workspace = true
8+
repository.workspace = true
9+
license.workspace = true
10+
keywords.workspace = true
11+
categories.workspace = true
12+
13+
[dependencies]
14+
documented = { workspace = true }
15+
miette = { workspace = true }
16+
serde = { workspace = true }
17+
soar-utils = { workspace = true }
18+
thiserror = { workspace = true }
19+
toml = { workspace = true }
20+
toml_edit = { workspace = true }
21+
tracing = { workspace = true }
Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use documented::{Documented, DocumentedFields};
44
use toml_edit::{ArrayOfTables, Decor, Item, RawString, Table};
55
use tracing::warn;
66

7-
use crate::error::ConfigError;
7+
use crate::error::{ConfigError, Result};
88

99
/// Appends documentation lines as TOML comments to the given `Decor`.
1010
///
@@ -52,7 +52,7 @@ pub fn append_docs_as_toml_comments(decor: &mut Decor, docs: &str) {
5252
///
5353
/// # Returns
5454
/// Returns `Ok(())` if successful, or a `ConfigError` if a TOML item is unexpectedly `None`.
55-
pub fn annotate_toml_table<T>(table: &mut Table, is_root: bool) -> Result<(), ConfigError>
55+
pub fn annotate_toml_table<T>(table: &mut Table, is_root: bool) -> Result<()>
5656
where
5757
T: Documented + DocumentedFields,
5858
{
@@ -66,9 +66,7 @@ where
6666
Ok(docs) => {
6767
match value_item {
6868
Item::None => {
69-
return Err(ConfigError::Custom(format!(
70-
"Encountered TomlEditItem::None for key '{key_str}' unexpectedly",
71-
)))
69+
return Err(ConfigError::UnexpectedTomlItem(key_str.into()));
7270
}
7371
Item::Value(_) => append_docs_as_toml_comments(key_mut.leaf_decor_mut(), docs),
7472
Item::Table(sub_table) => {
@@ -105,14 +103,60 @@ where
105103
///
106104
/// # Returns
107105
/// Returns `Ok(())` if annotation succeeds, or a `ConfigError` if annotation fails on the first table.
108-
pub fn annotate_toml_array_of_tables<T>(array: &mut ArrayOfTables) -> Result<(), ConfigError>
106+
pub fn annotate_toml_array_of_tables<T>(array: &mut ArrayOfTables) -> Result<()>
109107
where
110108
T: Documented + DocumentedFields,
111109
{
112110
if let Some(first_table) = array.iter_mut().next() {
113-
annotate_toml_table::<T>(first_table, false).map_err(|err| {
114-
ConfigError::Custom(format!("Failed to annotate first table in array: {err}"))
115-
})?;
111+
annotate_toml_table::<T>(first_table, false)
112+
.map_err(|err| ConfigError::AnnotateFirstTable(err.to_string()))?;
116113
}
117114
Ok(())
118115
}
116+
117+
#[cfg(test)]
118+
mod tests {
119+
use toml_edit::Decor;
120+
121+
use super::*;
122+
use crate::config::Config;
123+
124+
#[test]
125+
fn test_append_docs_as_toml_comments() {
126+
let mut decor = Decor::new("", "");
127+
append_docs_as_toml_comments(&mut decor, "Test documentation");
128+
129+
let prefix = decor.prefix().and_then(|p| p.as_str()).unwrap();
130+
assert!(prefix.contains("# Test documentation"));
131+
}
132+
133+
#[test]
134+
fn test_append_docs_multiline() {
135+
let mut decor = Decor::new("", "");
136+
append_docs_as_toml_comments(&mut decor, "Line 1\nLine 2\nLine 3");
137+
138+
let prefix = decor.prefix().and_then(|p| p.as_str()).unwrap();
139+
assert!(prefix.contains("# Line 1"));
140+
assert!(prefix.contains("# Line 2"));
141+
assert!(prefix.contains("# Line 3"));
142+
}
143+
144+
#[test]
145+
fn test_append_docs_empty_lines() {
146+
let mut decor = Decor::new("", "");
147+
append_docs_as_toml_comments(&mut decor, "Line 1\n\nLine 2");
148+
149+
let prefix = decor.prefix().and_then(|p| p.as_str()).unwrap();
150+
assert!(prefix.contains("#\n"));
151+
}
152+
153+
#[test]
154+
fn test_annotate_toml_document() {
155+
let config = Config::default_config::<&str>(false, &[]);
156+
let doc = config.to_annotated_document();
157+
158+
assert!(doc.is_ok());
159+
let doc = doc.unwrap();
160+
assert!(doc.to_string().contains("#"));
161+
}
162+
}

0 commit comments

Comments
 (0)