Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/nornir

crates/mimir-ingest/tests/ingest/git_walk.rs

//! The git half on its own: first-parent walk from an offset, merges seen as
//! ONE event, classification by diff against the first parent.



use super::common::Scratch;
use mimir_ingest::git::{Change, classify, first_parent_since};

/// Move `refs/heads/main` back to `sha` (the side commit stays reachable only
/// through the merge made next).
fn reset_main(root: &std::path::Path, sha: &str) {
    nornir_git::gitio::point_head_at_branch(root, "main", sha).unwrap();
}

/// A merge commit on main: parents [HEAD, side], tree = side's tree.
fn merge(root: &std::path::Path, side: &str, msg: &str) -> String {
    let repo = gix::open(root).unwrap();
    let head = repo.head_commit().unwrap().id;
    let side_id = gix::ObjectId::from_hex(side.as_bytes()).unwrap();
    let tree = repo.find_commit(side_id).unwrap().tree_id().unwrap().detach();
    let sig = gix::actor::SignatureRef {
        name: "fixture".into(),
        email: "fixture@nornir.invalid".into(),
        time: "1700000100 +0000",
    };
    repo.commit_as(sig, sig, "HEAD", msg, tree, [head, side_id]).unwrap().to_string()
}

#[test]
fn first_parent_walk_skips_branch_internal_commits_and_resumes_from_offset() {
    let tmp = tempfile::tempdir().unwrap();
    let src = Scratch::new(tmp.path().join("r"));
    src.write("src/lib.rs", "fn a() {}\n");
    let c1 = src.commit("c1");
    src.write("README.md", "docs\n");
    let c2 = src.commit("c2 docs");
    // A side commit (branch-internal), then main is put back and merges it.
    src.write("src/lib.rs", "fn a() { side() }\n");
    let side = src.commit("side work");
    reset_main(&src.root, &c2);
    let m = merge(&src.root, &side, "merge side");
    src.write("docs/x.md", "more docs\n");
    let c4 = src.commit("c4 docs");

    let all = first_parent_since(&src.root, "main", None).unwrap();
    assert_eq!(all, vec![c1.clone(), c2.clone(), m.clone(), c4.clone()], "side commit must not be an event");
    assert_eq!(first_parent_since(&src.root, "main", Some(&c2)).unwrap(), vec![m.clone(), c4.clone()]);
    assert!(first_parent_since(&src.root, "main", Some(&c4)).unwrap().is_empty());

    // An offset that is not on the first-parent chain is refused, not guessed.
    let err = first_parent_since(&src.root, "main", Some(&side)).unwrap_err();
    assert!(format!("{err:#}").contains("not on the first-parent chain"), "{err:#}");

    assert_eq!(classify(&src.root, &c1).unwrap(), Change::Code, "root commit diffs against the empty tree");
    assert_eq!(classify(&src.root, &c2).unwrap(), Change::DocsOnly);
    assert_eq!(classify(&src.root, &m).unwrap(), Change::Code, "the merge brings side's .rs change");
    assert_eq!(classify(&src.root, &c4).unwrap(), Change::DocsOnly);
}

#[test]
fn manifest_lock_and_toolchain_changes_are_code() {
    let tmp = tempfile::tempdir().unwrap();
    let src = Scratch::new(tmp.path().join("r"));
    src.write("README.md", "x\n");
    let root = src.commit("root docs");
    assert_eq!(classify(&src.root, &root).unwrap(), Change::DocsOnly);
    for (path, text) in [
        ("crates/a/Cargo.toml", "[package]\n"),
        ("Cargo.lock", "# lock\n"),
        ("rust-toolchain.toml", "[toolchain]\n"),
        ("crates/a/build.rs", "fn main() {}\n"),
    ] {
        src.write(path, text);
        let sha = src.commit(path);
        assert_eq!(classify(&src.root, &sha).unwrap(), Change::Code, "{path}");
    }
}