mod locate { use bstr::ByteSlice; use git_object::Kind; use git_odb::pack; use crate::{fixture_path, hex_to_id, pack::SMALL_PACK_INDEX}; fn locate<'a>(hex_id: &str, out: &'a mut Vec) -> git_object::Data<'a> { let bundle = pack::Bundle::at(fixture_path(SMALL_PACK_INDEX), git_hash::Kind::Sha1).expect("pack and idx"); bundle .find(hex_to_id(hex_id), out, &mut pack::cache::Never) .expect("read success") .expect("id present") .0 } mod locate_and_verify { use git_odb::pack; use crate::{fixture_path, pack::PACKS_AND_INDICES}; #[test] fn all() -> Result<(), Box> { for (index_path, data_path) in PACKS_AND_INDICES { // both paths are equivalent pack::Bundle::at(fixture_path(index_path), git_hash::Kind::Sha1)?; let bundle = pack::Bundle::at(fixture_path(data_path), git_hash::Kind::Sha1)?; let mut buf = Vec::new(); for entry in bundle.index.iter() { let (obj, _location) = bundle .find(entry.oid, &mut buf, &mut pack::cache::Never)? .expect("id present"); obj.verify_checksum(entry.oid)?; } } Ok(()) } } #[test] fn blob() -> Result<(), Box> { let mut out = Vec::new(); let obj = locate("bd46bb3f5bb4ca5431770c4fde0735fb89d382f3", &mut out); assert_eq!( obj.data.as_bstr(), b"GitPython is a python library used to interact with Git repositories.\n\nHi there\n".as_bstr() ); assert_eq!(obj.kind, Kind::Blob); let object = obj.decode()?; assert_eq!(object.kind(), Kind::Blob); assert_eq!(object.as_blob().expect("blob").data, obj.data); Ok(()) } #[test] fn tree() -> Result<(), Box> { let mut out = Vec::new(); let obj = locate("e90926b07092bccb7bf7da445fae6ffdfacf3eae", &mut out); assert_eq!(obj.kind, Kind::Tree); assert_eq!(obj.decode()?.kind(), Kind::Tree); Ok(()) } #[test] fn commit() -> Result<(), Box> { let mut out = Vec::new(); let obj = locate("779c5451ba9fe210ffd1f55db202e55f51acecac", &mut out); assert_eq!(obj.kind, Kind::Commit); assert_eq!(obj.decode()?.kind(), Kind::Commit); Ok(()) } } mod write_to_directory { use std::{fs, path::Path, sync::atomic::AtomicBool}; use git_features::progress; use git_odb::pack; use tempfile::TempDir; use crate::{ fixture_path, pack::{SMALL_PACK, SMALL_PACK_INDEX}, }; fn expected_outcome() -> Result> { Ok(pack::bundle::write::Outcome { index: pack::index::write::Outcome { index_version: pack::index::Version::V2, index_hash: git_hash::ObjectId::from_hex(b"544a7204a55f6e9cacccf8f6e191ea8f83575de3")?, data_hash: git_hash::ObjectId::from_hex(b"0f3ea84cd1bba10c2a03d736a460635082833e59")?, num_objects: 42, }, pack_version: pack::data::Version::V2, index_path: None, data_path: None, keep_path: None, object_hash: git_hash::Kind::Sha1, }) } #[test] fn without_providing_one() -> Result<(), Box> { let res = write_pack(None::<&Path>, SMALL_PACK)?; assert_eq!(res, expected_outcome()?); assert_eq!( res.index.index_hash, pack::index::File::at(fixture_path(SMALL_PACK_INDEX), git_hash::Kind::Sha1)?.index_checksum() ); assert!(res.to_bundle().is_none()); Ok(()) } #[test] fn given_a_directory() -> Result<(), Box> { let dir = TempDir::new()?; let mut res = write_pack(Some(&dir), SMALL_PACK)?; let (index_path, data_path, keep_path) = (res.index_path.take(), res.data_path.take(), res.keep_path.take()); assert_eq!(res, expected_outcome()?); let mut sorted_entries = fs::read_dir(&dir)?.filter_map(Result::ok).collect::>(); sorted_entries.sort_by_key(|e| e.file_name()); assert_eq!( sorted_entries.len(), 3, "we want a pack and the corresponding index and the keep file" ); let pack_hash = res.index.data_hash.to_hex(); assert_eq!(file_name(&sorted_entries[0]), format!("pack-{}.idx", pack_hash)); assert_eq!(Some(sorted_entries[0].path()), index_path); assert_eq!(file_name(&sorted_entries[1]), format!("pack-{}.keep", pack_hash)); assert_eq!(Some(sorted_entries[1].path()), keep_path); assert_eq!(file_name(&sorted_entries[2]), format!("pack-{}.pack", pack_hash)); assert_eq!(Some(sorted_entries[2].path()), data_path); res.index_path = index_path; assert!(res.to_bundle().transpose()?.is_some()); Ok(()) } fn file_name(entry: &fs::DirEntry) -> String { entry.path().file_name().unwrap().to_str().unwrap().to_owned() } fn write_pack( directory: Option>, pack_file: &str, ) -> Result> { let pack_file = fs::File::open(fixture_path(pack_file))?; static SHOULD_INTERRUPT: AtomicBool = AtomicBool::new(false); pack::Bundle::write_to_directory_eagerly( pack_file, None, directory, progress::Discard, &SHOULD_INTERRUPT, None, pack::bundle::write::Options { thread_limit: None, iteration_mode: pack::data::input::Mode::Verify, index_version: pack::index::Version::V2, object_hash: git_hash::Kind::Sha1, }, ) .map_err(Into::into) } }