Don't show trust modal for linked worktrees if main is trusted (#57153)

Follow up to https://github.com/zed-industries/zed/pull/57056 — This PR
ensures we're refreshing the security modal so that it consumes the
trust given to the main worktree when creating a new linked (Git)
worktree.

Release Notes:

- N/A
This commit is contained in:
Danilo Leal authored and GitHub committed 2026-05-19 14:32:46 +00:00
1 parent 4dcdf4866a
commit 3828e788d2
3 files changed
+127 -2

No files matched your search

+120
View File
@@ -282,6 +282,15 @@ fn maybe_propagate_worktree_trust(
}
})
.ok();
// After trust propagation, refresh the security modal on the new workspace
// so it dismisses itself if there are no more restricted worktrees.
cx.update(|window, cx| {
new_workspace.update(cx, |workspace, cx| {
workspace.show_worktree_trust_security_modal(false, window, cx);
});
})
.ok();
}
/// Handles the `CreateWorktree` action generically, without any agent panel involvement.
@@ -1011,4 +1020,115 @@ mod tests {
"switching back to the main worktree should not rerun create_worktree hooks"
);
}
#[gpui::test]
async fn test_linked_worktree_inherits_trust_from_main_worktree(cx: &mut TestAppContext) {
init_test(cx);
cx.update(|cx| {
project::trusted_worktrees::init(collections::HashMap::default(), cx);
});
let fs = FakeFs::new(cx.background_executor.clone());
cx.update(|cx| <dyn Fs>::set_global(fs.clone(), cx));
fs.insert_tree(
"/root",
json!({
"project": {
".git": {},
"src": {
"main.rs": "fn main() {}",
},
},
}),
)
.await;
let main_project_root = PathBuf::from(path!("/root/project"));
let project =
Project::test_with_worktree_trust(fs.clone(), [main_project_root.as_path()], cx).await;
project
.update(cx, |project, cx| project.git_scans_complete(cx))
.await;
// The main worktree starts restricted; trust it explicitly
let worktree_store = project.read_with(cx, |project, _| project.worktree_store());
let main_worktree_id = worktree_store.read_with(cx, |store, cx| {
store
.worktrees()
.next()
.map(|wt| wt.read(cx).id())
.expect("should have a worktree")
});
let trusted_store = cx
.read(|cx| project::trusted_worktrees::TrustedWorktrees::try_get_global(cx))
.expect("trust store should exist");
trusted_store.update(cx, |store, cx| {
store.trust(
&worktree_store,
collections::HashSet::from_iter([project::trusted_worktrees::PathTrust::Worktree(
main_worktree_id,
)]),
cx,
);
});
// Verify main worktree is now trusted
let has_restricted = cx.read(|cx| {
project::trusted_worktrees::TrustedWorktrees::has_restricted_worktrees(
&worktree_store,
cx,
)
});
assert!(
!has_restricted,
"main worktree should be trusted after explicit trust"
);
let (multi_workspace, cx) =
cx.add_window_view(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));
multi_workspace.update(cx, |multi_workspace, cx| {
multi_workspace.retain_active_workspace(cx);
});
// Create a linked worktree from the trusted main worktree
let main_workspace = multi_workspace.read_with(cx, |mw, _| mw.workspace().clone());
main_workspace.update_in(cx, |workspace, window, cx| {
handle_create_worktree(
workspace,
&zed_actions::CreateWorktree {
worktree_name: Some("feature".to_string()),
branch_target: NewWorktreeBranchTarget::CurrentBranch,
},
window,
None,
cx,
);
});
cx.run_until_parked();
// The new workspace (linked worktree) should inherit trust
let new_workspace = multi_workspace.read_with(cx, |mw, _| mw.workspace().clone());
let new_worktree_store =
new_workspace.read_with(cx, |ws, cx| ws.project().read(cx).worktree_store());
let new_has_restricted = cx.read(|cx| {
project::trusted_worktrees::TrustedWorktrees::has_restricted_worktrees(
&new_worktree_store,
cx,
)
});
assert!(
!new_has_restricted,
"linked worktree should inherit trust from the main worktree"
);
// The security modal should not be showing
let has_modal = new_workspace.read_with(cx, |ws, cx| {
ws.active_modal::<workspace::security_modal::SecurityModal>(cx)
.is_some()
});
assert!(
!has_modal,
"security modal should not show for a linked worktree created from a trusted main worktree"
);
}
}
+6 -1
View File
@@ -364,7 +364,12 @@ impl SecurityModal {
if self.restricted_paths != new_restricted_worktrees {
self.trust_parents = false;
self.restricted_paths = new_restricted_worktrees;
cx.notify();
if self.restricted_paths.is_empty() {
self.trusted = Some(true);
self.dismiss(cx);
} else {
cx.notify();
}
}
}
} else if !self.restricted_paths.is_empty() {
+1 -1
View File
@@ -15,7 +15,7 @@ pub mod path_list {
}
mod persistence;
pub mod searchable;
mod security_modal;
pub mod security_modal;
pub mod shared_screen;
pub use shared_screen::SharedScreen;
pub mod focus_follows_mouse;