Finish removing git repository state and scanning logic from worktrees (#27568)

This PR completes the process of moving git repository state storage and
scanning logic from the worktree crate to `project::git_store`.

Release Notes:

- N/A

---------

Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Co-authored-by: Conrad <conrad@zed.dev>
This commit is contained in:
Cole Miller 2025-04-01 17:41:20 -04:00 committed by GitHub
parent 8f25251faf
commit e7290df02b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
39 changed files with 3121 additions and 3529 deletions

View file

@ -336,7 +336,7 @@ impl PickerDelegate for BranchListDelegate {
let current_branch = self.repo.as_ref().map(|repo| {
repo.update(cx, |repo, _| {
repo.current_branch().map(|branch| branch.name.clone())
repo.branch.as_ref().map(|branch| branch.name.clone())
})
});
@ -463,7 +463,7 @@ impl PickerDelegate for BranchListDelegate {
let message = if entry.is_new {
if let Some(current_branch) =
self.repo.as_ref().and_then(|repo| {
repo.read(cx).current_branch().map(|b| b.name.clone())
repo.read(cx).branch.as_ref().map(|b| b.name.clone())
})
{
format!("based off {}", current_branch)

View file

@ -234,7 +234,7 @@ impl CommitModal {
let branch = active_repo
.as_ref()
.and_then(|repo| repo.read(cx).repository_entry.branch())
.and_then(|repo| repo.read(cx).branch.as_ref())
.map(|b| b.name.clone())
.unwrap_or_else(|| "<no branch>".into());

View file

@ -45,9 +45,10 @@ use panel::{
PanelHeader, panel_button, panel_editor_container, panel_editor_style, panel_filled_button,
panel_icon_button,
};
use project::git_store::RepositoryEvent;
use project::{
Fs, Project, ProjectPath,
git_store::{GitEvent, Repository},
git_store::{GitStoreEvent, Repository},
};
use serde::{Deserialize, Serialize};
use settings::{Settings as _, SettingsStore};
@ -340,7 +341,7 @@ const MAX_PANEL_EDITOR_LINES: usize = 6;
pub(crate) fn commit_message_editor(
commit_message_buffer: Entity<Buffer>,
placeholder: Option<&str>,
placeholder: Option<SharedString>,
project: Entity<Project>,
in_panel: bool,
window: &mut Window,
@ -361,7 +362,7 @@ pub(crate) fn commit_message_editor(
commit_editor.set_show_wrap_guides(false, cx);
commit_editor.set_show_indent_guides(false, cx);
commit_editor.set_hard_wrap(Some(72), cx);
let placeholder = placeholder.unwrap_or("Enter commit message");
let placeholder = placeholder.unwrap_or("Enter commit message".into());
commit_editor.set_placeholder_text(placeholder, cx);
commit_editor
}
@ -403,14 +404,18 @@ impl GitPanel {
&git_store,
window,
move |this, git_store, event, window, cx| match event {
GitEvent::FileSystemUpdated => {
this.schedule_update(false, window, cx);
}
GitEvent::ActiveRepositoryChanged | GitEvent::GitStateUpdated => {
GitStoreEvent::ActiveRepositoryChanged(_) => {
this.active_repository = git_store.read(cx).active_repository();
this.schedule_update(true, window, cx);
}
GitEvent::IndexWriteError(error) => {
GitStoreEvent::RepositoryUpdated(_, RepositoryEvent::Updated, true) => {
this.schedule_update(true, window, cx);
}
GitStoreEvent::RepositoryUpdated(_, _, _) => {}
GitStoreEvent::RepositoryAdded(_) | GitStoreEvent::RepositoryRemoved(_) => {
this.schedule_update(false, window, cx);
}
GitStoreEvent::IndexWriteError(error) => {
this.workspace
.update(cx, |workspace, cx| {
workspace.show_error(error, cx);
@ -828,7 +833,7 @@ impl GitPanel {
.active_repository
.as_ref()
.map_or(false, |active_repository| {
active_repository.read(cx).entry_count() > 0
active_repository.read(cx).status_summary().count > 0
});
if have_entries && self.selected_entry.is_none() {
self.selected_entry = Some(1);
@ -1415,7 +1420,7 @@ impl GitPanel {
let message = self.commit_editor.read(cx).text(cx);
if !message.trim().is_empty() {
return Some(message.to_string());
return Some(message);
}
self.suggest_commit_message(cx)
@ -1593,7 +1598,7 @@ impl GitPanel {
.as_ref()
.and_then(|repo| repo.read(cx).merge_message.as_ref())
{
return Some(merge_message.clone());
return Some(merge_message.to_string());
}
let git_status_entry = if let Some(staged_entry) = &self.single_staged_entry {
@ -1849,7 +1854,7 @@ impl GitPanel {
let Some(repo) = self.active_repository.clone() else {
return;
};
let Some(branch) = repo.read(cx).current_branch() else {
let Some(branch) = repo.read(cx).branch.as_ref() else {
return;
};
telemetry::event!("Git Pulled");
@ -1906,7 +1911,7 @@ impl GitPanel {
let Some(repo) = self.active_repository.clone() else {
return;
};
let Some(branch) = repo.read(cx).current_branch() else {
let Some(branch) = repo.read(cx).branch.as_ref() else {
return;
};
telemetry::event!("Git Pushed");
@ -2019,7 +2024,7 @@ impl GitPanel {
let mut current_remotes: Vec<Remote> = repo
.update(&mut cx, |repo, _| {
let Some(current_branch) = repo.current_branch() else {
let Some(current_branch) = repo.branch.as_ref() else {
return Err(anyhow::anyhow!("No active branch"));
};
@ -2215,7 +2220,7 @@ impl GitPanel {
git_panel.commit_editor = cx.new(|cx| {
commit_message_editor(
buffer,
git_panel.suggest_commit_message(cx).as_deref(),
git_panel.suggest_commit_message(cx).map(SharedString::from),
git_panel.project.clone(),
true,
window,
@ -2275,10 +2280,7 @@ impl GitPanel {
continue;
}
let abs_path = repo
.repository_entry
.work_directory_abs_path
.join(&entry.repo_path.0);
let abs_path = repo.work_directory_abs_path.join(&entry.repo_path.0);
let entry = GitStatusEntry {
repo_path: entry.repo_path.clone(),
abs_path,
@ -2392,9 +2394,7 @@ impl GitPanel {
self.select_first_entry_if_none(cx);
let suggested_commit_message = self.suggest_commit_message(cx);
let placeholder_text = suggested_commit_message
.as_deref()
.unwrap_or("Enter commit message");
let placeholder_text = suggested_commit_message.unwrap_or("Enter commit message".into());
self.commit_editor.update(cx, |editor, cx| {
editor.set_placeholder_text(Arc::from(placeholder_text), cx)
@ -2823,12 +2823,7 @@ impl GitPanel {
}
pub(crate) fn render_remote_button(&self, cx: &mut Context<Self>) -> Option<AnyElement> {
let branch = self
.active_repository
.as_ref()?
.read(cx)
.current_branch()
.cloned();
let branch = self.active_repository.as_ref()?.read(cx).branch.clone();
if !self.can_push_and_pull(cx) {
return None;
}
@ -2868,7 +2863,7 @@ impl GitPanel {
let commit_tooltip_focus_handle = editor_focus_handle.clone();
let expand_tooltip_focus_handle = editor_focus_handle.clone();
let branch = active_repository.read(cx).current_branch().cloned();
let branch = active_repository.read(cx).branch.clone();
let footer_size = px(32.);
let gap = px(9.0);
@ -2999,7 +2994,7 @@ impl GitPanel {
fn render_previous_commit(&self, cx: &mut Context<Self>) -> Option<impl IntoElement> {
let active_repository = self.active_repository.as_ref()?;
let branch = active_repository.read(cx).current_branch()?;
let branch = active_repository.read(cx).branch.as_ref()?;
let commit = branch.most_recent_commit.as_ref()?.clone();
let workspace = self.workspace.clone();

View file

@ -24,7 +24,7 @@ use language::{Anchor, Buffer, Capability, OffsetRangeExt};
use multi_buffer::{MultiBuffer, PathKey};
use project::{
Project, ProjectPath,
git_store::{GitEvent, GitStore},
git_store::{GitStore, GitStoreEvent, RepositoryEvent},
};
use std::any::{Any, TypeId};
use theme::ActiveTheme;
@ -153,9 +153,8 @@ impl ProjectDiff {
&git_store,
window,
move |this, _git_store, event, _window, _cx| match event {
GitEvent::ActiveRepositoryChanged
| GitEvent::FileSystemUpdated
| GitEvent::GitStateUpdated => {
GitStoreEvent::ActiveRepositoryChanged(_)
| GitStoreEvent::RepositoryUpdated(_, RepositoryEvent::Updated, true) => {
*this.update_needed.borrow_mut() = ();
}
_ => {}
@ -452,13 +451,11 @@ impl ProjectDiff {
) -> Result<()> {
while let Some(_) = recv.next().await {
this.update(cx, |this, cx| {
let new_branch =
this.git_store
.read(cx)
.active_repository()
.and_then(|active_repository| {
active_repository.read(cx).current_branch().cloned()
});
let new_branch = this
.git_store
.read(cx)
.active_repository()
.and_then(|active_repository| active_repository.read(cx).branch.clone());
if new_branch != this.current_branch {
this.current_branch = new_branch;
cx.notify();
@ -1499,6 +1496,7 @@ mod tests {
.unindent(),
);
eprintln!(">>>>>>>> git restore");
let prev_buffer_hunks =
cx.update_window_entity(&buffer_editor, |buffer_editor, window, cx| {
let snapshot = buffer_editor.snapshot(window, cx);
@ -1516,14 +1514,13 @@ mod tests {
cx.update_window_entity(&buffer_editor, |buffer_editor, window, cx| {
let snapshot = buffer_editor.snapshot(window, cx);
let snapshot = &snapshot.buffer_snapshot;
let new_buffer_hunks = buffer_editor
buffer_editor
.diff_hunks_in_ranges(&[editor::Anchor::min()..editor::Anchor::max()], snapshot)
.collect::<Vec<_>>();
buffer_editor.git_restore(&Default::default(), window, cx);
new_buffer_hunks
.collect::<Vec<_>>()
});
assert_eq!(new_buffer_hunks.as_slice(), &[]);
eprintln!(">>>>>>>> modify");
cx.update_window_entity(&buffer_editor, |buffer_editor, window, cx| {
buffer_editor.set_text("different\n", window, cx);
buffer_editor.save(false, project.clone(), window, cx)
@ -1533,6 +1530,20 @@ mod tests {
cx.run_until_parked();
cx.update_window_entity(&buffer_editor, |buffer_editor, window, cx| {
buffer_editor.expand_all_diff_hunks(&Default::default(), window, cx);
});
assert_state_with_diff(
&buffer_editor,
cx,
&"
- original
+ different
ˇ"
.unindent(),
);
assert_state_with_diff(
&diff_editor,
cx,