git: Handle buffer file path changes (#41944)
Update `GitStore.on_buffer_store_event` so that, when a `BufferStoreEvent::BufferChangedFilePath` event is received, we check if there's any diff state for the buffer and, if so, update it according to the new file path, in case the file exists in the repository. Closes #40499 Release Notes: - Fixed issue with git diff tracking when updating a buffer's file from an untracked to a tracked file
This commit is contained in:
@@ -10045,6 +10045,120 @@ async fn test_repository_deduplication(cx: &mut gpui::TestAppContext) {
|
||||
pretty_assertions::assert_eq!(repos, [Path::new(path!("/root/project")).into()]);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_buffer_changed_file_path_updates_git_diff(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx);
|
||||
|
||||
let file_1_committed = String::from(r#"file_1_committed"#);
|
||||
let file_1_staged = String::from(r#"file_1_staged"#);
|
||||
let file_2_committed = String::from(r#"file_2_committed"#);
|
||||
let file_2_staged = String::from(r#"file_2_staged"#);
|
||||
let buffer_contents = String::from(r#"buffer"#);
|
||||
|
||||
let fs = FakeFs::new(cx.background_executor.clone());
|
||||
fs.insert_tree(
|
||||
path!("/dir"),
|
||||
json!({
|
||||
".git": {},
|
||||
"src": {
|
||||
"file_1.rs": file_1_committed.clone(),
|
||||
"file_2.rs": file_2_committed.clone(),
|
||||
}
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
fs.set_head_for_repo(
|
||||
path!("/dir/.git").as_ref(),
|
||||
&[
|
||||
("src/file_1.rs", file_1_committed.clone()),
|
||||
("src/file_2.rs", file_2_committed.clone()),
|
||||
],
|
||||
"deadbeef",
|
||||
);
|
||||
fs.set_index_for_repo(
|
||||
path!("/dir/.git").as_ref(),
|
||||
&[
|
||||
("src/file_1.rs", file_1_staged.clone()),
|
||||
("src/file_2.rs", file_2_staged.clone()),
|
||||
],
|
||||
);
|
||||
|
||||
let project = Project::test(fs.clone(), [path!("/dir").as_ref()], cx).await;
|
||||
|
||||
let buffer = project
|
||||
.update(cx, |project, cx| {
|
||||
project.open_local_buffer(path!("/dir/src/file_1.rs"), cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit([(0..buffer.len(), buffer_contents.as_str())], None, cx);
|
||||
});
|
||||
|
||||
let unstaged_diff = project
|
||||
.update(cx, |project, cx| {
|
||||
project.open_unstaged_diff(buffer.clone(), cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cx.run_until_parked();
|
||||
|
||||
unstaged_diff.update(cx, |unstaged_diff, _cx| {
|
||||
let base_text = unstaged_diff.base_text_string().unwrap();
|
||||
assert_eq!(base_text, file_1_staged, "Should start with file_1 staged");
|
||||
});
|
||||
|
||||
// Save the buffer as `file_2.rs`, which should trigger the
|
||||
// `BufferChangedFilePath` event.
|
||||
project
|
||||
.update(cx, |project, cx| {
|
||||
let worktree_id = project.worktrees(cx).next().unwrap().read(cx).id();
|
||||
let path = ProjectPath {
|
||||
worktree_id,
|
||||
path: rel_path("src/file_2.rs").into(),
|
||||
};
|
||||
project.save_buffer_as(buffer.clone(), path, cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cx.run_until_parked();
|
||||
|
||||
// Verify that the diff bases have been updated to file_2's contents due to
|
||||
// the `BufferChangedFilePath` event being handled.
|
||||
unstaged_diff.update(cx, |unstaged_diff, cx| {
|
||||
let snapshot = buffer.read(cx).snapshot();
|
||||
let base_text = unstaged_diff.base_text_string().unwrap();
|
||||
assert_eq!(
|
||||
base_text, file_2_staged,
|
||||
"Diff bases should be automatically updated to file_2 staged content"
|
||||
);
|
||||
|
||||
let hunks: Vec<_> = unstaged_diff.hunks(&snapshot, cx).collect();
|
||||
assert!(!hunks.is_empty(), "Should have diff hunks for file_2");
|
||||
});
|
||||
|
||||
let uncommitted_diff = project
|
||||
.update(cx, |project, cx| {
|
||||
project.open_uncommitted_diff(buffer.clone(), cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cx.run_until_parked();
|
||||
|
||||
uncommitted_diff.update(cx, |uncommitted_diff, _cx| {
|
||||
let base_text = uncommitted_diff.base_text_string().unwrap();
|
||||
assert_eq!(
|
||||
base_text, file_2_committed,
|
||||
"Uncommitted diff should compare against file_2 committed content"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async fn search(
|
||||
project: &Entity<Project>,
|
||||
query: SearchQuery,
|
||||
|
||||
Reference in New Issue
Block a user