945 lines · 43.6 KB · Rust
RawDownload
mod changes {    mod to_obtain_tree {        use std::collections::HashMap;         use gix_diff::tree::{            recorder,            recorder::{Change::*, Location},            visit::Relation,        };        use gix_hash::{ObjectId, oid};        use gix_object::{TreeRefIter, bstr::ByteSlice, tree::EntryKind};        use gix_odb::pack::Find;         use crate::hex_to_id;         type Changes = Vec<recorder::Change>;         fn db(args: impl IntoIterator<Item = &'static str>) -> crate::Result<gix_odb::Handle> {            crate::open_odb(                crate::scripted_fixture_read_only_with_args("make_diff_repo.sh", args)?                    .join(".git")                    .join("objects"),            )            .map_err(Into::into)        }         fn locate_tree_by_commit<'a>(            db: &gix_odb::Handle,            commit: &oid,            buf: &'a mut Vec<u8>,        ) -> crate::Result<TreeRefIter<'a>> {            let tree_id = db                .try_find(commit, buf)?                .ok_or_else(|| format!("start commit {commit:?} to be present"))?                .0                .decode()?                .into_commit()                .expect("id is actually a commit")                .tree();             Ok(db                .try_find(&tree_id, buf)?                .expect("main tree present")                .0                .try_into_tree_iter()                .expect("id to be a tree"))        }         fn diff_commits(            db: &gix_odb::Handle,            lhs: impl Into<Option<ObjectId>>,            rhs: &oid,            location: Option<Location>,        ) -> crate::Result<Changes> {            let mut buf = Vec::new();            let lhs_tree = lhs                .into()                .and_then(|lhs| locate_tree_by_commit(db, &lhs, &mut buf).ok());            let mut buf2 = Vec::new();            let rhs_tree = locate_tree_by_commit(db, rhs, &mut buf2)?;            let mut recorder = gix_diff::tree::Recorder::default().track_location(location);            gix_diff::tree(                lhs_tree.unwrap_or_default(),                rhs_tree,                gix_diff::tree::State::default(),                db,                &mut recorder,            )?;            Ok(recorder.records)        }         fn diff_with_previous_commit_from(db: &gix_odb::Handle, commit_id: &oid) -> crate::Result<Changes> {            let mut buf = Vec::new();            let (main_tree_id, parent_commit_id) = {                let commit = db                    .try_find(commit_id, &mut buf)?                    .ok_or_else(|| format!("start commit {commit_id:?} to be present"))?                    .0                    .decode()?                    .into_commit()                    .expect("id is actually a commit");                 (commit.tree(), commit.parents().next())            };            let current_tree = db                .try_find(&main_tree_id, &mut buf)?                .expect("main tree present")                .0                .try_into_tree_iter()                .expect("id to be a tree");            let mut buf2 = Vec::new();            let previous_tree: Option<_> = {                parent_commit_id                    .and_then(|id| db.try_find(&id, &mut buf2).ok().flatten())                    .and_then(|(c, _l)| c.decode().ok())                    .and_then(gix_object::ObjectRef::into_commit)                    .map(|c| c.tree())                    .and_then(|tree| db.try_find(&tree, &mut buf2).ok().flatten())                    .and_then(|(tree, _)| tree.try_into_tree_iter())            };             let mut recorder = gix_diff::tree::Recorder::default();            gix_diff::tree(                previous_tree.unwrap_or_default(),                current_tree,                &mut gix_diff::tree::State::default(),                db,                &mut recorder,            )?;            Ok(recorder.records)        }         fn head_of(db: &gix_odb::Handle) -> ObjectId {            ObjectId::from_hex(                std::fs::read(                    db.store_ref()                        .path()                        .parent()                        .unwrap()                        .join("refs")                        .join("heads")                        .join("main"),                )                .expect("head ref")                .as_bstr()                .trim(),            )            .expect("valid hex id")        }         fn all_commits(db: &gix_odb::Handle) -> HashMap<String, ObjectId> {            let mut buf = Vec::new();             let head = head_of(db);            gix_traverse::commit::Simple::new(Some(head), &db)                .collect::<Result<Vec<_>, _>>()                .expect("valid iteration")                .into_iter()                .map(|c| {                    use gix_object::FindExt;                    (                        db.find_commit(&c.id, &mut buf)                            .unwrap()                            .message                            .trim()                            .to_str_lossy()                            .into_owned(),                        c.id,                    )                })                .rev()                .collect()        }         #[test]        fn many_different_states() -> crate::Result {            let db = db(None)?;            let all_commits = all_commits(&db);            pretty_assertions::assert_eq!(                diff_with_previous_commit_from(&db, &all_commits["f added"])?,                vec![Addition {                    entry_mode: EntryKind::Blob.into(),                    oid: hex_to_id(                        "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",                        "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"                    ),                    path: "f".into(),                    relation: None                }],                ":000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A      f"            );             pretty_assertions::assert_eq!(                diff_with_previous_commit_from(&db, &all_commits["f modified"])?,                vec![Modification {                    previous_entry_mode: EntryKind::Blob.into(),                    previous_oid: hex_to_id(                        "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",                        "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"                    ),                    entry_mode: EntryKind::Blob.into(),                    oid: hex_to_id(                        "28ce6a8b26aa170e1de65536fe8abe1832bd3242",                        "6ca8d4e3bc5df874055e542d18505b5a5efa0fb7d65776efedc13781073ed0f1"                    ),                    path: "f".into()                }],                ":100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 28ce6a8b26aa170e1de65536fe8abe1832bd3242 M      f"            );             pretty_assertions::assert_eq!(                diff_with_previous_commit_from(&db, &all_commits["f deleted"])?,                vec![Deletion {                    entry_mode: EntryKind::Blob.into(),                    oid: hex_to_id(                        "28ce6a8b26aa170e1de65536fe8abe1832bd3242",                        "6ca8d4e3bc5df874055e542d18505b5a5efa0fb7d65776efedc13781073ed0f1"                    ),                    path: "f".into(),                    relation: None                }],                ":100644 000000 28ce6a8b26aa170e1de65536fe8abe1832bd3242 0000000000000000000000000000000000000000 D	f            "            );             pretty_assertions::assert_eq!(                diff_with_previous_commit_from(&db, &all_commits["f mode modified to dir f/"])?,                vec![                    Deletion {                        entry_mode: EntryKind::Blob.into(),                        oid: hex_to_id("28ce6a8b26aa170e1de65536fe8abe1832bd3242", "6ca8d4e3bc5df874055e542d18505b5a5efa0fb7d65776efedc13781073ed0f1"),                        path: "f".into(),                        relation: None                    },                    Addition {                        entry_mode: EntryKind::Tree.into(),                        oid: hex_to_id("10f2f4b82222d2b5c31985130979a91fd87410f7", "9e220e584599b9cff376b638fa71675280f4582a87138b6be425258dbb85f94c"),                        path: "f".into(),                        relation: Some(Relation::Parent(1)),                    },                    Addition {                        entry_mode: EntryKind::Blob.into(),                        oid: hex_to_id("28ce6a8b26aa170e1de65536fe8abe1832bd3242", "6ca8d4e3bc5df874055e542d18505b5a5efa0fb7d65776efedc13781073ed0f1"),                        path: "f/f".into(),                        relation: Some(Relation::ChildOfParent(1)),                    }                ],                ":100644 000000 28ce6a8b26aa170e1de65536fe8abe1832bd3242 0000000000000000000000000000000000000000 D      f                   :000000 100644 0000000000000000000000000000000000000000 28ce6a8b26aa170e1de65536fe8abe1832bd3242 A      f/f"            );             pretty_assertions::assert_eq!(                diff_with_previous_commit_from(&db, &all_commits["a renamed to b"])?,                vec![                    Deletion {                        entry_mode: EntryKind::Blob.into(),                        oid: hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"),                        path: "a".into(),                        relation: None                    },                    Addition {                        entry_mode: EntryKind::Blob.into(),                        oid: hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"),                        path: "b".into(),                        relation: None                    }                ],                "simple rename, same level                 :100644 000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 D      a                 :000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A      b"             );             pretty_assertions::assert_eq!(                diff_with_previous_commit_from(&db, &all_commits["f/f modified"])?,                vec![                    Modification {                        previous_entry_mode: EntryKind::Tree.into(),                        previous_oid: hex_to_id(                            "10f2f4b82222d2b5c31985130979a91fd87410f7",                            "9e220e584599b9cff376b638fa71675280f4582a87138b6be425258dbb85f94c"                        ),                        entry_mode: EntryKind::Tree.into(),                        oid: hex_to_id(                            "ebbe0b3000afdfd1aed15000094b59a2800328eb",                            "ca3ee6fe1455fc077ae53f0fe7af54153feb35d52a892b1377e9c0b6828428d4"                        ),                        path: "f".into()                    },                    Modification {                        previous_entry_mode: EntryKind::Blob.into(),                        previous_oid: hex_to_id(                            "28ce6a8b26aa170e1de65536fe8abe1832bd3242",                            "6ca8d4e3bc5df874055e542d18505b5a5efa0fb7d65776efedc13781073ed0f1"                        ),                        entry_mode: EntryKind::Blob.into(),                        oid: hex_to_id(                            "13c2aca72ab576cb5f22dc8e7f8ba8ddab553a8a",                            "ab879bd65609705434bab6bc157306769fd1053c6d86d82c89e76df9bee62809"                        ),                        path: "f/f".into()                    },                ],                ":100644 100644 28ce6a8b26aa170e1de65536fe8abe1832bd3242 13c2aca72ab576cb5f22dc8e7f8ba8ddab553a8a M	f/f"            );             let tree_with_link_id = hex_to_id(                "7e26dba59b6336f87d1d4ae3505a2da302b91c76",                "825cbacedb89cffe4fd6532846f376ab9cb8bc9e5cb399620d3592b714c2e95f",            );            let link_entry_oid = hex_to_id(                "2e65efe2a145dda7ee51d1741299f848e5bf752e",                "eb337bcee2061c5313c9a1392116b6c76039e9e30d71467ae359b36277e17dc7",            );            let link_entry_mode = EntryKind::Link;            pretty_assertions::assert_eq!(                diff_with_previous_commit_from(&db, &all_commits["f/f mode changed to link"])?,                vec![                    Modification {                        previous_entry_mode: EntryKind::Tree.into(),                        previous_oid: hex_to_id(                            "849bd76db90b65ebbd2e6d3970ca70c96ee5592c",                            "003781d2cca9a680f5ccfe0963614bb813dea1654968713b48a6a27490c3771e"                        ),                        entry_mode: EntryKind::Tree.into(),                        oid: tree_with_link_id,                        path: "f".into()                    },                    Modification {                        previous_entry_mode: EntryKind::Blob.into(),                        previous_oid: hex_to_id(                            "13c2aca72ab576cb5f22dc8e7f8ba8ddab553a8a",                            "ab879bd65609705434bab6bc157306769fd1053c6d86d82c89e76df9bee62809"                        ),                        entry_mode: link_entry_mode.into(),                        oid: link_entry_oid,                        path: "f/f".into()                    },                ],                ":100644 120000 13c2aca72ab576cb5f22dc8e7f8ba8ddab553a8a 2e65efe2a145dda7ee51d1741299f848e5bf752e T	f/f"            );             pretty_assertions::assert_eq!(                diff_with_previous_commit_from(&db, &all_commits["f/ changed into file f"])?,                vec![                    Addition {                        entry_mode: EntryKind::Blob.into(),                        oid: hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"),                        path: "f".into(),                        relation: None                    },                    Deletion {                        entry_mode: EntryKind::Tree.into(),                        oid: tree_with_link_id,                        path: "f".into(),                        relation: Some(Relation::Parent(1))                    },                    Deletion {                        entry_mode: EntryKind::Blob.into(),                        oid: hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"),                        path: "f/a".into(),                        relation: Some(Relation::ChildOfParent(1))                    },                    Deletion {                        entry_mode: EntryKind::Blob.into(),                        oid: hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"),                        path: "f/b".into(),                        relation: Some(Relation::ChildOfParent(1))                    },                    Deletion {                        entry_mode: link_entry_mode.into(),                        oid: link_entry_oid,                        path: "f/f".into(),                        relation: Some(Relation::ChildOfParent(1))                    },                ],                ":000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A	f                 :100644 000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 D	f/a                 :100644 000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 D	f/b                 :120000 000000 2e65efe2a145dda7ee51d1741299f848e5bf752e 0000000000000000000000000000000000000000 D	f/f"            );            pretty_assertions::assert_eq!(                diff_with_previous_commit_from(&db, &all_commits["delete d/"])?,                vec![                    Deletion {                        entry_mode: EntryKind::Tree.into(),                        oid: hex_to_id(                            "3d5a503f4062d198b443db5065ca727f8354e7df",                            "1f5422fc234c61cf503a86521bcafcb86cc48653c5d80d4e93a6cc677e345b40"                        ),                        path: "d".into(),                        relation: Some(Relation::Parent(1))                    },                    Deletion {                        entry_mode: EntryKind::Blob.into(),                        oid: hex_to_id(                            "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",                            "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"                        ),                        path: "d/f".into(),                        relation: Some(Relation::ChildOfParent(1))                    },                ],                ":100644 000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 D	d/f"            );            let empty_blob_id = hex_to_id(                "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",                "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813",            );            pretty_assertions::assert_eq!(                diff_with_previous_commit_from(&db, &all_commits["add /c /d /e"])?,                vec![                    Addition {                        entry_mode: EntryKind::Blob.into(),                        oid: empty_blob_id,                        path: "c".into(),                        relation: None,                    },                    Addition {                        entry_mode: EntryKind::Blob.into(),                        oid: empty_blob_id,                        path: "d".into(),                        relation: None,                    },                    Addition {                        entry_mode: EntryKind::Blob.into(),                        oid: empty_blob_id,                        path: "e".into(),                        relation: None,                    },                ],                ":000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A	c                 :000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A	d                 :000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A	e"            );            pretty_assertions::assert_eq!(                diff_with_previous_commit_from(&db, &all_commits["add g/a"])?,                vec![                    Addition {                        entry_mode: EntryKind::Tree.into(),                        oid: hex_to_id(                            "496d6428b9cf92981dc9495211e6e1120fb6f2ba",                            "5f6f307bcc469c02acba4f7da42d8d4defdda8209777fe732956f1e2fa0db3ff"                        ),                        path: "g".into(),                        relation: Some(Relation::Parent(1))                    },                    Addition {                        entry_mode: EntryKind::Blob.into(),                        oid: hex_to_id(                            "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",                            "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"                        ),                        path: "g/a".into(),                        relation: Some(Relation::ChildOfParent(1))                    },                ],                ":000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A	g/a"            );            pretty_assertions::assert_eq!(                diff_with_previous_commit_from(&db, &all_commits["remove /c /d /e"])?,                vec![                    Deletion {                        entry_mode: EntryKind::Blob.into(),                        oid: empty_blob_id,                        path: "c".into(),                        relation: None                    },                    Deletion {                        entry_mode: EntryKind::Blob.into(),                        oid: empty_blob_id,                        path: "d".into(),                        relation: None                    },                    Deletion {                        entry_mode: EntryKind::Blob.into(),                        oid: empty_blob_id,                        path: "e".into(),                        relation: None                    },                ],                ":100644 000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 D	c                 :100644 000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 D	d                 :100644 000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 D	e"            );            pretty_assertions::assert_eq!(                diff_with_previous_commit_from(&db, &all_commits["rm /f, add /ff"])?,                vec![                    Deletion {                        entry_mode: EntryKind::Blob.into(),                        oid: hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"),                        path: "f".into(),                        relation: None                    },                    Addition {                        entry_mode: EntryKind::Blob.into(),                        oid: hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"),                        path: "ff".into(),                        relation: None                    },                ],                ":100644 000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 D	f                  :000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A	ff"            );            pretty_assertions::assert_eq!(                diff_with_previous_commit_from(&db, &all_commits["rm g/a, add g/aa"])?,                vec![                    Modification {                        previous_entry_mode: EntryKind::Tree.into(),                        previous_oid: hex_to_id("496d6428b9cf92981dc9495211e6e1120fb6f2ba", "5f6f307bcc469c02acba4f7da42d8d4defdda8209777fe732956f1e2fa0db3ff"),                        entry_mode: EntryKind::Tree.into(),                        oid: hex_to_id("6e5931346904b020301f74f581142826eacc4678", "c56aa83b78552302a7ab7c6377d8a54573a3845e10242df3eae849394ab91b53"),                        path: "g".into()                    },                    Deletion {                        entry_mode: EntryKind::Blob.into(),                        oid: hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", "473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813"),                        path: "g/a".into(),                        relation: None                    },

Lines 1–500 of 945.