index.add_frombuffer
not adding index unless flags changedΒ #1086
Open
Description
I was writing some tests for our index resolving code, and noticed that when we're calling index.add_frombuffer
if we don't clear the flags of our our
IndexEntry, the tree that we write out ends up with that file missing.
Repro:
main.rs
use std::{
fs,
path::{Path, PathBuf},
};
use git2::IndexConflict;
use tempfile::tempdir;
/// Commit whatever is in the current working directory
fn commit<'a>(
repository: &'a git2::Repository,
parent: Option<&git2::Commit<'a>>,
) -> git2::Commit<'a> {
let signature = git2::Signature::now("Caleb", "caleb@gitbutler.com").unwrap();
let mut index = repository.index().unwrap();
// Make sure we're not having weird cached state
index.read(true).unwrap();
index
.add_all(["*"], git2::IndexAddOption::DEFAULT, None)
.unwrap();
let commit = repository
.commit(
None,
&signature,
&signature,
"Committee",
&repository.find_tree(index.write_tree().unwrap()).unwrap(),
parent.map(|c| vec![c]).unwrap_or_default().as_slice(),
)
.unwrap();
repository.find_commit(commit).unwrap()
}
fn bytes_to_path(path: &[u8]) -> PathBuf {
let path = std::str::from_utf8(path).unwrap();
Path::new(path).to_owned()
}
fn in_memory_repository(repository: &git2::Repository) -> git2::Repository {
let repository = git2::Repository::open(repository.path()).unwrap();
repository
.odb()
.unwrap()
.add_new_mempack_backend(999)
.unwrap();
repository
}
fn main() {
let tempdir = tempdir().unwrap();
let repository = git2::Repository::init(tempdir.path()).unwrap();
// Make some commits
fs::write(tempdir.path().join("foo.txt"), "a").unwrap();
let a = commit(&repository, None);
fs::write(tempdir.path().join("foo.txt"), "b").unwrap();
let b = commit(&repository, None);
fs::write(tempdir.path().join("foo.txt"), "c").unwrap();
let c = commit(&repository, None);
let in_memory_repository = in_memory_repository(&repository);
let mut index: git2::Index = repository
.merge_trees(
&a.tree().unwrap(), // Base
&b.tree().unwrap(), // Ours
&c.tree().unwrap(), // Theirs
None,
)
.unwrap();
in_memory_repository.set_index(&mut index).unwrap();
assert!(index.has_conflicts());
let mut conflicts = index.conflicts().unwrap().flatten().collect::<Vec<_>>();
assert_eq!(conflicts.len(), 1);
let conflict = conflicts.first_mut().unwrap();
let IndexConflict {
ancestor: Some(ancestor),
our: Some(our),
their: Some(their),
} = conflict
else {
panic!("Ahh");
};
index.remove_path(&bytes_to_path(&ancestor.path)).unwrap();
index.remove_path(&bytes_to_path(&their.path)).unwrap();
let blob = repository.find_blob(our.id).unwrap();
// our.flags = 0;
index.add_frombuffer(&our, blob.content()).unwrap();
let tree = index.write_tree_to(&repository).unwrap();
repository.find_tree(tree).unwrap();
assert_eq!(
tree,
git2::Oid::from_str("6e4760ce692776132d52ac0787b7dc1ca2ac15f4").unwrap()
) // Ends up being 4b825dc642cb6eb9a060e54bf8d69288fbee4904 (empty tree)
}
Cargo.toml
[package]
name = "strange_behaviour"
version = "0.1.0"
edition = "2021"
[dependencies]
git2 = { version = "0.19.0", features = [
"vendored-openssl",
"vendored-libgit2",
] }
tempfile = "3.10"
If we set our.flags
to 0 ourselves, before we call add_frombuffer, then we end up with the tree that we expected.
It's a bit strange that we're ending up with this empty tree rather than having some form of error
Metadata
Assignees
Labels
No labels