From 33f5248d4f6c2395f8633aa307571e3b69dc7ff6 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 21 Jun 2023 15:23:52 -0700 Subject: [PATCH 1/7] Add the ability to make new directories by adding slashes to a file name --- Cargo.lock | 1 + Cargo.toml | 1 + crates/collab/Cargo.toml | 2 +- crates/fs/src/fs.rs | 6 + crates/project/Cargo.toml | 2 +- crates/project/src/worktree.rs | 23 +++- crates/project/src/worktree_tests.rs | 77 +++++++++++ crates/project_panel/Cargo.toml | 1 + crates/project_panel/src/project_panel.rs | 152 +++++++++++++++++++++- crates/settings/Cargo.toml | 2 +- 10 files changed, 259 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a9b2e29ea0..3748f24933 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5033,6 +5033,7 @@ dependencies = [ "language", "menu", "postage", + "pretty_assertions", "project", "schemars", "serde", diff --git a/Cargo.toml b/Cargo.toml index 3f3953096e..26555f32cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,6 +101,7 @@ time = { version = "0.3", features = ["serde", "serde-well-known"] } toml = { version = "0.5" } tree-sitter = "0.20" unindent = { version = "0.1.7" } +pretty_assertions = "1.3.0" [patch.crates-io] tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "49226023693107fba9a1191136a4f47f38cdca73" } diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index a87234ded7..0c752a2047 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -67,7 +67,7 @@ fs = { path = "../fs", features = ["test-support"] } git = { path = "../git", features = ["test-support"] } live_kit_client = { path = "../live_kit_client", features = ["test-support"] } lsp = { path = "../lsp", features = ["test-support"] } -pretty_assertions = "1.3.0" +pretty_assertions = "*" project = { path = "../project", features = ["test-support"] } rpc = { path = "../rpc", features = ["test-support"] } settings = { path = "../settings", features = ["test-support"] } diff --git a/crates/fs/src/fs.rs b/crates/fs/src/fs.rs index 592e6c9a53..ec8a249ff4 100644 --- a/crates/fs/src/fs.rs +++ b/crates/fs/src/fs.rs @@ -279,6 +279,9 @@ impl Fs for RealFs { async fn save(&self, path: &Path, text: &Rope, line_ending: LineEnding) -> Result<()> { let buffer_size = text.summary().len.min(10 * 1024); + if let Some(path) = path.parent() { + self.create_dir(path).await?; + } let file = smol::fs::File::create(path).await?; let mut writer = smol::io::BufWriter::with_capacity(buffer_size, file); for chunk in chunks(text, line_ending) { @@ -1077,6 +1080,9 @@ impl Fs for FakeFs { self.simulate_random_delay().await; let path = normalize_path(path); let content = chunks(text, line_ending).collect(); + if let Some(path) = path.parent() { + self.create_dir(path).await?; + } self.write_file_internal(path, content)?; Ok(()) } diff --git a/crates/project/Cargo.toml b/crates/project/Cargo.toml index d6578c87ba..dbc0c617f2 100644 --- a/crates/project/Cargo.toml +++ b/crates/project/Cargo.toml @@ -64,7 +64,7 @@ itertools = "0.10" [dev-dependencies] ctor.workspace = true env_logger.workspace = true -pretty_assertions = "1.3.0" +pretty_assertions = "*" client = { path = "../client", features = ["test-support"] } collections = { path = "../collections", features = ["test-support"] } db = { path = "../db", features = ["test-support"] } diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 20e693770f..a0497fa677 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -1001,10 +1001,25 @@ impl LocalWorktree { cx.spawn(|this, mut cx| async move { write.await?; - this.update(&mut cx, |this, cx| { - this.as_local_mut().unwrap().refresh_entry(path, None, cx) - }) - .await + let (result, refreshes) = this.update(&mut cx, |this, cx| { + let mut refreshes = Vec::new(); + for path in path.ancestors().skip(1) { + refreshes.push(this.as_local_mut().unwrap().refresh_entry( + path.into(), + None, + cx, + )); + } + ( + this.as_local_mut().unwrap().refresh_entry(path, None, cx), + refreshes, + ) + }); + for refresh in refreshes { + refresh.await.log_err(); + } + + result.await }) } diff --git a/crates/project/src/worktree_tests.rs b/crates/project/src/worktree_tests.rs index f908d702eb..efc5f42369 100644 --- a/crates/project/src/worktree_tests.rs +++ b/crates/project/src/worktree_tests.rs @@ -936,6 +936,83 @@ async fn test_create_directory_during_initial_scan(cx: &mut TestAppContext) { ); } +#[gpui::test] +async fn test_create_dir_all_on_create_entry(cx: &mut TestAppContext) { + let client_fake = cx.read(|cx| Client::new(FakeHttpClient::with_404_response(), cx)); + + let fs_fake = FakeFs::new(cx.background()); + fs_fake.insert_tree( + "/root", + json!({ + "a": {}, + }), + ) + .await; + + let tree_fake = Worktree::local( + client_fake, + "/root".as_ref(), + true, + fs_fake, + Default::default(), + &mut cx.to_async(), + ) + .await + .unwrap(); + + let entry = tree_fake + .update(cx, |tree, cx| { + tree.as_local_mut() + .unwrap() + .create_entry("a/b/c/d.txt".as_ref(), false, cx) + }) + .await + .unwrap(); + assert!(entry.is_file()); + + cx.foreground().run_until_parked(); + tree_fake.read_with(cx, |tree, _| { + assert!(tree.entry_for_path("a/b/c/d.txt").unwrap().is_file()); + assert!(tree.entry_for_path("a/b/c/").unwrap().is_dir()); + assert!(tree.entry_for_path("a/b/").unwrap().is_dir()); + }); + + let client_real = cx.read(|cx| Client::new(FakeHttpClient::with_404_response(), cx)); + + let fs_real = Arc::new(RealFs); + let temp_root = temp_tree(json!({ + "a": {} + })); + + let tree_real = Worktree::local( + client_real, + temp_root.path(), + true, + fs_real, + Default::default(), + &mut cx.to_async(), + ) + .await + .unwrap(); + + let entry = tree_real + .update(cx, |tree, cx| { + tree.as_local_mut() + .unwrap() + .create_entry("a/b/c/d.txt".as_ref(), false, cx) + }) + .await + .unwrap(); + assert!(entry.is_file()); + + cx.foreground().run_until_parked(); + tree_real.read_with(cx, |tree, _| { + assert!(tree.entry_for_path("a/b/c/d.txt").unwrap().is_file()); + assert!(tree.entry_for_path("a/b/c/").unwrap().is_dir()); + assert!(tree.entry_for_path("a/b/").unwrap().is_dir()); + }); +} + #[gpui::test(iterations = 100)] async fn test_random_worktree_operations_during_initial_scan( cx: &mut TestAppContext, diff --git a/crates/project_panel/Cargo.toml b/crates/project_panel/Cargo.toml index 55efc09deb..33606fccc4 100644 --- a/crates/project_panel/Cargo.toml +++ b/crates/project_panel/Cargo.toml @@ -27,6 +27,7 @@ serde_derive.workspace = true serde_json.workspace = true anyhow.workspace = true schemars.workspace = true +pretty_assertions.workspace = true unicase = "2.6" [dev-dependencies] diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 3f80e02317..57a45ddb16 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -64,7 +64,7 @@ pub struct ProjectPanel { pending_serialization: Task>, } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] struct Selection { worktree_id: WorktreeId, entry_id: ProjectEntryId, @@ -588,6 +588,7 @@ impl ProjectPanel { if selection.entry_id == edited_entry_id { selection.worktree_id = worktree_id; selection.entry_id = new_entry.id; + this.expand_to_selection(cx); } } this.update_visible_entries(None, cx); @@ -965,6 +966,25 @@ impl ProjectPanel { Some((worktree, entry)) } + fn expand_to_selection(&mut self, cx: &mut ViewContext) -> Option<()> { + let (worktree, entry) = self.selected_entry(cx)?; + let expanded_dir_ids = self.expanded_dir_ids.entry(worktree.id()).or_default(); + + for path in entry.path.ancestors() { + let Some(entry) = worktree.entry_for_path(path) else { + continue; + }; + if entry.is_dir() { + if let Err(idx) = expanded_dir_ids.binary_search(&entry.id) { + expanded_dir_ids.insert(idx, entry.id); + } + } + } + + + Some(()) + } + fn update_visible_entries( &mut self, new_selected_entry: Option<(WorktreeId, ProjectEntryId)>, @@ -1139,6 +1159,7 @@ impl ProjectPanel { for entry in visible_worktree_entries[entry_range].iter() { let status = git_status_setting.then(|| entry.git_status).flatten(); + let mut details = EntryDetails { filename: entry .path @@ -1592,6 +1613,7 @@ impl ClipboardEntry { mod tests { use super::*; use gpui::{TestAppContext, ViewHandle}; + use pretty_assertions::assert_eq; use project::FakeFs; use serde_json::json; use settings::SettingsStore; @@ -2002,6 +2024,134 @@ mod tests { ); } + #[gpui::test(iterations = 30)] + async fn test_adding_directories_via_file(cx: &mut gpui::TestAppContext) { + init_test(cx); + + let fs = FakeFs::new(cx.background()); + fs.insert_tree( + "/root1", + json!({ + ".dockerignore": "", + ".git": { + "HEAD": "", + }, + "a": { + "0": { "q": "", "r": "", "s": "" }, + "1": { "t": "", "u": "" }, + "2": { "v": "", "w": "", "x": "", "y": "" }, + }, + "b": { + "3": { "Q": "" }, + "4": { "R": "", "S": "", "T": "", "U": "" }, + }, + "C": { + "5": {}, + "6": { "V": "", "W": "" }, + "7": { "X": "" }, + "8": { "Y": {}, "Z": "" } + } + }), + ) + .await; + fs.insert_tree( + "/root2", + json!({ + "d": { + "9": "" + }, + "e": {} + }), + ) + .await; + + let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await; + let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); + let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx)); + + select_path(&panel, "root1", cx); + assert_eq!( + visible_entries_as_strings(&panel, 0..10, cx), + &[ + "v root1 <== selected", + " > .git", + " > a", + " > b", + " > C", + " .dockerignore", + "v root2", + " > d", + " > e", + ] + ); + + // Add a file with the root folder selected. The filename editor is placed + // before the first file in the root folder. + panel.update(cx, |panel, cx| panel.new_file(&NewFile, cx)); + cx.read_window(window_id, |cx| { + let panel = panel.read(cx); + assert!(panel.filename_editor.is_focused(cx)); + }); + assert_eq!( + visible_entries_as_strings(&panel, 0..10, cx), + &[ + "v root1", + " > .git", + " > a", + " > b", + " > C", + " [EDITOR: ''] <== selected", + " .dockerignore", + "v root2", + " > d", + " > e", + ] + ); + + + let confirm = panel.update(cx, |panel, cx| { + panel.filename_editor.update(cx, |editor, cx| { + editor.set_text("bdir1/dir2/the-new-filename", cx) + }); + panel.confirm(&Confirm, cx).unwrap() + }); + + assert_eq!( + visible_entries_as_strings(&panel, 0..10, cx), + &[ + "v root1", + " > .git", + " > a", + " > b", + " > C", + " [PROCESSING: 'bdir1/dir2/the-new-filename'] <== selected", + " .dockerignore", + "v root2", + " > d", + " > e", + ] + ); + + confirm.await.unwrap(); + assert_eq!( + visible_entries_as_strings(&panel, 0..13, cx), + &[ + "v root1", + " > .git", + " > a", + " > b", + " v bdir1", + " v dir2", + " the-new-filename <== selected", + " > C", + " .dockerignore", + "v root2", + " > d", + " > e", + ] + ); + } + #[gpui::test] async fn test_copy_paste(cx: &mut gpui::TestAppContext) { init_test(cx); diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index b5dc301a5c..6c1ded805b 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -38,5 +38,5 @@ tree-sitter-json = "*" gpui = { path = "../gpui", features = ["test-support"] } fs = { path = "../fs", features = ["test-support"] } indoc.workspace = true -pretty_assertions = "1.3.0" +pretty_assertions = "*" unindent.workspace = true From cd670e340fa4a7e5c6d452a87ceee6329ae0ee21 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 29 Jun 2023 17:48:01 -0700 Subject: [PATCH 2/7] Fix edge case with absolute file paths --- crates/project_panel/src/project_panel.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 57a45ddb16..fe8c649420 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -547,7 +547,7 @@ impl ProjectPanel { worktree_id, entry_id: NEW_ENTRY_ID, }); - let new_path = entry.path.join(&filename); + let new_path = entry.path.join(&filename.trim_start_matches("/")); if path_already_exists(new_path.as_path()) { return None; } @@ -2111,7 +2111,7 @@ mod tests { let confirm = panel.update(cx, |panel, cx| { panel.filename_editor.update(cx, |editor, cx| { - editor.set_text("bdir1/dir2/the-new-filename", cx) + editor.set_text("/bdir1/dir2/the-new-filename", cx) }); panel.confirm(&Confirm, cx).unwrap() }); @@ -2124,7 +2124,7 @@ mod tests { " > a", " > b", " > C", - " [PROCESSING: 'bdir1/dir2/the-new-filename'] <== selected", + " [PROCESSING: '/bdir1/dir2/the-new-filename'] <== selected", " .dockerignore", "v root2", " > d", From 787412b545cd6e9e4cb0f40f5d33d3b9a4480a22 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 29 Jun 2023 17:49:42 -0700 Subject: [PATCH 3/7] fmt and update dependency --- crates/collab/Cargo.toml | 2 +- crates/project/Cargo.toml | 2 +- crates/project/src/worktree_tests.rs | 15 ++++++++------- crates/project_panel/src/project_panel.rs | 3 --- crates/settings/Cargo.toml | 2 +- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index 0c752a2047..c787287a0c 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -67,7 +67,7 @@ fs = { path = "../fs", features = ["test-support"] } git = { path = "../git", features = ["test-support"] } live_kit_client = { path = "../live_kit_client", features = ["test-support"] } lsp = { path = "../lsp", features = ["test-support"] } -pretty_assertions = "*" +pretty_assertions.workspace = true project = { path = "../project", features = ["test-support"] } rpc = { path = "../rpc", features = ["test-support"] } settings = { path = "../settings", features = ["test-support"] } diff --git a/crates/project/Cargo.toml b/crates/project/Cargo.toml index dbc0c617f2..bfe5f89f68 100644 --- a/crates/project/Cargo.toml +++ b/crates/project/Cargo.toml @@ -64,7 +64,7 @@ itertools = "0.10" [dev-dependencies] ctor.workspace = true env_logger.workspace = true -pretty_assertions = "*" +pretty_assertions.workspace = true client = { path = "../client", features = ["test-support"] } collections = { path = "../collections", features = ["test-support"] } db = { path = "../db", features = ["test-support"] } diff --git a/crates/project/src/worktree_tests.rs b/crates/project/src/worktree_tests.rs index efc5f42369..63f1f28eea 100644 --- a/crates/project/src/worktree_tests.rs +++ b/crates/project/src/worktree_tests.rs @@ -941,13 +941,14 @@ async fn test_create_dir_all_on_create_entry(cx: &mut TestAppContext) { let client_fake = cx.read(|cx| Client::new(FakeHttpClient::with_404_response(), cx)); let fs_fake = FakeFs::new(cx.background()); - fs_fake.insert_tree( - "/root", - json!({ - "a": {}, - }), - ) - .await; + fs_fake + .insert_tree( + "/root", + json!({ + "a": {}, + }), + ) + .await; let tree_fake = Worktree::local( client_fake, diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index fe8c649420..c329ae4e51 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -981,7 +981,6 @@ impl ProjectPanel { } } - Some(()) } @@ -1159,7 +1158,6 @@ impl ProjectPanel { for entry in visible_worktree_entries[entry_range].iter() { let status = git_status_setting.then(|| entry.git_status).flatten(); - let mut details = EntryDetails { filename: entry .path @@ -2108,7 +2106,6 @@ mod tests { ] ); - let confirm = panel.update(cx, |panel, cx| { panel.filename_editor.update(cx, |editor, cx| { editor.set_text("/bdir1/dir2/the-new-filename", cx) diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index 6c1ded805b..06b81a0c61 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -38,5 +38,5 @@ tree-sitter-json = "*" gpui = { path = "../gpui", features = ["test-support"] } fs = { path = "../fs", features = ["test-support"] } indoc.workspace = true -pretty_assertions = "*" +pretty_assertions.workspace = true unindent.workspace = true From a6dabf7acfef0f235bdd41d81daf8433b1955f59 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 29 Jun 2023 18:15:40 -0700 Subject: [PATCH 4/7] Make path updates minimal --- crates/project/src/worktree.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index a0497fa677..2b166bf6ef 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -981,6 +981,19 @@ impl LocalWorktree { }) } + /// Find the lowest path in the worktree's datastructures that is an ancestor + pub fn lowest_ancestor(&self, path: &Path) -> PathBuf { + let mut lowest_ancestor = None; + for path in path.ancestors() { + if self.entry_for_path(path).is_some() { + lowest_ancestor = Some(path.to_path_buf()); + break; + } + } + + lowest_ancestor.unwrap_or_else(|| PathBuf::from("")) + } + pub fn create_entry( &self, path: impl Into>, @@ -988,6 +1001,7 @@ impl LocalWorktree { cx: &mut ModelContext, ) -> Task> { let path = path.into(); + let lowest_ancestor = self.lowest_ancestor(&path); let abs_path = self.absolutize(&path); let fs = self.fs.clone(); let write = cx.background().spawn(async move { @@ -1003,9 +1017,14 @@ impl LocalWorktree { write.await?; let (result, refreshes) = this.update(&mut cx, |this, cx| { let mut refreshes = Vec::new(); - for path in path.ancestors().skip(1) { + let refresh_paths = path.strip_prefix(&lowest_ancestor).unwrap(); + for refresh_path in refresh_paths.ancestors() { + let refresh_full_path = lowest_ancestor.join(refresh_path); + if refresh_full_path.as_path() == path.deref() { + continue; + } refreshes.push(this.as_local_mut().unwrap().refresh_entry( - path.into(), + refresh_full_path.into(), None, cx, )); From a9a51ab3addfda7c97a96d3194099077d13fc7a1 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 29 Jun 2023 18:21:35 -0700 Subject: [PATCH 5/7] Added more tests and minimal file updates --- crates/project/src/worktree_tests.rs | 35 ++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/crates/project/src/worktree_tests.rs b/crates/project/src/worktree_tests.rs index 63f1f28eea..8f130f648a 100644 --- a/crates/project/src/worktree_tests.rs +++ b/crates/project/src/worktree_tests.rs @@ -1012,6 +1012,41 @@ async fn test_create_dir_all_on_create_entry(cx: &mut TestAppContext) { assert!(tree.entry_for_path("a/b/c/").unwrap().is_dir()); assert!(tree.entry_for_path("a/b/").unwrap().is_dir()); }); + + // Test smallest change + let entry = tree_real + .update(cx, |tree, cx| { + tree.as_local_mut() + .unwrap() + .create_entry("a/b/c/e.txt".as_ref(), false, cx) + }) + .await + .unwrap(); + assert!(entry.is_file()); + + cx.foreground().run_until_parked(); + tree_real.read_with(cx, |tree, _| { + assert!(tree.entry_for_path("a/b/c/e.txt").unwrap().is_file()); + }); + + // Test largest change + let entry = tree_real + .update(cx, |tree, cx| { + tree.as_local_mut() + .unwrap() + .create_entry("d/e/f/g.txt".as_ref(), false, cx) + }) + .await + .unwrap(); + assert!(entry.is_file()); + + cx.foreground().run_until_parked(); + tree_real.read_with(cx, |tree, _| { + assert!(tree.entry_for_path("d/e/f/g.txt").unwrap().is_file()); + assert!(tree.entry_for_path("d/e/f").unwrap().is_dir()); + assert!(tree.entry_for_path("d/e/").unwrap().is_dir()); + assert!(tree.entry_for_path("d/").unwrap().is_dir()); + }); } #[gpui::test(iterations = 100)] From d22a576f5e05f0a3b1a83e67b40489f9068c4e74 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 29 Jun 2023 23:50:24 -0700 Subject: [PATCH 6/7] fix failing test --- crates/project/src/worktree.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 2b166bf6ef..7596b0fcb7 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -1016,13 +1016,14 @@ impl LocalWorktree { cx.spawn(|this, mut cx| async move { write.await?; let (result, refreshes) = this.update(&mut cx, |this, cx| { - let mut refreshes = Vec::new(); + let mut refreshes = Vec::>>::new(); let refresh_paths = path.strip_prefix(&lowest_ancestor).unwrap(); for refresh_path in refresh_paths.ancestors() { - let refresh_full_path = lowest_ancestor.join(refresh_path); - if refresh_full_path.as_path() == path.deref() { + if refresh_path == Path::new("") { continue; } + let refresh_full_path = lowest_ancestor.join(refresh_path); + refreshes.push(this.as_local_mut().unwrap().refresh_entry( refresh_full_path.into(), None, From 3d6e063a6dcabe7644a10891417dc648793afa70 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 29 Jun 2023 23:53:57 -0700 Subject: [PATCH 7/7] Fix method header --- crates/project/src/worktree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 7596b0fcb7..d86b98e0ec 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -982,7 +982,7 @@ impl LocalWorktree { } /// Find the lowest path in the worktree's datastructures that is an ancestor - pub fn lowest_ancestor(&self, path: &Path) -> PathBuf { + fn lowest_ancestor(&self, path: &Path) -> PathBuf { let mut lowest_ancestor = None; for path in path.ancestors() { if self.entry_for_path(path).is_some() {