ep cli: Refresh cursor path entry (#46195)

Agus Zubiaga created

Release Notes:

- N/A

Change summary

crates/edit_prediction/src/udiff.rs            | 66 +++++++++++++------
crates/edit_prediction_cli/src/load_project.rs |  7 +
2 files changed, 50 insertions(+), 23 deletions(-)

Detailed changes

crates/edit_prediction/src/udiff.rs 🔗

@@ -14,6 +14,7 @@ use language::{Anchor, Buffer, OffsetRangeExt as _, TextBufferSnapshot, text_dif
 use postage::stream::Stream as _;
 use project::Project;
 use util::{paths::PathStyle, rel_path::RelPath};
+use worktree::Worktree;
 
 #[derive(Clone, Debug)]
 pub struct OpenedBuffers(#[allow(unused)] HashMap<String, Entity<Buffer>>);
@@ -28,29 +29,18 @@ pub async fn apply_diff(
         .read_with(cx, |project, cx| project.visible_worktrees(cx).next())?
         .context("project has no worktree")?;
 
-    // Ensure the files in the diff are loaded, since worktree scanning is disabled in
-    // edit prediction CLI.
-    let mut paths = Vec::new();
-    for line in diff_str.lines() {
-        if let DiffLine::OldPath { path } = DiffLine::parse(line) {
-            if path != "/dev/null" {
-                let path = Path::new(path.as_ref());
-                paths.push(RelPath::new(path, PathStyle::Posix)?.into_arc());
-
-                let path_without_root = path.components().skip(1).collect::<PathBuf>();
-                paths.push(RelPath::new(&path_without_root, PathStyle::Posix)?.into_arc());
+    let paths: Vec<_> = diff_str
+        .lines()
+        .filter_map(|line| {
+            if let DiffLine::OldPath { path } = DiffLine::parse(line) {
+                if path != "/dev/null" {
+                    return Some(PathBuf::from(path.as_ref()));
+                }
             }
-        }
-    }
-    worktree
-        .update(cx, |worktree, _| {
-            worktree
-                .as_local()
-                .unwrap()
-                .refresh_entries_for_paths(paths)
-        })?
-        .recv()
-        .await;
+            None
+        })
+        .collect();
+    refresh_worktree_entries(&worktree, paths.iter().map(|p| p.as_path()), cx).await?;
 
     let mut included_files = HashMap::default();
 
@@ -129,6 +119,38 @@ pub async fn apply_diff(
     Ok(OpenedBuffers(included_files))
 }
 
+pub async fn refresh_worktree_entries(
+    worktree: &Entity<Worktree>,
+    paths: impl IntoIterator<Item = &Path>,
+    cx: &mut AsyncApp,
+) -> Result<()> {
+    let mut rel_paths = Vec::new();
+    for path in paths {
+        if let Ok(rel_path) = RelPath::new(path, PathStyle::Posix) {
+            rel_paths.push(rel_path.into_arc());
+        }
+
+        let path_without_root: PathBuf = path.components().skip(1).collect();
+        if let Ok(rel_path) = RelPath::new(&path_without_root, PathStyle::Posix) {
+            rel_paths.push(rel_path.into_arc());
+        }
+    }
+
+    if !rel_paths.is_empty() {
+        worktree
+            .update(cx, |worktree, _| {
+                worktree
+                    .as_local()
+                    .unwrap()
+                    .refresh_entries_for_paths(rel_paths)
+            })?
+            .recv()
+            .await;
+    }
+
+    Ok(())
+}
+
 /// Extract the diff for a specific file from a multi-file diff.
 /// Returns an error if the file is not found in the diff.
 pub fn extract_file_diff(full_diff: &str, file_path: &str) -> Result<String> {

crates/edit_prediction_cli/src/load_project.rs 🔗

@@ -6,7 +6,7 @@ use crate::{
 };
 use anyhow::{Context as _, Result};
 use edit_prediction::EditPredictionStore;
-use edit_prediction::udiff::OpenedBuffers;
+use edit_prediction::udiff::{OpenedBuffers, refresh_worktree_entries};
 use futures::AsyncWriteExt as _;
 use gpui::{AsyncApp, Entity};
 use language::{Anchor, Buffer, LanguageNotFound, ToOffset, ToPoint};
@@ -75,6 +75,11 @@ async fn cursor_position(
         return Err(error);
     }
 
+    // Since the worktree scanner is disabled, manually refresh entries for the cursor path.
+    if let Some(worktree) = project.read_with(cx, |project, cx| project.worktrees(cx).next())? {
+        refresh_worktree_entries(&worktree, [&*example.spec.cursor_path], cx).await?;
+    }
+
     let cursor_path = project
         .read_with(cx, |project, cx| {
             project.find_project_path(&example.spec.cursor_path, cx)