alef 0.71.0

Opinionated polyglot binding generator for Rust libraries
Documentation
use super::*;
use crate::core::backend::GeneratedFile;
use std::path::PathBuf;

fn generated(path: &str, content: &str) -> GeneratedFile {
    GeneratedFile {
        path: PathBuf::from(path),
        content: content.to_string(),
        generated_header: true,
    }
}

#[test]
fn reconciliation_replaces_only_alef_owned_generated_manifests() {
    let directory = tempfile::tempdir().expect("create temp directory");
    let managed_path = directory.path().join("crates/sample-ffi/Cargo.toml");
    let handwritten_path = directory.path().join("crates/manual/Cargo.toml");
    let source_path = directory.path().join("crates/sample-ffi/src/lib.rs");
    std::fs::create_dir_all(managed_path.parent().expect("managed parent")).expect("create managed directory");
    std::fs::create_dir_all(handwritten_path.parent().expect("handwritten parent"))
        .expect("create handwritten directory");
    std::fs::create_dir_all(source_path.parent().expect("source parent")).expect("create source directory");
    std::fs::write(
        &managed_path,
        "# This file is auto-generated by alef — DO NOT EDIT.\n# alef:hash:old\n[dependencies]\ncustom = \"1\"\n",
    )
    .expect("write managed manifest");
    let handwritten = "[dependencies]\ncustom = \"1\"\n";
    std::fs::write(&handwritten_path, handwritten).expect("write handwritten manifest");
    std::fs::write(&source_path, "pub fn existing() {}\n").expect("write generated source");

    let files = vec![
        generated(
            "crates/sample-ffi/Cargo.toml",
            "[dependencies]\nserde = { version = \"1\", features = [\"derive\"] }\n",
        ),
        generated(
            "crates/manual/Cargo.toml",
            "[dependencies]\nserde = { version = \"1\", features = [\"derive\"] }\n",
        ),
        generated("crates/sample-ffi/src/lib.rs", "pub fn replaced() {}\n"),
    ];

    let report = reconcile_managed_scaffold_manifests(&files, directory.path()).expect("reconcile manifests");
    let managed = std::fs::read_to_string(&managed_path).expect("read managed manifest");

    assert!(
        managed.contains("serde"),
        "a pristine-clone manifest with Alef's standard header must receive generated dependencies"
    );
    assert!(
        !managed.contains("custom"),
        "managed manifest must match generated content"
    );
    assert_eq!(
        std::fs::read_to_string(&handwritten_path).expect("read handwritten manifest"),
        handwritten,
        "an unmarked manifest must not be claimed or modified",
    );
    assert_eq!(
        std::fs::read_to_string(&source_path).expect("read generated source"),
        "pub fn existing() {}\n",
        "manifest reconciliation must not widen into source regeneration",
    );
    assert_eq!(report.changed_paths, std::collections::HashSet::from([managed_path]));
}

#[test]
fn reconciliation_creates_missing_generated_manifest() {
    let directory = tempfile::tempdir().expect("create temp directory");
    let manifest = generated("crates/sample-ffi/Cargo.toml", "[dependencies]\nserde = \"1\"\n");

    reconcile_managed_scaffold_manifests(&[manifest], directory.path()).expect("reconcile manifest");

    let content =
        std::fs::read_to_string(directory.path().join("crates/sample-ffi/Cargo.toml")).expect("read created manifest");
    assert!(
        content.contains("auto-generated by alef"),
        "new managed manifest must carry Alef's generated header"
    );
    assert!(
        content.contains("serde"),
        "new managed manifest must include generated dependencies"
    );
}