use gix_object::{ TreeRefIter, bstr::ByteSlice, tree::{self, EntryRef}, }; use pretty_assertions::assert_eq; use crate::{fixture_hash_kind, fixture_oid, tree_fixture}; #[test] fn empty() { assert_eq!( TreeRefIter::from_bytes(&[], gix_testtools::object_hash()).count(), 0, "empty trees are definitely ok" ); } #[test] fn error_handling() { let data = tree_fixture("everything.tree").expect("fixture is valid"); let iter = TreeRefIter::from_bytes(&data[..data.len() / 2], fixture_hash_kind()); let entries = iter.collect::>(); assert!( entries.last().expect("at least one token").is_err(), "errors are propagated and none is returned from that point on" ); } #[test] fn offset_to_next_entry() { let hash_kind = fixture_hash_kind(); let buf = tree_fixture("everything.tree").expect("fixture is valid"); let mut iter = TreeRefIter::from_bytes(&buf, hash_kind); assert_eq!(iter.offset_to_next_entry(&buf), 0, "first entry is always at 0"); iter.next(); let actual = iter.offset_to_next_entry(&buf); assert_eq!(actual, 11 + hash_kind.len_in_bytes(), "now the offset increases"); assert_eq!( TreeRefIter::from_bytes(&buf[actual..], hash_kind) .next() .map(|e| e.unwrap().filename), iter.next().map(|e| e.unwrap().filename), "One can now start the iteration at a certain entry" ); } #[test] fn everything() -> crate::Result { assert_eq!( TreeRefIter::from_bytes(&tree_fixture("everything.tree")?, fixture_hash_kind()) .collect::, _>>()?, vec![ EntryRef { mode: tree::EntryKind::BlobExecutable.into(), filename: b"exe".as_bstr(), oid: &fixture_oid("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391") }, EntryRef { mode: tree::EntryKind::Blob.into(), filename: b"file".as_bstr(), oid: &fixture_oid("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391") }, EntryRef { mode: tree::EntryKind::Commit.into(), filename: b"grit-submodule".as_bstr(), oid: &fixture_oid("b2d1b5d684bdfda5f922b466cc13d4ce2d635cf8") }, EntryRef { mode: tree::EntryKind::Tree.into(), filename: b"subdir".as_bstr(), oid: &fixture_oid("4d5fcadc293a348e88f777dc0920f11e7d71441c") }, EntryRef { mode: tree::EntryKind::Link.into(), filename: b"symlink".as_bstr(), oid: &fixture_oid("1a010b1c0f081b2e8901d55307a15c29ff30af0e") } ] ); Ok(()) } #[test] fn leading_space_in_tree_name() -> crate::Result { let oid = fixture_oid("4d5fcadc293a348e88f777dc0920f11e7d71441c"); let mut buf = b"40000 leading space\0".to_vec(); buf.extend_from_slice(oid.as_bytes()); assert_eq!( TreeRefIter::from_bytes(&buf, fixture_hash_kind()).collect::, _>>()?, vec![EntryRef { mode: tree::EntryKind::Tree.into(), filename: b" leading space".as_bstr(), oid: oid.as_ref(), }] ); Ok(()) } mod lookup_entry { use gix_object::tree::EntryKind; use utils::entry; use crate::fixture_hash_kind; #[test] fn top_level_directory() -> crate::Result { assert_eq!( utils::lookup_entry_by_path("bin")?, entry("bin", EntryKind::Blob, fixture_hash_kind().empty_blob()) ); Ok(()) } #[test] fn nested_file() -> crate::Result { assert_eq!( utils::lookup_entry_by_path("file/a")?, entry("a", EntryKind::Blob, fixture_hash_kind().empty_blob()) ); Ok(()) } #[test] fn non_existing_nested_file() -> crate::Result { for path in ["file/does-not-exist", "non-existing", "file/a/through-file"] { let actual = utils::lookup_entry_by_path(path)?; assert_eq!(actual, None); } Ok(()) } mod utils { use gix_object::{FindExt, tree}; use crate::generated_tree_root_id; pub(super) fn entry(filename: &str, mode: tree::EntryKind, oid: gix_hash::ObjectId) -> Option { Some(tree::Entry { mode: mode.into(), filename: filename.into(), oid, }) } pub(super) fn tree_odb() -> gix_testtools::Result { let root = gix_testtools::scripted_fixture_read_only("make_trees.sh")?; Ok(gix_odb::at_opts( root.join(".git/objects"), Vec::new(), gix_odb::store::init::Options { object_hash: crate::fixture_hash_kind(), ..Default::default() }, )?) } pub(super) fn lookup_entry_by_path(path: &str) -> gix_testtools::Result> { let odb = tree_odb()?; let root_tree_id = generated_tree_root_id()?; let mut buf = Vec::new(); let root_tree = odb.find_tree_iter(&root_tree_id, &mut buf)?; let mut buf = Vec::new(); root_tree.lookup_entry_by_path(&odb, &mut buf, path) } } }