weavatrix-git 0.3.1

Fast, bounded, evidence-carrying Git reader with an optional read-only MCP server
Documentation
use std::{
    env, fs,
    io::Write,
    path::Path,
    process::{Command, Stdio},
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let args = env::args().skip(1).collect::<Vec<_>>();
    let path = args
        .first()
        .ok_or("usage: create_fixture <new-path> [commits]")?;
    let commits = args
        .get(1)
        .map(|value| value.parse())
        .transpose()?
        .unwrap_or(2_000);
    if Path::new(path).exists() {
        return Err("fixture path already exists; refusing to overwrite it".into());
    }
    fs::create_dir_all(path)?;
    run(path, &["init", "-q"])?;
    let mut child = Command::new("git")
        .args(["fast-import", "--quiet"])
        .current_dir(path)
        .stdin(Stdio::piped())
        .spawn()?;
    let mut input = child.stdin.take().ok_or("fast-import stdin unavailable")?;
    input.write_all(b"feature done\n")?;
    for index in 0..commits {
        let blob_mark = index * 2 + 1;
        let commit_mark = blob_mark + 1;
        let content = format!(
            "revision={index:06}\n{}\n",
            "stable architecture evidence ".repeat(120)
        );
        write!(
            input,
            "blob\nmark :{blob_mark}\ndata {}\n{content}\n",
            content.len()
        )?;
        let message = format!("revision {index}");
        write!(
            input,
            "commit refs/heads/main\nmark :{commit_mark}\n\
             committer Weavatrix <bench@weavatrix.local> {} +0000\n\
             data {}\n{message}\n",
            1_700_000_000 + index,
            message.len()
        )?;
        if index > 0 {
            writeln!(input, "from :{}", commit_mark - 2)?;
        }
        writeln!(input, "M 100644 :{blob_mark} tracked.txt")?;
    }
    input.write_all(b"done\n")?;
    drop(input);
    if !child.wait()?.success() {
        return Err("git fast-import failed".into());
    }
    run(path, &["symbolic-ref", "HEAD", "refs/heads/main"])?;
    run(path, &["reset", "--hard", "--quiet", "HEAD"])?;
    run(path, &["gc", "--aggressive", "--prune=now"])?;
    println!("{}", Path::new(path).canonicalize()?.display());
    Ok(())
}

fn run(path: &str, args: &[&str]) -> Result<(), Box<dyn std::error::Error>> {
    let output = Command::new("git").args(args).current_dir(path).output()?;
    if !output.status.success() {
        return Err(String::from_utf8_lossy(&output.stderr).into_owned().into());
    }
    Ok(())
}