rpo 0.1.0-beta.5

Git contribution analysis: commits, file changes, and per-line authorship over time as polars DataFrames
mod helpers;

use helpers::RepoFixture;
use rpo::RepoAnalyzer;

/// `gix::object::tree::diff` emits a Change for the directory tree itself
/// alongside Changes for each contained blob, so any file under
/// `requests/` would normally produce two rows in `file_changes`: one for
/// the directory path `requests` and one for the file. `diff_tree` in
/// `rpo/src/backend/gix.rs` now filters on `entry_mode.is_blob()` so only
/// blob rows survive.
#[test]
fn file_changes_omits_directory_rows() {
    let f = RepoFixture::new();
    f.write("a/b.rs", "fn b() {}\n");
    f.commit("Alice", "alice@a.com", "add a/b");
    f.write("a/b.rs", "fn b() { /* v2 */ }\n");
    f.commit("Alice", "alice@a.com", "edit a/b");
    f.write("a/c.rs", "fn c() {}\n");
    f.commit("Alice", "alice@a.com", "add a/c");

    let analysis = RepoAnalyzer::open(f.path()).unwrap().all().unwrap();
    let paths: Vec<String> = analysis
        .file_changes
        .column("path")
        .unwrap()
        .str()
        .unwrap()
        .iter()
        .filter_map(|o| o.map(|s| s.to_string()))
        .collect();

    assert!(
        !paths.iter().any(|p| p == "a"),
        "directory path 'a' leaked into file_changes: {paths:?}"
    );

    // Sanity: the individual blobs ARE present.
    assert!(
        paths.iter().any(|p| p == "a/b.rs"),
        "missing a/b.rs in {paths:?}"
    );
    assert!(
        paths.iter().any(|p| p == "a/c.rs"),
        "missing a/c.rs in {paths:?}"
    );
}