Skip to content

Commit 873ca05

Browse files
committed
added type_toml_item_like func,it inspects the existing item's type in the document and parses the new value into that same type.
1 parent 5538578 commit 873ca05

1 file changed

Lines changed: 77 additions & 0 deletions

File tree

src/main.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,83 @@ fn handle_action(action: AppAction, app: &mut App) -> Result<ControlFlow<()>> {
385385
}
386386

387387
Ok(ControlFlow::Continue(()))
388+
Ok(false)
389+
}
390+
391+
/// Matches the TOML type of an existing item and parses the new string
392+
/// value into that same type. This prevents numeric/bool fields from
393+
/// being written back as quoted strings (e.g. port = "3333").
394+
fn typed_toml_item_like(existing: &toml_edit::Item, new_value: &str) -> Result<toml_edit::Item> {
395+
if existing.as_integer().is_some() {
396+
let parsed = new_value
397+
.parse::<i64>()
398+
.map_err(|e| anyhow::anyhow!("Expected integer, got '{}': {}", new_value, e))?;
399+
Ok(toml_edit::value(parsed))
400+
} else if existing.as_float().is_some() {
401+
let parsed = new_value
402+
.parse::<f64>()
403+
.map_err(|e| anyhow::anyhow!("Expected float, got '{}': {}", new_value, e))?;
404+
Ok(toml_edit::value(parsed))
405+
} else if existing.as_bool().is_some() {
406+
let parsed = new_value.parse::<bool>().map_err(|e| {
407+
anyhow::anyhow!("Expected bool (true/false), got '{}': {}", new_value, e)
408+
})?;
409+
Ok(toml_edit::value(parsed))
410+
} else if existing.as_str().is_some() {
411+
Ok(toml_edit::value(new_value.to_owned()))
412+
} else {
413+
Err(anyhow::anyhow!(
414+
"Unsupported TOML value type for key: {}",
415+
existing
416+
))
417+
}
418+
}
419+
420+
/// Serialize the live `P2PoolConfig` back to TOML and write it to disk.
421+
/// Saves P2Pool config by patching the original TOML file in-place.
422+
/// Uses toml_edit so comments and formatting are preserved.
423+
fn save_p2pool_config(path: &std::path::Path, cfg: &P2PoolConfig) -> Result<()> {
424+
use pdm::p2poolv2_config::flatten_config;
425+
use toml_edit::DocumentMut;
426+
427+
// Read the original file so we preserve comments/ordering
428+
let original = std::fs::read_to_string(path)
429+
.map_err(|e| anyhow::anyhow!("Failed to read P2Pool config: {}", e))?;
430+
431+
let mut doc = original
432+
.parse::<DocumentMut>()
433+
.map_err(|e| anyhow::anyhow!("Failed to parse P2Pool config TOML: {}", e))?;
434+
435+
// Walk every flattened entry and patch the matching TOML key
436+
for entry in flatten_config(cfg) {
437+
let section = entry.section.to_string();
438+
let key = entry.key.as_str();
439+
440+
// Skip optional fields that are unset — leave them absent in the file
441+
if !entry.enabled {
442+
continue;
443+
}
444+
445+
if let Some(table) = doc.get_mut(&section).and_then(|v| v.as_table_mut()) {
446+
// Only update keys that already exist in the file to avoid
447+
// injecting fields the user intentionally omitted
448+
if let Some(existing) = table.get(key) {
449+
match typed_toml_item_like(existing, &entry.value) {
450+
Ok(updated) => table[key] = updated,
451+
Err(e) => {
452+
// Soft error — skip this field and continue
453+
// saving the rest rather than aborting entirely
454+
eprintln!("Warning: skipping {}.{}: {}", section, key, e);
455+
}
456+
}
457+
}
458+
}
459+
}
460+
461+
std::fs::write(path, doc.to_string())
462+
.map_err(|e| anyhow::anyhow!("Failed to write P2Pool config: {}", e))?;
463+
464+
Ok(())
388465
}
389466

390467
#[cfg(test)]

0 commit comments

Comments
 (0)