makepad/libs/git/tests/object_size.rs

74 lines
3.3 KiB
Rust

//! `Repository::object_size` (header-only sizes) and `Repository::first_parents`.
//! No git binary.
use makepad_git::test_support::{
delta_copy, delta_header, delta_insert, tempdir, write_pack_entries, PackEntry,
};
use makepad_git::*;
use std::fs;
use std::path::Path;
fn init_repo(dir: &Path) -> Repository {
let git = dir.join(".git");
fs::create_dir_all(git.join("objects")).unwrap();
fs::create_dir_all(git.join("refs/heads")).unwrap();
fs::write(git.join("HEAD"), "ref: refs/heads/main\n").unwrap();
Repository::open(dir).unwrap()
}
#[test]
fn object_size_reads_loose_packed_and_delta_headers() {
let dir = tempdir().unwrap();
let mut repo = init_repo(dir.path());
let loose = repo.write_blob(b"loose object\n").unwrap();
let base: Vec<u8> = (0..300u32).map(|i| (i % 251) as u8).collect();
let mut ofs_result = base[..200].to_vec();
ofs_result.extend_from_slice(b"tail");
let mut ofs_delta = delta_header(base.len(), ofs_result.len());
ofs_delta.extend(delta_copy(0, 200));
ofs_delta.extend(delta_insert(b"tail"));
let mut ref_result = b"head".to_vec();
ref_result.extend_from_slice(&base[100..300]);
let mut ref_delta = delta_header(base.len(), ref_result.len());
ref_delta.extend(delta_insert(b"head"));
ref_delta.extend(delta_copy(100, 200));
let base_oid = makepad_git::oid::hash_object("blob", &base);
let ids = write_pack_entries(
&dir.path().join(".git"),
&[
PackEntry::Full(ObjectKind::Blob, base.clone()),
PackEntry::OfsDelta { kind: ObjectKind::Blob, base_index: 0, delta: ofs_delta, result: ofs_result.clone() },
PackEntry::RefDelta { kind: ObjectKind::Blob, base: base_oid, delta: ref_delta, result: ref_result.clone() },
],
)
.unwrap();
assert_eq!(repo.object_size(&loose).unwrap(), 13);
assert_eq!(repo.object_size(&ids[0]).unwrap(), base.len() as u64);
assert_eq!(repo.object_size(&ids[1]).unwrap(), ofs_result.len() as u64);
assert_eq!(repo.object_size(&ids[2]).unwrap(), ref_result.len() as u64);
// Sizes agree with a full read of the same objects.
for oid in [&ids[0], &ids[1], &ids[2], &loose] {
assert_eq!(repo.object_size(oid).unwrap(), repo.read_object(oid).unwrap().data.len() as u64);
}
let missing = ObjectId::from_hex("0123456789012345678901234567890123456789").unwrap();
assert!(matches!(repo.object_size(&missing), Err(GitError::ObjectNotFound(_))));
}
#[test]
fn first_parents_walks_the_first_parent_chain_only() {
let dir = tempdir().unwrap();
let repo = init_repo(dir.path());
let tree = repo.write_tree(&Tree { entries: vec![] }).unwrap();
let commit = |parents: Vec<ObjectId>, message: &str, timestamp: i64| {
let sig = Signature { name: "T".into(), email: "t@example.org".into(), timestamp, tz_offset: "+0000".into() };
repo.write_commit(&Commit { tree, parents, author: sig.clone(), committer: sig, message: message.into() }).unwrap()
};
let root = commit(vec![], "root\n", 1);
let side = commit(vec![root], "side\n", 2);
let main = commit(vec![root], "main\n", 3);
let merge = commit(vec![main, side], "merge\n", 4);
let mut repo = Repository::open(dir.path()).unwrap();
let chain: Vec<ObjectId> = repo.first_parents(merge).map(|item| item.unwrap().0).collect();
assert_eq!(chain, vec![merge, main, root]);
}