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 ---------
Unified · Split
| @@ -4163,23 +4163,36 @@ impl Project { · 4162 unmodified lines | ||
| 4163 | 4163 | let path = path.as_ref(); |
| 4164 | 4164 | let worktree_store = self.worktree_store.read(cx); |
| 4165 | 4165 | |
| 4166 | − for worktree in worktree_store.visible_worktrees(cx) { | |
| 4167 | − let worktree_root_name = worktree.read(cx).root_name(); | |
| 4168 | − if let Ok(relative_path) = path.strip_prefix(worktree_root_name) { | |
| 4169 | − return Some(ProjectPath { | |
| 4170 | − worktree_id: worktree.read(cx).id(), | |
| 4171 | − path: relative_path.into(), | |
| 4172 | − }); | |
| 4166 | + if path.is_absolute() { | |
| 4167 | + for worktree in worktree_store.visible_worktrees(cx) { | |
| 4168 | + let worktree_abs_path = worktree.read(cx).abs_path(); | |
| 4169 | + | |
| 4170 | + if let Ok(relative_path) = path.strip_prefix(worktree_abs_path) { | |
| 4171 | + return Some(ProjectPath { | |
| 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) { | |
| 4177 | − let worktree = worktree.read(cx); | |
| 4178 | − if let Some(entry) = worktree.entry_for_path(path) { | |
| 4179 | − return Some(ProjectPath { | |
| 4180 | − worktree_id: worktree.id(), | |
| 4181 | − path: entry.path.clone(), | |
| 4182 | − }); | |
| 4188 | + for worktree in worktree_store.visible_worktrees(cx) { | |
| 4189 | + let worktree = worktree.read(cx); | |
| 4190 | + if let Some(entry) = worktree.entry_for_path(path) { | |
| 4191 | + return Some(ProjectPath { | |
| 4192 | + worktree_id: worktree.id(), | |
| 4193 | + path: entry.path.clone(), | |
| 4194 | + }); | |
| 4195 | + } | |
| 4183 | 4196 | } |
| 4184 | 4197 | } |
| 4185 | 4198 | |
| @@ -8766,3 +8766,89 @@ fn git_status(repo: &git2::Repository) -> collections::HashMap<String, git2::Sta · 8765 unmodified lines | ||
| 8766 | 8766 | .map(|status| (status.path().unwrap().to_string(), status.status())) |
| 8767 | 8767 | .collect() |
| 8768 | 8768 | } |
| 8769 | + | |
| 8770 | +#[gpui::test] | |
| 8771 | +async 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 | +} | |