fix: handle removed files correctly when building working directory tree

This commit is contained in:
Nikita Galaiko 2023-11-08 10:48:09 +01:00 committed by GitButler
parent 35cc2a5870
commit 14b25966e5
2 changed files with 35 additions and 6 deletions

View File

@ -626,7 +626,7 @@ fn build_wd_tree(
.find_reference("refs/heads/current")
{
Result::Ok(reference) => {
// build the working directory tree from the current commit
// re-use the last tree as a base to copy non changed entries
let tree = reference.peel_to_tree()?;
let wd_tree_entry = tree.get_name("wd").unwrap();
let wd_tree = gb_repository.git_repository.find_tree(wd_tree_entry.id())?;
@ -637,7 +637,7 @@ fn build_wd_tree(
.list_files(&path::PathBuf::from("."))
.context("failed to read session wd files")?;
// the session files on top of it
// write the session files on top of the last tree
for file_path in &session_wd_files {
let abs_path = gb_repository.session_wd_path().join(file_path);
let metadata = abs_path.metadata().with_context(|| {
@ -698,12 +698,12 @@ fn build_wd_tree(
})?;
}
// remove deleted files from the index
// remove deleted files from the last tree
wd_tree.walk(git2::TreeWalkMode::PreOrder, |root, entry| {
if let Some(name) = &entry.name() {
let full_path = path::Path::new(root).join(name);
let exists = session_wd_files.contains(&full_path);
if !exists && index.remove_path(&full_path).is_err() {
let rel_path = path::Path::new(root).join(name);
let full_path = project_repository.path().join(&rel_path);
if !full_path.exists() && index.remove_path(&rel_path).is_err() {
return TreeWalkResult::Abort;
}
}

View File

@ -423,6 +423,35 @@ mod test {
Ok(())
}
#[test]
fn test_register_no_changes_saved_thgoughout_flushes() -> Result<()> {
let suite = Suite::default();
let Case {
gb_repository,
project_repository,
project,
..
} = suite.new_case();
let listener = Handler::from(&suite.local_app_data);
// file change, wd and deltas are written
std::fs::write(project.path.join("test.txt"), "test")?;
listener.handle("test.txt", &project.id)?;
// make two more sessions.
gb_repository.flush(&project_repository, None)?;
gb_repository.get_or_create_current_session()?;
gb_repository.flush(&project_repository, None)?;
// after some sessions, files from the first change are still there.
let session = gb_repository.get_or_create_current_session()?;
let session_reader = sessions::Reader::open(&gb_repository, &session)?;
let files = session_reader.files(None)?;
assert_eq!(files.len(), 1);
Ok(())
}
#[test]
fn test_register_new_file_twice() -> Result<()> {
let suite = Suite::default();