From 7ee9109ade5813b96011e6821215ed99688b0176 Mon Sep 17 00:00:00 2001 From: Smit Barmase Date: Tue, 8 Apr 2025 18:00:01 +0530 Subject: [PATCH] project_panel: Do not allow creating empty file/dir or file/dir with only whitespaces (#28240) - Do not allow creating empty file or empty directory. - Do not allow creating file or directory with just whitespace. - Show error only in case whitespace. image Release Notes: - N/A --- crates/project_panel/src/project_panel.rs | 38 +++++++++------- .../project_panel/src/project_panel_tests.rs | 44 +++++++++++++++++++ 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 29eb04c2a8..b1d4df8a4c 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -1150,9 +1150,7 @@ impl ProjectPanel { Some(state) => state, None => return, }; - let filename = self.filename_editor.read(cx).text(cx); - if !filename.is_empty() { if let Some(worktree) = self .project @@ -1160,6 +1158,7 @@ impl ProjectPanel { .worktree_for_id(edit_state.worktree_id, cx) { if let Some(entry) = worktree.read(cx).entry_for_id(edit_state.entry_id) { + let mut already_exists = false; if edit_state.is_new_entry() { let new_path = entry.path.join(filename.trim_start_matches('/')); if worktree @@ -1167,12 +1166,7 @@ impl ProjectPanel { .entry_for_path(new_path.as_path()) .is_some() { - edit_state.validation_state = ValidationState::Error(format!( - "File or directory '{}' already exists at location. Please choose a different name.", - filename - )); - cx.notify(); - return; + already_exists = true; } } else { let new_path = if let Some(parent) = entry.path.clone().parent() { @@ -1183,18 +1177,28 @@ impl ProjectPanel { if let Some(existing) = worktree.read(cx).entry_for_path(new_path.as_path()) { if existing.id != entry.id { - edit_state.validation_state = ValidationState::Error( - "File or directory already exists".to_string(), - ); - cx.notify(); - return; + already_exists = true; } } }; + if already_exists { + edit_state.validation_state = ValidationState::Error(format!( + "File or directory '{}' already exists at location. Please choose a different name.", + filename + )); + cx.notify(); + return; + } } } - - if filename.trim() != filename { + let trimmed_filename = filename.trim(); + if trimmed_filename.is_empty() { + edit_state.validation_state = + ValidationState::Error("File or directory name cannot be empty.".to_string()); + cx.notify(); + return; + } + if trimmed_filename != filename { edit_state.validation_state = ValidationState::Warning( "File or directory name contains leading or trailing whitespace.".to_string(), ); @@ -1202,7 +1206,6 @@ impl ProjectPanel { return; } } - edit_state.validation_state = ValidationState::None; cx.notify(); } @@ -1216,6 +1219,9 @@ impl ProjectPanel { 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); + if filename.trim().is_empty() { + return None; + } #[cfg(not(target_os = "windows"))] let filename_indicates_dir = filename.ends_with("/"); // On Windows, path separator could be either `/` or `\`. diff --git a/crates/project_panel/src/project_panel_tests.rs b/crates/project_panel/src/project_panel_tests.rs index a290e8c34a..fc1a538cc9 100644 --- a/crates/project_panel/src/project_panel_tests.rs +++ b/crates/project_panel/src/project_panel_tests.rs @@ -766,6 +766,50 @@ async fn test_editing_files(cx: &mut gpui::TestAppContext) { " .dockerignore", ] ); + + // Test empty filename and filename with only whitespace + panel.update_in(cx, |panel, window, cx| panel.new_file(&NewFile, window, cx)); + assert_eq!( + visible_entries_as_strings(&panel, 0..10, cx), + &[ + "v root1", + " > .git", + " > a", + " v b", + " > 3", + " > 4", + " > new-dir", + " [EDITOR: ''] <== selected", + " a-different-filename.tar.gz", + " > C", + ] + ); + panel.update_in(cx, |panel, window, cx| { + panel.filename_editor.update(cx, |editor, cx| { + editor.set_text("", window, cx); + }); + assert!(panel.confirm_edit(window, cx).is_none()); + panel.filename_editor.update(cx, |editor, cx| { + editor.set_text(" ", window, cx); + }); + assert!(panel.confirm_edit(window, cx).is_none()); + panel.cancel(&menu::Cancel, window, cx) + }); + assert_eq!( + visible_entries_as_strings(&panel, 0..10, cx), + &[ + "v root1", + " > .git", + " > a", + " v b", + " > 3", + " > 4", + " > new-dir", + " a-different-filename.tar.gz <== selected", + " > C", + " .dockerignore", + ] + ); } #[gpui::test(iterations = 10)]