vh 0.1.1

VHost manager for local development.
use anyhow::{Context, Result};
use std::process::Command;
use std::io::Write;

pub struct HostsModifier;

impl HostsModifier {
    const HOSTS_PATH: &'static str = "/etc/hosts";

    pub fn add_entry(domain: &str, ip: &str) -> Result<()> {
        let entry = format!("{} {}", ip, domain);
        let current = std::fs::read_to_string(Self::HOSTS_PATH)?;

        let mut lines: Vec<&str> = current
            .lines()
            .filter(|line| !line.contains(domain))
            .collect();

        lines.push(&entry);
        let updated = format!("{}\n", lines.join("\n"));
        
        Self::apply_changes(updated)
    }

    pub fn remove_entry(domain: &str) -> Result<()> {
        let current = std::fs::read_to_string(Self::HOSTS_PATH)?;
        
        let filtered: Vec<&str> = current
            .lines()
            .filter(|line| !line.contains(domain))
            .collect();

        let updated = format!("{}\n", filtered.join("\n"));
        Self::apply_changes(updated)
    }

    fn apply_changes(content: String) -> Result<()> {
        let mut child = Command::new("sudo")
            .arg("tee")
            .arg(Self::HOSTS_PATH)
            .stdin(std::process::Stdio::piped())
            .stdout(std::process::Stdio::null())
            .spawn()
            .context("Failed to elevate privileges for /etc/hosts update")?;

        let mut stdin = child.stdin.take().context("Failed to capture stdin")?;
        stdin.write_all(content.as_bytes())?;
        drop(stdin);

        let status = child.wait()?;
        if !status.success() {
            return Err(anyhow::anyhow!("Sudo operation failed with status {}", status));
        }
        Ok(())
    }
}