Fix Project Panel select_next_git_entry
action (#24217)
## Context I noticed that the project panel `select_next_git_entry` wasn't behaving correctly. Turns out it was searching in reverse, which caused the action to select itself or the last entry. This PR corrects the behavior and adds a unit test that should stop regressions. Note: Since select next/prev git entry uses the same function as select next/prev diagnostic, the test partially works for that as well. Release Notes: - Fix bug where `select_next_git_entry` project panel action would only select a previous entry or the currently selected entry. --------- Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
parent
c5913899d9
commit
d83c316e6d
2 changed files with 282 additions and 2 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -7184,7 +7184,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -1866,7 +1866,7 @@ impl ProjectPanel {
|
||||||
) {
|
) {
|
||||||
let selection = self.find_entry(
|
let selection = self.find_entry(
|
||||||
self.selection.as_ref(),
|
self.selection.as_ref(),
|
||||||
true,
|
false,
|
||||||
|entry, worktree_id| {
|
|entry, worktree_id| {
|
||||||
(self.selection.is_none()
|
(self.selection.is_none()
|
||||||
|| self.selection.is_some_and(|selection| {
|
|| self.selection.is_some_and(|selection| {
|
||||||
|
@ -6726,6 +6726,286 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_select_git_entry(cx: &mut gpui::TestAppContext) {
|
||||||
|
use git::status::{FileStatus, StatusCode, TrackedStatus};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
init_test_with_editor(cx);
|
||||||
|
|
||||||
|
let fs = FakeFs::new(cx.executor().clone());
|
||||||
|
fs.insert_tree(
|
||||||
|
"/root",
|
||||||
|
json!({
|
||||||
|
"tree1": {
|
||||||
|
".git": {},
|
||||||
|
"dir1": {
|
||||||
|
"modified1.txt": "",
|
||||||
|
"unmodified1.txt": "",
|
||||||
|
"modified2.txt": "",
|
||||||
|
},
|
||||||
|
"dir2": {
|
||||||
|
"modified3.txt": "",
|
||||||
|
"unmodified2.txt": "",
|
||||||
|
},
|
||||||
|
"modified4.txt": "",
|
||||||
|
"unmodified3.txt": "",
|
||||||
|
},
|
||||||
|
"tree2": {
|
||||||
|
".git": {},
|
||||||
|
"dir3": {
|
||||||
|
"modified5.txt": "",
|
||||||
|
"unmodified4.txt": "",
|
||||||
|
},
|
||||||
|
"modified6.txt": "",
|
||||||
|
"unmodified5.txt": "",
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// Mark files as git modified
|
||||||
|
let tree1_modified_files = [
|
||||||
|
"dir1/modified1.txt",
|
||||||
|
"dir1/modified2.txt",
|
||||||
|
"modified4.txt",
|
||||||
|
"dir2/modified3.txt",
|
||||||
|
];
|
||||||
|
|
||||||
|
let tree2_modified_files = ["dir3/modified5.txt", "modified6.txt"];
|
||||||
|
|
||||||
|
let root1_dot_git = Path::new("/root/tree1/.git");
|
||||||
|
let root2_dot_git = Path::new("/root/tree2/.git");
|
||||||
|
let set_value = FileStatus::Tracked(TrackedStatus {
|
||||||
|
index_status: StatusCode::Modified,
|
||||||
|
worktree_status: StatusCode::Modified,
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.with_git_state(&root1_dot_git, true, |git_repo_state| {
|
||||||
|
for file_path in tree1_modified_files {
|
||||||
|
git_repo_state.statuses.insert(file_path.into(), set_value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.with_git_state(&root2_dot_git, true, |git_repo_state| {
|
||||||
|
for file_path in tree2_modified_files {
|
||||||
|
git_repo_state.statuses.insert(file_path.into(), set_value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let project = Project::test(
|
||||||
|
fs.clone(),
|
||||||
|
["/root/tree1".as_ref(), "/root/tree2".as_ref()],
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
let workspace =
|
||||||
|
cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
|
||||||
|
let cx = &mut VisualTestContext::from_window(*workspace, cx);
|
||||||
|
let panel = workspace.update(cx, ProjectPanel::new).unwrap();
|
||||||
|
|
||||||
|
// Check initial state
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 0..15, cx),
|
||||||
|
&[
|
||||||
|
"v tree1",
|
||||||
|
" > .git",
|
||||||
|
" > dir1",
|
||||||
|
" > dir2",
|
||||||
|
" modified4.txt",
|
||||||
|
" unmodified3.txt",
|
||||||
|
"v tree2",
|
||||||
|
" > .git",
|
||||||
|
" > dir3",
|
||||||
|
" modified6.txt",
|
||||||
|
" unmodified5.txt"
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test selecting next modified entry
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.select_next_git_entry(&SelectNextGitEntry, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 0..6, cx),
|
||||||
|
&[
|
||||||
|
"v tree1",
|
||||||
|
" > .git",
|
||||||
|
" v dir1",
|
||||||
|
" modified1.txt <== selected",
|
||||||
|
" modified2.txt",
|
||||||
|
" unmodified1.txt",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.select_next_git_entry(&SelectNextGitEntry, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 0..6, cx),
|
||||||
|
&[
|
||||||
|
"v tree1",
|
||||||
|
" > .git",
|
||||||
|
" v dir1",
|
||||||
|
" modified1.txt",
|
||||||
|
" modified2.txt <== selected",
|
||||||
|
" unmodified1.txt",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.select_next_git_entry(&SelectNextGitEntry, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 6..9, cx),
|
||||||
|
&[
|
||||||
|
" v dir2",
|
||||||
|
" modified3.txt <== selected",
|
||||||
|
" unmodified2.txt",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.select_next_git_entry(&SelectNextGitEntry, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 9..11, cx),
|
||||||
|
&[" modified4.txt <== selected", " unmodified3.txt",],
|
||||||
|
);
|
||||||
|
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.select_next_git_entry(&SelectNextGitEntry, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 13..16, cx),
|
||||||
|
&[
|
||||||
|
" v dir3",
|
||||||
|
" modified5.txt <== selected",
|
||||||
|
" unmodified4.txt",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.select_next_git_entry(&SelectNextGitEntry, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 16..18, cx),
|
||||||
|
&[" modified6.txt <== selected", " unmodified5.txt",],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Wraps around to first modified file
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.select_next_git_entry(&SelectNextGitEntry, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 0..18, cx),
|
||||||
|
&[
|
||||||
|
"v tree1",
|
||||||
|
" > .git",
|
||||||
|
" v dir1",
|
||||||
|
" modified1.txt <== selected",
|
||||||
|
" modified2.txt",
|
||||||
|
" unmodified1.txt",
|
||||||
|
" v dir2",
|
||||||
|
" modified3.txt",
|
||||||
|
" unmodified2.txt",
|
||||||
|
" modified4.txt",
|
||||||
|
" unmodified3.txt",
|
||||||
|
"v tree2",
|
||||||
|
" > .git",
|
||||||
|
" v dir3",
|
||||||
|
" modified5.txt",
|
||||||
|
" unmodified4.txt",
|
||||||
|
" modified6.txt",
|
||||||
|
" unmodified5.txt",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Wraps around again to last modified file
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.select_prev_git_entry(&SelectPrevGitEntry, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 16..18, cx),
|
||||||
|
&[" modified6.txt <== selected", " unmodified5.txt",],
|
||||||
|
);
|
||||||
|
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.select_prev_git_entry(&SelectPrevGitEntry, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 13..16, cx),
|
||||||
|
&[
|
||||||
|
" v dir3",
|
||||||
|
" modified5.txt <== selected",
|
||||||
|
" unmodified4.txt",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.select_prev_git_entry(&SelectPrevGitEntry, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 9..11, cx),
|
||||||
|
&[" modified4.txt <== selected", " unmodified3.txt",],
|
||||||
|
);
|
||||||
|
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.select_prev_git_entry(&SelectPrevGitEntry, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 6..9, cx),
|
||||||
|
&[
|
||||||
|
" v dir2",
|
||||||
|
" modified3.txt <== selected",
|
||||||
|
" unmodified2.txt",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.select_prev_git_entry(&SelectPrevGitEntry, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 0..6, cx),
|
||||||
|
&[
|
||||||
|
"v tree1",
|
||||||
|
" > .git",
|
||||||
|
" v dir1",
|
||||||
|
" modified1.txt",
|
||||||
|
" modified2.txt <== selected",
|
||||||
|
" unmodified1.txt",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.select_prev_git_entry(&SelectPrevGitEntry, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 0..6, cx),
|
||||||
|
&[
|
||||||
|
"v tree1",
|
||||||
|
" > .git",
|
||||||
|
" v dir1",
|
||||||
|
" modified1.txt <== selected",
|
||||||
|
" modified2.txt",
|
||||||
|
" unmodified1.txt",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_select_directory(cx: &mut gpui::TestAppContext) {
|
async fn test_select_directory(cx: &mut gpui::TestAppContext) {
|
||||||
init_test_with_editor(cx);
|
init_test_with_editor(cx);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue