@@ -1472,9 +1472,18 @@ pub mod test {
impl TestProjectItem {
pub fn new(id: u64, path: &str, cx: &mut App) -> Entity<Self> {
+ Self::new_in_worktree(id, path, WorktreeId::from_usize(0), cx)
+ }
+
+ pub fn new_in_worktree(
+ id: u64,
+ path: &str,
+ worktree_id: WorktreeId,
+ cx: &mut App,
+ ) -> Entity<Self> {
let entry_id = Some(ProjectEntryId::from_proto(id));
let project_path = Some(ProjectPath {
- worktree_id: WorktreeId::from_usize(0),
+ worktree_id,
path: rel_path(path).into(),
});
cx.new(|_| Self {
@@ -3765,11 +3765,18 @@ impl Workspace {
.project
.read(cx)
.worktree_for_id(path.worktree_id, cx)?;
- if worktree.read(cx).is_visible() {
- abs_path
- } else {
- None
+ if !worktree.read(cx).is_visible() {
+ return None;
+ }
+ let settings_location = SettingsLocation {
+ worktree_id: path.worktree_id,
+ path: &path.path,
+ };
+ if WorktreeSettings::get(Some(settings_location), cx).is_path_read_only(&path.path)
+ {
+ return None;
}
+ abs_path
})
.next()
}
@@ -15156,4 +15163,51 @@ mod tests {
);
});
}
+
+ #[gpui::test]
+ async fn test_most_recent_active_path_skips_read_only_paths(cx: &mut TestAppContext) {
+ init_test(cx);
+
+ let fs = FakeFs::new(cx.executor());
+ fs.insert_tree(
+ path!("/project"),
+ json!({
+ "src": { "main.py": "" },
+ ".venv": { "lib": { "dep.py": "" } },
+ }),
+ )
+ .await;
+
+ let project = Project::test(fs.clone(), [path!("/project").as_ref()], cx).await;
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
+ let worktree_id = project.update(cx, |project, cx| {
+ project.worktrees(cx).next().unwrap().read(cx).id()
+ });
+
+ // Configure .venv as read-only
+ workspace.update_in(cx, |_workspace, _window, cx| {
+ cx.update_global::<SettingsStore, _>(|store, cx| {
+ store
+ .set_user_settings(r#"{"read_only_files": ["**/.venv/**"]}"#, cx)
+ .ok();
+ });
+ });
+
+ let item_dep = cx.new(|cx| {
+ TestItem::new(cx).with_project_items(&[TestProjectItem::new_in_worktree(
+ 1001,
+ ".venv/lib/dep.py",
+ worktree_id,
+ cx,
+ )])
+ });
+
+ // dep.py is active but matches read_only_files → should be skipped
+ workspace.update_in(cx, |workspace, window, cx| {
+ workspace.add_item_to_active_pane(Box::new(item_dep.clone()), None, true, window, cx);
+ });
+ let path = workspace.read_with(cx, |workspace, cx| workspace.most_recent_active_path(cx));
+ assert_eq!(path, None);
+ }
}