ep: Support both full paths and relative paths in examples (#46177)

Agus Zubiaga , Max Brunsfeld , and Oleksiy Syvokon created

Release Notes:

- N/A

Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Co-authored-by: Oleksiy Syvokon <oleksiy.syvokon@gmail.com>

Change summary

crates/edit_prediction/src/udiff.rs            | 27 ++++++++-----------
crates/edit_prediction_cli/src/load_project.rs | 22 ++++++++--------
crates/project/src/project.rs                  | 24 ++++++++--------
3 files changed, 34 insertions(+), 39 deletions(-)

Detailed changes

crates/edit_prediction/src/udiff.rs 🔗

@@ -3,7 +3,7 @@ use std::{
     fmt::{Debug, Display, Write},
     mem,
     ops::Range,
-    path::Path,
+    path::{Path, PathBuf},
     sync::Arc,
 };
 
@@ -34,7 +34,11 @@ pub async fn apply_diff(
     for line in diff_str.lines() {
         if let DiffLine::OldPath { path } = DiffLine::parse(line) {
             if path != "/dev/null" {
-                paths.push(RelPath::new(Path::new(path.as_ref()), PathStyle::Posix)?.into_arc());
+                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());
             }
         }
     }
@@ -62,23 +66,14 @@ pub async fn apply_diff(
                 hunk,
                 is_new_file,
             } => {
-                let worktree_id = worktree.read_with(cx, |wt, _| wt.id())?;
-                let rel_path = RelPath::new(Path::new(path.as_ref()), PathStyle::Posix)?;
-                let project_path = project::ProjectPath {
-                    worktree_id,
-                    path: rel_path.into_arc(),
-                };
+                let project_path = project
+                    .update(cx, |project, cx| {
+                        project.find_project_path(path.as_ref(), cx)
+                    })?
+                    .context("no such path")?;
 
                 let buffer = match current_file {
                     None => {
-                        if is_new_file {
-                            // New file - create it first, then open the buffer
-                            project
-                                .update(cx, |project, cx| {
-                                    project.create_entry(project_path.clone(), false, cx)
-                                })?
-                                .await?;
-                        }
                         let buffer = project
                             .update(cx, |project, cx| project.open_buffer(project_path, cx))?
                             .await?;

crates/edit_prediction_cli/src/load_project.rs 🔗

@@ -11,10 +11,9 @@ use edit_prediction::udiff::OpenedBuffers;
 use futures::AsyncWriteExt as _;
 use gpui::{AsyncApp, Entity};
 use language::{Anchor, Buffer, LanguageNotFound, ToOffset, ToPoint};
+use project::Project;
 use project::buffer_store::BufferStoreEvent;
-use project::{Project, ProjectPath};
 use std::{fs, path::PathBuf, sync::Arc};
-use util::{paths::PathStyle, rel_path::RelPath};
 
 pub async fn run_load_project(
     example: &mut Example,
@@ -77,15 +76,16 @@ async fn cursor_position(
         return Err(error);
     }
 
-    let worktree = project
-        .read_with(cx, |project, cx| project.visible_worktrees(cx).next())?
-        .context("project has no worktree")?;
-
-    let worktree_id = worktree.read_with(cx, |wt, _| wt.id())?;
-    let cursor_path = ProjectPath {
-        worktree_id,
-        path: RelPath::new(example.spec.cursor_path.as_ref(), PathStyle::Posix)?.into_arc(),
-    };
+    let cursor_path = project
+        .read_with(cx, |project, cx| {
+            project.find_project_path(&example.spec.cursor_path, cx)
+        })?
+        .with_context(|| {
+            format!(
+                "failed to find cursor path {}",
+                example.spec.cursor_path.display()
+            )
+        })?;
 
     let cursor_buffer = project
         .update(cx, |project, cx| project.open_buffer(cursor_path, cx))?

crates/project/src/project.rs 🔗

@@ -4550,18 +4550,6 @@ impl Project {
                 }
             }
         } else {
-            for worktree in worktree_store.visible_worktrees(cx) {
-                let worktree_root_name = worktree.read(cx).root_name();
-                if let Ok(relative_path) = path.strip_prefix(worktree_root_name.as_std_path())
-                    && let Ok(path) = RelPath::new(relative_path, path_style)
-                {
-                    return Some(ProjectPath {
-                        worktree_id: worktree.read(cx).id(),
-                        path: path.into_arc(),
-                    });
-                }
-            }
-
             for worktree in worktree_store.visible_worktrees(cx) {
                 let worktree = worktree.read(cx);
                 if let Ok(rel_path) = RelPath::new(path, path_style) {
@@ -4573,6 +4561,18 @@ impl Project {
                     }
                 }
             }
+
+            for worktree in worktree_store.visible_worktrees(cx) {
+                let worktree_root_name = worktree.read(cx).root_name();
+                if let Ok(relative_path) = path.strip_prefix(worktree_root_name.as_std_path())
+                    && let Ok(path) = RelPath::new(relative_path, path_style)
+                {
+                    return Some(ProjectPath {
+                        worktree_id: worktree.read(cx).id(),
+                        path: path.into_arc(),
+                    });
+                }
+            }
         }
 
         None