caxe 0.3.8

A modern C/C++ project manager that cuts through build system complexity. Zero config, smart dependencies, and parallel builds.
Documentation
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::fs;
use std::path::Path;

#[derive(Debug, Serialize, Deserialize, Default)]
pub struct LockFile {
    #[serde(rename = "package")]
    pub packages: BTreeMap<String, PackageLock>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct PackageLock {
    pub git: String,
    pub rev: String,
}

impl LockFile {
    pub fn load() -> Result<Self> {
        if Path::new("cx.lock").exists() {
            let content = fs::read_to_string("cx.lock")?;
            Ok(toml::from_str(&content)?)
        } else {
            Ok(Self::default())
        }
    }

    pub fn save(&self) -> Result<()> {
        let content = toml::to_string_pretty(self)?;
        fs::write("cx.lock", content)?;
        Ok(())
    }

    pub fn get(&self, name: &str) -> Option<&PackageLock> {
        self.packages.get(name)
    }

    pub fn insert(&mut self, name: String, git: String, rev: String) {
        self.packages.insert(name, PackageLock { git, rev });
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_lockfile_insert_and_get() {
        let mut lock = LockFile::default();
        lock.insert(
            "fmt".to_string(),
            "https://github.com/fmtlib/fmt".to_string(),
            "abc123".to_string(),
        );
        let entry = lock.get("fmt").unwrap();
        assert_eq!(entry.git, "https://github.com/fmtlib/fmt");
        assert_eq!(entry.rev, "abc123");
    }

    #[test]
    fn test_lockfile_get_missing() {
        let lock = LockFile::default();
        assert!(lock.get("nonexistent").is_none());
    }

    #[test]
    fn test_lockfile_serialization() {
        let mut lock = LockFile::default();
        lock.insert(
            "json".to_string(),
            "https://github.com/nlohmann/json".to_string(),
            "v3.11.2".to_string(),
        );
        let toml_str = toml::to_string_pretty(&lock).unwrap();
        assert!(toml_str.contains("json"));
        assert!(toml_str.contains("v3.11.2"));
    }

    #[test]
    fn test_lockfile_parse() {
        let toml_str = r#"
[package]
fmt = { git = "https://github.com/fmtlib/fmt", rev = "abc123" }
"#;
        let lock: LockFile = toml::from_str(toml_str).unwrap();
        let entry = lock.get("fmt").unwrap();
        assert_eq!(entry.rev, "abc123");
    }
}