use super::Setting;
pub const BEGIN: &str =
"# BEGIN PGTUNE — generated by `bestool tamanu pg-tune`, do not edit by hand";
pub const END: &str = "# END PGTUNE";
const LEGACY_HEADER: &str = "# PGTUNE";
pub fn render(settings: &[Setting]) -> String {
let mut out = String::new();
out.push_str(BEGIN);
out.push('\n');
for setting in settings {
out.push_str(setting.key);
out.push_str(" = ");
out.push_str(&setting.value);
out.push('\n');
}
out.push_str(END);
out.push('\n');
out
}
pub fn splice(existing: &str, block: &str) -> String {
let block_lines: Vec<&str> = block.trim_end_matches('\n').split('\n').collect();
let lines: Vec<&str> = if existing.is_empty() {
Vec::new()
} else {
existing.split('\n').collect()
};
let begin = lines.iter().position(|l| l.trim_end() == BEGIN);
let end = lines.iter().position(|l| l.trim_end() == END);
let mut result: Vec<&str> = Vec::new();
match (begin, end) {
(Some(b), Some(e)) if b <= e => {
result.extend_from_slice(&lines[..b]);
result.extend_from_slice(&block_lines);
result.extend_from_slice(&lines[e + 1..]);
}
_ => {
let cut = lines
.iter()
.position(|l| l.trim_start().starts_with(LEGACY_HEADER))
.unwrap_or(lines.len());
result.extend_from_slice(&lines[..cut]);
trim_trailing_empty(&mut result);
if !result.is_empty() {
result.push("");
}
result.extend_from_slice(&block_lines);
}
}
trim_trailing_empty(&mut result);
let mut out = result.join("\n");
out.push('\n');
out
}
fn trim_trailing_empty(lines: &mut Vec<&str>) {
while lines.last().is_some_and(|l| l.trim().is_empty()) {
lines.pop();
}
}
#[cfg(test)]
mod tests {
use super::*;
fn sample_block() -> String {
render(&[
Setting::new("shared_buffers", "1GB"),
Setting::new("work_mem", "16MB"),
])
}
#[test]
fn appends_to_a_file_without_markers() {
let existing = "listen_addresses = '*'\nport = 5432\n";
let out = splice(existing, &sample_block());
assert!(out.starts_with("listen_addresses = '*'\nport = 5432\n\n# BEGIN PGTUNE"));
assert!(out.ends_with("# END PGTUNE\n"));
assert!(out.contains("shared_buffers = 1GB"));
}
#[test]
fn replaces_between_existing_markers() {
let first = splice("port = 5432\n", &sample_block());
let updated = render(&[Setting::new("shared_buffers", "2GB")]);
let second = splice(&first, &updated);
assert!(second.contains("shared_buffers = 2GB"));
assert!(!second.contains("shared_buffers = 1GB"));
assert!(!second.contains("work_mem"));
assert!(second.starts_with("port = 5432\n"));
assert_eq!(second.matches(BEGIN).count(), 1);
assert_eq!(second.matches(END).count(), 1);
}
#[test]
fn migrates_a_legacy_header_to_eof() {
let existing = "port = 5432\n\n# PGTUNE https://pgtune.leopard.in.ua/\nshared_buffers = 512MB\nwork_mem = 8MB\n";
let out = splice(existing, &sample_block());
assert!(out.starts_with("port = 5432\n"));
assert!(!out.contains("# PGTUNE https"));
assert!(!out.contains("512MB"));
assert!(out.contains("# BEGIN PGTUNE"));
assert!(out.contains("shared_buffers = 1GB"));
assert!(out.ends_with("# END PGTUNE\n"));
}
#[test]
fn is_idempotent() {
let block = sample_block();
let once = splice("port = 5432\n", &block);
let twice = splice(&once, &block);
assert_eq!(once, twice);
}
#[test]
fn empty_file_gets_only_the_block() {
let out = splice("", &sample_block());
assert!(out.starts_with("# BEGIN PGTUNE"));
assert!(out.ends_with("# END PGTUNE\n"));
}
}