Show entries in remote git panels (#23773)

Now both remote collab and ssh remote get entries shown and updated in
the git panel.
This seems to be quite a step towards remote git support, hence
submitting a PR.

Further steps: remove `get_local_repo` and allow getting the repo from
`Worktree`, not its local counterpart + have another, remote impl of the
`GitRepository` trait.

Release Notes:

- N/A
This commit is contained in:
Kirill Bulatov 2025-01-28 15:25:59 +02:00 committed by GitHub
parent fc5461adf4
commit 7105f9c68c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 33 additions and 18 deletions

View file

@ -30,7 +30,7 @@ pub struct RepositoryHandle {
git_state: WeakEntity<GitState>, git_state: WeakEntity<GitState>,
worktree_id: WorktreeId, worktree_id: WorktreeId,
repository_entry: RepositoryEntry, repository_entry: RepositoryEntry,
git_repo: Arc<dyn GitRepository>, git_repo: Option<Arc<dyn GitRepository>>,
commit_message: Entity<Buffer>, commit_message: Entity<Buffer>,
update_sender: mpsc::UnboundedSender<(Message, mpsc::Sender<anyhow::Error>)>, update_sender: mpsc::UnboundedSender<(Message, mpsc::Sender<anyhow::Error>)>,
} }
@ -100,7 +100,7 @@ impl GitState {
GitState { GitState {
languages, languages,
repositories: vec![], repositories: Vec::new(),
active_index: None, active_index: None,
update_sender, update_sender,
_subscription, _subscription,
@ -128,13 +128,11 @@ impl GitState {
for worktree in worktree_store.worktrees() { for worktree in worktree_store.worktrees() {
worktree.update(cx, |worktree, cx| { worktree.update(cx, |worktree, cx| {
let snapshot = worktree.snapshot(); let snapshot = worktree.snapshot();
let Some(local) = worktree.as_local() else {
return;
};
for repo in snapshot.repositories().iter() { for repo in snapshot.repositories().iter() {
let Some(local_repo) = local.get_local_repo(repo) else { let git_repo = worktree
continue; .as_local()
}; .and_then(|local_worktree| local_worktree.get_local_repo(repo))
.map(|local_repo| local_repo.repo().clone());
let existing = self let existing = self
.repositories .repositories
.iter() .iter()
@ -166,7 +164,7 @@ impl GitState {
git_state: this.clone(), git_state: this.clone(),
worktree_id: worktree.id(), worktree_id: worktree.id(),
repository_entry: repo.clone(), repository_entry: repo.clone(),
git_repo: local_repo.repo().clone(), git_repo,
commit_message, commit_message,
update_sender: self.update_sender.clone(), update_sender: self.update_sender.clone(),
} }
@ -247,8 +245,11 @@ impl RepositoryHandle {
if entries.is_empty() { if entries.is_empty() {
return Ok(()); return Ok(());
} }
let Some(git_repo) = self.git_repo.clone() else {
return Ok(());
};
self.update_sender self.update_sender
.unbounded_send((Message::Stage(self.git_repo.clone(), entries), err_sender)) .unbounded_send((Message::Stage(git_repo, entries), err_sender))
.map_err(|_| anyhow!("Failed to submit stage operation"))?; .map_err(|_| anyhow!("Failed to submit stage operation"))?;
Ok(()) Ok(())
} }
@ -261,8 +262,11 @@ impl RepositoryHandle {
if entries.is_empty() { if entries.is_empty() {
return Ok(()); return Ok(());
} }
let Some(git_repo) = self.git_repo.clone() else {
return Ok(());
};
self.update_sender self.update_sender
.unbounded_send((Message::Unstage(self.git_repo.clone(), entries), err_sender)) .unbounded_send((Message::Unstage(git_repo, entries), err_sender))
.map_err(|_| anyhow!("Failed to submit unstage operation"))?; .map_err(|_| anyhow!("Failed to submit unstage operation"))?;
Ok(()) Ok(())
} }
@ -314,11 +318,13 @@ impl RepositoryHandle {
} }
pub fn commit(&self, mut err_sender: mpsc::Sender<anyhow::Error>, cx: &mut App) { pub fn commit(&self, mut err_sender: mpsc::Sender<anyhow::Error>, cx: &mut App) {
let Some(git_repo) = self.git_repo.clone() else {
return;
};
let message = self.commit_message.read(cx).as_rope().clone(); let message = self.commit_message.read(cx).as_rope().clone();
let result = self.update_sender.unbounded_send(( let result = self
Message::Commit(self.git_repo.clone(), message), .update_sender
err_sender.clone(), .unbounded_send((Message::Commit(git_repo, message), err_sender.clone()));
));
if result.is_err() { if result.is_err() {
cx.spawn(|_| async move { cx.spawn(|_| async move {
err_sender err_sender
@ -335,6 +341,9 @@ impl RepositoryHandle {
} }
pub fn commit_all(&self, mut err_sender: mpsc::Sender<anyhow::Error>, cx: &mut App) { pub fn commit_all(&self, mut err_sender: mpsc::Sender<anyhow::Error>, cx: &mut App) {
let Some(git_repo) = self.git_repo.clone() else {
return;
};
let to_stage = self let to_stage = self
.repository_entry .repository_entry
.status() .status()
@ -343,7 +352,7 @@ impl RepositoryHandle {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let message = self.commit_message.read(cx).as_rope().clone(); let message = self.commit_message.read(cx).as_rope().clone();
let result = self.update_sender.unbounded_send(( let result = self.update_sender.unbounded_send((
Message::StageAndCommit(self.git_repo.clone(), message, to_stage), Message::StageAndCommit(git_repo, message, to_stage),
err_sender.clone(), err_sender.clone(),
)); ));
if result.is_err() { if result.is_err() {

View file

@ -814,6 +814,9 @@ impl Project {
}); });
cx.subscribe(&lsp_store, Self::on_lsp_store_event).detach(); cx.subscribe(&lsp_store, Self::on_lsp_store_event).detach();
let git_state =
Some(cx.new(|cx| GitState::new(&worktree_store, languages.clone(), cx)));
cx.subscribe(&ssh, Self::on_ssh_event).detach(); cx.subscribe(&ssh, Self::on_ssh_event).detach();
cx.observe(&ssh, |_, _, cx| cx.notify()).detach(); cx.observe(&ssh, |_, _, cx| cx.notify()).detach();
@ -826,7 +829,7 @@ impl Project {
lsp_store, lsp_store,
join_project_response_message_id: 0, join_project_response_message_id: 0,
client_state: ProjectClientState::Local, client_state: ProjectClientState::Local,
git_state: None, git_state,
client_subscriptions: Vec::new(), client_subscriptions: Vec::new(),
_subscriptions: vec![ _subscriptions: vec![
cx.on_release(Self::release), cx.on_release(Self::release),
@ -1009,6 +1012,9 @@ impl Project {
SettingsObserver::new_remote(worktree_store.clone(), task_store.clone(), cx) SettingsObserver::new_remote(worktree_store.clone(), task_store.clone(), cx)
})?; })?;
let git_state =
Some(cx.new(|cx| GitState::new(&worktree_store, languages.clone(), cx))).transpose()?;
let this = cx.new(|cx| { let this = cx.new(|cx| {
let replica_id = response.payload.replica_id as ReplicaId; let replica_id = response.payload.replica_id as ReplicaId;
@ -1059,7 +1065,7 @@ impl Project {
remote_id, remote_id,
replica_id, replica_id,
}, },
git_state: None, git_state,
buffers_needing_diff: Default::default(), buffers_needing_diff: Default::default(),
git_diff_debouncer: DebouncedDelay::new(), git_diff_debouncer: DebouncedDelay::new(),
terminals: Terminals { terminals: Terminals {