History

Support `find_project_path` being given absolute paths (#30283)

Sometimes models return absolute paths even though we ask them not to (including sometimes returning `/dev/null`). Currently we assume we're always given a relative path, which leads to a panic in debug builds. Now we just support being given absolute paths. Release Notes: - N/A ---------

Richard Feldman committed 1 year ago

Commit 77945fc1 parent 6827bf12 files · +114 −15Browse files

Unified · Split

2 files
  1. crates/project/src/project.rs +28 −15
  2. crates/project/src/project_tests.rs +86 −0
crates/project/src/project.rs+28−15
@@ -4163,23 +4163,36 @@ impl Project { · 4162 unmodified lines
4163 let path = path.as_ref();4163 let path = path.as_ref();
4164 let worktree_store = self.worktree_store.read(cx);4164 let worktree_store = self.worktree_store.read(cx);
4165 4165
4166 for worktree in worktree_store.visible_worktrees(cx) {4166 if path.is_absolute() {
4167 let worktree_root_name = worktree.read(cx).root_name();4167 for worktree in worktree_store.visible_worktrees(cx) {
4168 if let Ok(relative_path) = path.strip_prefix(worktree_root_name) {4168 let worktree_abs_path = worktree.read(cx).abs_path();
4169 return Some(ProjectPath {4169
4170 worktree_id: worktree.read(cx).id(),4170 if let Ok(relative_path) = path.strip_prefix(worktree_abs_path) {
4171 path: relative_path.into(),4171 return Some(ProjectPath {
4172 });4172 worktree_id: worktree.read(cx).id(),
4173 path: relative_path.into(),
4174 });
4175 }
4176 }
4177 } else {
4178 for worktree in worktree_store.visible_worktrees(cx) {
4179 let worktree_root_name = worktree.read(cx).root_name();
4180 if let Ok(relative_path) = path.strip_prefix(worktree_root_name) {
4181 return Some(ProjectPath {
4182 worktree_id: worktree.read(cx).id(),
4183 path: relative_path.into(),
4184 });
4185 }
4173 }4186 }
4174 }
4175 4187
4176 for worktree in worktree_store.visible_worktrees(cx) {4188 for worktree in worktree_store.visible_worktrees(cx) {
4177 let worktree = worktree.read(cx);4189 let worktree = worktree.read(cx);
4178 if let Some(entry) = worktree.entry_for_path(path) {4190 if let Some(entry) = worktree.entry_for_path(path) {
4179 return Some(ProjectPath {4191 return Some(ProjectPath {
4180 worktree_id: worktree.id(),4192 worktree_id: worktree.id(),
4181 path: entry.path.clone(),4193 path: entry.path.clone(),
4182 });4194 });
4195 }
4183 }4196 }
4184 }4197 }
4185 4198
crates/project/src/project_tests.rs+86−0
@@ -8766,3 +8766,89 @@ fn git_status(repo: &git2::Repository) -> collections::HashMap<String, git2::Sta · 8765 unmodified lines
8766 .map(|status| (status.path().unwrap().to_string(), status.status()))8766 .map(|status| (status.path().unwrap().to_string(), status.status()))
8767 .collect()8767 .collect()
8768}8768}
8769
8770#[gpui::test]
8771async fn test_find_project_path_abs(
8772 background_executor: BackgroundExecutor,
8773 cx: &mut gpui::TestAppContext,
8774) {
8775 // find_project_path should work with absolute paths
8776 init_test(cx);
8777
8778 let fs = FakeFs::new(background_executor);
8779 fs.insert_tree(
8780 path!("/root"),
8781 json!({
8782 "project1": {
8783 "file1.txt": "content1",
8784 "subdir": {
8785 "file2.txt": "content2"
8786 }
8787 },
8788 "project2": {
8789 "file3.txt": "content3"
8790 }
8791 }),
8792 )
8793 .await;
8794
8795 let project = Project::test(
8796 fs.clone(),
8797 [
8798 path!("/root/project1").as_ref(),
8799 path!("/root/project2").as_ref(),
8800 ],
8801 cx,
8802 )
8803 .await;
8804
8805 // Make sure the worktrees are fully initialized
8806 for worktree in project.read_with(cx, |project, cx| project.worktrees(cx).collect::<Vec<_>>()) {
8807 worktree
8808 .read_with(cx, |tree, _| tree.as_local().unwrap().scan_complete())
8809 .await;
8810 }
8811 cx.run_until_parked();
8812
8813 let (project1_abs_path, project1_id, project2_abs_path, project2_id) =
8814 project.read_with(cx, |project, cx| {
8815 let worktrees: Vec<_> = project.worktrees(cx).collect();
8816 let abs_path1 = worktrees[0].read(cx).abs_path().to_path_buf();
8817 let id1 = worktrees[0].read(cx).id();
8818 let abs_path2 = worktrees[1].read(cx).abs_path().to_path_buf();
8819 let id2 = worktrees[1].read(cx).id();
8820 (abs_path1, id1, abs_path2, id2)
8821 });
8822
8823 project.update(cx, |project, cx| {
8824 let abs_path = project1_abs_path.join("file1.txt");
8825 let found_path = project.find_project_path(abs_path, cx).unwrap();
8826 assert_eq!(found_path.worktree_id, project1_id);
8827 assert_eq!(found_path.path.as_ref(), Path::new("file1.txt"));
8828
8829 let abs_path = project1_abs_path.join("subdir").join("file2.txt");
8830 let found_path = project.find_project_path(abs_path, cx).unwrap();
8831 assert_eq!(found_path.worktree_id, project1_id);
8832 assert_eq!(found_path.path.as_ref(), Path::new("subdir/file2.txt"));
8833
8834 let abs_path = project2_abs_path.join("file3.txt");
8835 let found_path = project.find_project_path(abs_path, cx).unwrap();
8836 assert_eq!(found_path.worktree_id, project2_id);
8837 assert_eq!(found_path.path.as_ref(), Path::new("file3.txt"));
8838
8839 let abs_path = project1_abs_path.join("nonexistent.txt");
8840 let found_path = project.find_project_path(abs_path, cx);
8841 assert!(
8842 found_path.is_some(),
8843 "Should find project path for nonexistent file in worktree"
8844 );
8845
8846 // Test with an absolute path outside any worktree
8847 let abs_path = Path::new("/some/other/path");
8848 let found_path = project.find_project_path(abs_path, cx);
8849 assert!(
8850 found_path.is_none(),
8851 "Should not find project path for path outside any worktree"
8852 );
8853 });
8854}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t