litvc 1.3.0

Lit - The agentic-first distributed version control system. A complete Git replacement designed for AI agents first and humans second.
Documentation
use crate::network::{AirgapConfig, NetworkConfig};
use crate::response::{ConfigEntry, ConfigResponse};

pub fn execute(
    command: Option<crate::ConfigCommands>,
) -> Result<ConfigResponse, crate::errors::LitError> {
    match command {
        Some(crate::ConfigCommands::Show) | None => show_config(),
        Some(crate::ConfigCommands::Get { key }) => get_config(&key),
        Some(crate::ConfigCommands::Set { key, value }) => set_config(&key, &value),
    }
}

fn show_config() -> Result<ConfigResponse, crate::errors::LitError> {
    let network_config = NetworkConfig::load()?;
    let airgap_config = AirgapConfig::load()?;

    let mut entries = Vec::new();

    entries.push(ConfigEntry {
        key: "airgap.enabled".to_string(),
        value: airgap_config.enabled.to_string(),
    });
    entries.push(ConfigEntry {
        key: "airgap.strict_mode".to_string(),
        value: airgap_config.strict_mode.to_string(),
    });
    entries.push(ConfigEntry {
        key: "airgap.allowed_transports".to_string(),
        value: format!("{:?}", airgap_config.allowed_transports),
    });
    if !airgap_config.allowed_media.is_empty() {
        entries.push(ConfigEntry {
            key: "airgap.allowed_media".to_string(),
            value: airgap_config.allowed_media.join(", "),
        });
    }
    if !airgap_config.allowed_shares.is_empty() {
        entries.push(ConfigEntry {
            key: "airgap.allowed_shares".to_string(),
            value: airgap_config.allowed_shares.join(", "),
        });
    }
    entries.push(ConfigEntry {
        key: "network.allowed_networks".to_string(),
        value: network_config.allowed_networks.join(", "),
    });
    entries.push(ConfigEntry {
        key: "network.allowed_hosts".to_string(),
        value: if network_config.allowed_hosts.is_empty() {
            "(none)".to_string()
        } else {
            network_config.allowed_hosts.join(", ")
        },
    });
    entries.push(ConfigEntry {
        key: "security.network_audit_log".to_string(),
        value: network_config.audit_log.to_string(),
    });
    if let Some(path) = &network_config.audit_log_path {
        entries.push(ConfigEntry {
            key: "security.network_audit_log_path".to_string(),
            value: path.clone(),
        });
    }
    entries.push(ConfigEntry {
        key: "security.airgap_audit_log".to_string(),
        value: airgap_config.audit_log.to_string(),
    });
    if let Some(path) = &airgap_config.audit_log_path {
        entries.push(ConfigEntry {
            key: "security.airgap_audit_log_path".to_string(),
            value: path.clone(),
        });
    }

    Ok(ConfigResponse::Show { entries })
}

fn get_config(key: &str) -> Result<ConfigResponse, crate::errors::LitError> {
    let network_config = NetworkConfig::load()?;
    let airgap_config = AirgapConfig::load()?;

    let value = match key {
        "airgap.enabled" => airgap_config.enabled.to_string(),
        "airgap.strict_mode" => airgap_config.strict_mode.to_string(),
        "network.allowed_networks" => network_config.allowed_networks.join(", "),
        "network.allowed_hosts" => network_config.allowed_hosts.join(", "),
        "security.audit_log" => network_config.audit_log.to_string(),
        "security.audit_log_path" => network_config.audit_log_path.unwrap_or_default(),
        _ => return Err(format!("Unknown configuration key: {}", key).into()),
    };

    Ok(ConfigResponse::Get {
        key: key.to_string(),
        value,
    })
}

fn set_config(key: &str, value: &str) -> Result<ConfigResponse, crate::errors::LitError> {
    match key {
        "airgap.enabled" => {
            let mut config = AirgapConfig::load()?;
            config.enabled = value
                .parse::<bool>()
                .map_err(|_| "Invalid boolean value (use 'true' or 'false')".to_string())?;
            config.save()?;
            Ok(ConfigResponse::Set {
                key: key.to_string(),
                value: value.to_string(),
            })
        }
        "airgap.strict_mode" => {
            let mut config = AirgapConfig::load()?;
            config.strict_mode = value
                .parse::<bool>()
                .map_err(|_| "Invalid boolean value (use 'true' or 'false')".to_string())?;
            config.save()?;
            Ok(ConfigResponse::Set {
                key: key.to_string(),
                value: value.to_string(),
            })
        }
        _ => Err(format!(
            "Setting '{}' is not supported via command line.\n\
                 Supported keys: airgap.enabled, airgap.strict_mode\n\
                 For other settings, edit ~/.lit/airgap.toml or ~/.litconfig directly.",
            key
        )
        .into()),
    }
}