project_panel: Fix create entry with trailing dot duplicating on windows (#44524)

Release Notes:

- Fixed an issue where creating a file through the project panel with a
trailing dot in its name would duplicate the entries with and without
the dot

Co-authored by: Smit Barmase <smit@zed.dev>
This commit is contained in:
Lukas Wirth
2025-12-10 10:33:49 +00:00
committed by GitHub
parent a8e2dc2f25
commit 30597a0cba
3 changed files with 81 additions and 3 deletions
+3 -1
View File
@@ -73,7 +73,9 @@ impl LspInstaller for GoLspAdapter {
delegate.show_notification(NOTIFICATION_MESSAGE, cx);
})?
}
anyhow::bail!("cannot install gopls");
anyhow::bail!(
"Could not install the Go language server `gopls`, because `go` was not found."
);
}
let release =
+10 -2
View File
@@ -1663,12 +1663,20 @@ impl ProjectPanel {
let edit_state = self.state.edit_state.as_mut()?;
let worktree_id = edit_state.worktree_id;
let is_new_entry = edit_state.is_new_entry();
let filename = self.filename_editor.read(cx).text(cx);
let mut filename = self.filename_editor.read(cx).text(cx);
let path_style = self.project.read(cx).path_style(cx);
if path_style.is_windows() {
// on windows, trailing dots are ignored in paths
// this can cause project panel to create a new entry with a trailing dot
// while the actual one without the dot gets populated by the file watcher
while let Some(trimmed) = filename.strip_suffix('.') {
filename = trimmed.to_string();
}
}
if filename.trim().is_empty() {
return None;
}
let path_style = self.project.read(cx).path_style(cx);
let filename_indicates_dir = if path_style.is_windows() {
filename.ends_with('/') || filename.ends_with('\\')
} else {
@@ -6612,6 +6612,74 @@ async fn test_create_entries_without_selection_hide_root(cx: &mut gpui::TestAppC
);
}
#[cfg(windows)]
#[gpui::test]
async fn test_create_entry_with_trailing_dot_windows(cx: &mut gpui::TestAppContext) {
init_test(cx);
let fs = FakeFs::new(cx.executor());
fs.insert_tree(
path!("/root"),
json!({
"dir1": {
"file1.txt": "",
},
}),
)
.await;
let project = Project::test(fs.clone(), [path!("/root").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, |workspace, window, cx| {
let panel = ProjectPanel::new(workspace, window, cx);
workspace.add_panel(panel.clone(), window, cx);
panel
})
.unwrap();
cx.run_until_parked();
#[rustfmt::skip]
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
"v root",
" > dir1",
],
"Initial state with nothing selected"
);
panel.update_in(cx, |panel, window, cx| {
panel.new_file(&NewFile, window, cx);
});
cx.run_until_parked();
panel.update_in(cx, |panel, window, cx| {
assert!(panel.filename_editor.read(cx).is_focused(window));
});
panel
.update_in(cx, |panel, window, cx| {
panel
.filename_editor
.update(cx, |editor, cx| editor.set_text("foo.", window, cx));
panel.confirm_edit(true, window, cx).unwrap()
})
.await
.unwrap();
cx.run_until_parked();
#[rustfmt::skip]
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
"v root",
" > dir1",
" foo <== selected <== marked",
],
"A new file is created under the root directory without the trailing dot"
);
}
#[gpui::test]
async fn test_highlight_entry_for_external_drag(cx: &mut gpui::TestAppContext) {
init_test(cx);