Temporarily revert git panel diff editor feature (#22733)

Mikayla Maki and Cole created

The existing code was causing us to constantly re-scan files when
anything changed in the project. Temporarily revert this as we're about
to rework this entire UI with the new primitives.

follow up to https://github.com/zed-industries/zed/pull/22329

Release Notes:

- N/A

---------

Co-authored-by: Cole <cole@zed.dev>

Change summary

Cargo.lock                                |   3 
crates/git_ui/Cargo.toml                  |   3 
crates/git_ui/src/git_panel.rs            | 553 ++++++++++++------------
crates/project/src/lsp_store.rs           |   1 
crates/project/src/project.rs             |   2 
crates/project/src/worktree_store.rs      |  12 
crates/project_panel/src/project_panel.rs |   2 
7 files changed, 274 insertions(+), 302 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -5178,11 +5178,8 @@ dependencies = [
  "anyhow",
  "collections",
  "db",
- "editor",
- "futures 0.3.31",
  "git",
  "gpui",
- "language",
  "menu",
  "project",
  "schemars",

crates/git_ui/Cargo.toml 🔗

@@ -16,11 +16,8 @@ path = "src/git_ui.rs"
 anyhow.workspace = true
 collections.workspace = true
 db.workspace = true
-editor.workspace = true
-futures.workspace = true
 git.workspace = true
 gpui.workspace = true
-language.workspace = true
 menu.workspace = true
 project.workspace = true
 schemars.workspace = true

crates/git_ui/src/git_panel.rs 🔗

@@ -1,11 +1,7 @@
 use crate::{git_status_icon, settings::GitPanelSettings};
 use crate::{CommitAllChanges, CommitStagedChanges, DiscardAll, StageAll, UnstageAll};
-use anyhow::{Context as _, Result};
+use anyhow::Result;
 use db::kvp::KEY_VALUE_STORE;
-use editor::{
-    scroll::{Autoscroll, AutoscrollStrategy},
-    Editor, MultiBuffer, DEFAULT_MULTIBUFFER_CONTEXT,
-};
 use git::{
     diff::DiffHunk,
     repository::{GitFileStatus, RepoPath},
@@ -17,9 +13,8 @@ use gpui::{
     ListHorizontalSizingBehavior, ListSizingBehavior, Model, Modifiers, ModifiersChangedEvent,
     MouseButton, ScrollStrategy, Stateful, Task, UniformListScrollHandle, View, WeakView,
 };
-use language::{Buffer, BufferRow, OffsetRangeExt};
 use menu::{SelectNext, SelectPrev};
-use project::{EntryKind, Fs, Project, ProjectEntryId, ProjectPath, WorktreeId};
+use project::{EntryKind, Fs, Project, ProjectEntryId, WorktreeId};
 use serde::{Deserialize, Serialize};
 use settings::Settings as _;
 use std::{
@@ -40,7 +35,7 @@ use ui::{
 use util::{ResultExt, TryFutureExt};
 use workspace::{
     dock::{DockPosition, Panel, PanelEvent},
-    ItemHandle, Workspace,
+    Workspace,
 };
 use worktree::StatusEntry;
 
@@ -93,7 +88,7 @@ struct SerializedGitPanel {
 }
 
 pub struct GitPanel {
-    workspace: WeakView<Workspace>,
+    // workspace: WeakView<Workspace>,
     current_modifiers: Modifiers,
     focus_handle: FocusHandle,
     fs: Arc<dyn Fs>,
@@ -111,8 +106,8 @@ pub struct GitPanel {
     // not hidden by folding or such
     visible_entries: Vec<WorktreeEntries>,
     width: Option<Pixels>,
-    git_diff_editor: Option<View<Editor>>,
-    git_diff_editor_updates: Task<()>,
+    // git_diff_editor: Option<View<Editor>>,
+    // git_diff_editor_updates: Task<()>,
     reveal_in_editor: Task<()>,
 }
 
@@ -120,7 +115,7 @@ pub struct GitPanel {
 struct WorktreeEntries {
     worktree_id: WorktreeId,
     // TODO support multiple repositories per worktree
-    work_directory: worktree::WorkDirectory,
+    // work_directory: worktree::WorkDirectory,
     visible_entries: Vec<GitPanelEntry>,
     paths: Rc<OnceCell<HashSet<RepoPath>>>,
 }
@@ -160,7 +155,7 @@ impl GitPanel {
 
     pub fn new(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
         let fs = workspace.app_state().fs.clone();
-        let weak_workspace = workspace.weak_handle();
+        // let weak_workspace = workspace.weak_handle();
         let project = workspace.project().clone();
 
         let git_panel = cx.new_view(|cx: &mut ViewContext<Self>| {
@@ -171,9 +166,6 @@ impl GitPanel {
             })
             .detach();
             cx.subscribe(&project, |this, _, event, cx| match event {
-                project::Event::GitRepositoryUpdated => {
-                    this.update_visible_entries(None, None, cx);
-                }
                 project::Event::WorktreeRemoved(_id) => {
                     // this.expanded_dir_ids.remove(id);
                     this.update_visible_entries(None, None, cx);
@@ -190,11 +182,11 @@ impl GitPanel {
                     cx.notify();
                 }
                 project::Event::Closed => {
-                    this.git_diff_editor_updates = Task::ready(());
+                    // this.git_diff_editor_updates = Task::ready(());
                     this.reveal_in_editor = Task::ready(());
                     // this.expanded_dir_ids.clear();
                     this.visible_entries.clear();
-                    this.git_diff_editor = None;
+                    // this.git_diff_editor = None;
                 }
                 _ => {}
             })
@@ -203,7 +195,7 @@ impl GitPanel {
             let scroll_handle = UniformListScrollHandle::new();
 
             let mut git_panel = Self {
-                workspace: weak_workspace,
+                // workspace: weak_workspace,
                 focus_handle: cx.focus_handle(),
                 fs,
                 pending_serialization: Task::ready(None),
@@ -216,8 +208,8 @@ impl GitPanel {
                 selected_item: None,
                 show_scrollbar: !Self::should_autohide_scrollbar(cx),
                 hide_scrollbar_task: None,
-                git_diff_editor: Some(diff_display_editor(cx)),
-                git_diff_editor_updates: Task::ready(()),
+                // git_diff_editor: Some(diff_display_editor(cx)),
+                // git_diff_editor_updates: Task::ready(()),
                 reveal_in_editor: Task::ready(()),
                 project,
             };
@@ -527,6 +519,7 @@ impl GitPanel {
 
     // TODO: Update expanded directory state
     // TODO: Updates happen in the main loop, could be long for large workspaces
+    #[track_caller]
     fn update_visible_entries(
         &mut self,
         for_worktree: Option<WorktreeId>,
@@ -562,10 +555,10 @@ impl GitPanel {
             let mut visible_worktree_entries = Vec::new();
             // Only use the first repository for now
             let repositories = snapshot.repositories().take(1);
-            let mut work_directory = None;
+            // let mut work_directory = None;
             for repository in repositories {
                 visible_worktree_entries.extend(repository.status());
-                work_directory = Some(worktree::WorkDirectory::clone(repository));
+                // work_directory = Some(worktree::WorkDirectory::clone(repository));
             }
 
             // TODO use the GitTraversal
@@ -581,7 +574,7 @@ impl GitPanel {
             if !visible_worktree_entries.is_empty() {
                 self.visible_entries.push(WorktreeEntries {
                     worktree_id,
-                    work_directory: work_directory.unwrap(),
+                    // work_directory: work_directory.unwrap(),
                     visible_entries: visible_worktree_entries
                         .into_iter()
                         .map(|entry| GitPanelEntry {
@@ -615,166 +608,166 @@ impl GitPanel {
         //     );
         // }
 
-        let project = self.project.downgrade();
-        self.git_diff_editor_updates = cx.spawn(|git_panel, mut cx| async move {
-            cx.background_executor()
-                .timer(UPDATE_DEBOUNCE)
-                .await;
-            let Some(project_buffers) = git_panel
-                .update(&mut cx, |git_panel, cx| {
-                    futures::future::join_all(git_panel.visible_entries.iter_mut().flat_map(
-                        |worktree_entries| {
-                            worktree_entries
-                                .visible_entries
-                                .iter()
-                                .filter_map(|entry| {
-                                    let git_status = entry.status;
-                                    let entry_hunks = entry.hunks.clone();
-                                    let (entry_path, unstaged_changes_task) =
-                                        project.update(cx, |project, cx| {
-                                            let entry_path = ProjectPath {
-                                                worktree_id: worktree_entries.worktree_id,
-                                                path: worktree_entries.work_directory.unrelativize(&entry.repo_path)?,
-                                            };
-                                            let open_task =
-                                                project.open_path(entry_path.clone(), cx);
-                                            let unstaged_changes_task =
-                                                cx.spawn(|project, mut cx| async move {
-                                                    let (_, opened_model) = open_task
-                                                        .await
-                                                        .context("opening buffer")?;
-                                                    let buffer = opened_model
-                                                        .downcast::<Buffer>()
-                                                        .map_err(|_| {
-                                                            anyhow::anyhow!(
-                                                                "accessing buffer for entry"
-                                                            )
-                                                        })?;
-                                                    // TODO added files have noop changes and those are not expanded properly in the multi buffer
-                                                    let unstaged_changes = project
-                                                        .update(&mut cx, |project, cx| {
-                                                            project.open_unstaged_changes(
-                                                                buffer.clone(),
-                                                                cx,
-                                                            )
-                                                        })?
-                                                        .await
-                                                        .context("opening unstaged changes")?;
-
-                                                    let hunks = cx.update(|cx| {
-                                                        entry_hunks
-                                                            .get_or_init(|| {
-                                                                match git_status {
-                                                                    GitFileStatus::Added => {
-                                                                        let buffer_snapshot = buffer.read(cx).snapshot();
-                                                                        let entire_buffer_range =
-                                                                            buffer_snapshot.anchor_after(0)
-                                                                                ..buffer_snapshot
-                                                                                    .anchor_before(
-                                                                                        buffer_snapshot.len(),
-                                                                                    );
-                                                                        let entire_buffer_point_range =
-                                                                            entire_buffer_range
-                                                                                .clone()
-                                                                                .to_point(&buffer_snapshot);
-
-                                                                        vec![DiffHunk {
-                                                                            row_range: entire_buffer_point_range
-                                                                                .start
-                                                                                .row
-                                                                                ..entire_buffer_point_range
-                                                                                    .end
-                                                                                    .row,
-                                                                            buffer_range: entire_buffer_range,
-                                                                            diff_base_byte_range: 0..0,
-                                                                        }]
-                                                                    }
-                                                                    GitFileStatus::Modified => {
-                                                                            let buffer_snapshot =
-                                                                                buffer.read(cx).snapshot();
-                                                                            unstaged_changes.read(cx)
-                                                                                .diff_to_buffer
-                                                                                .hunks_in_row_range(
-                                                                                    0..BufferRow::MAX,
-                                                                                    &buffer_snapshot,
-                                                                                )
-                                                                                .collect()
-                                                                    }
-                                                                    // TODO support these
-                                                                    GitFileStatus::Conflict | GitFileStatus::Deleted | GitFileStatus::Untracked => Vec::new(),
-                                                                }
-                                                            }).clone()
-                                                    })?;
-
-                                                    anyhow::Ok((buffer, unstaged_changes, hunks))
-                                                });
-                                            Some((entry_path, unstaged_changes_task))
-                                        }).ok()??;
-                                    Some((entry_path, unstaged_changes_task))
-                                })
-                                .map(|(entry_path, open_task)| async move {
-                                    (entry_path, open_task.await)
-                                })
-                                .collect::<Vec<_>>()
-                        },
-                    ))
-                })
-                .ok()
-            else {
-                return;
-            };
-
-            let project_buffers = project_buffers.await;
-            if project_buffers.is_empty() {
-                return;
-            }
-            let mut change_sets = Vec::with_capacity(project_buffers.len());
-            if let Some(buffer_update_task) = git_panel
-                .update(&mut cx, |git_panel, cx| {
-                    let editor = git_panel.git_diff_editor.clone()?;
-                    let multi_buffer = editor.read(cx).buffer().clone();
-                    let mut buffers_with_ranges = Vec::with_capacity(project_buffers.len());
-                    for (buffer_path, open_result) in project_buffers {
-                        if let Some((buffer, unstaged_changes, diff_hunks)) = open_result
-                            .with_context(|| format!("opening buffer {buffer_path:?}"))
-                            .log_err()
-                        {
-                            change_sets.push(unstaged_changes);
-                            buffers_with_ranges.push((
-                                buffer,
-                                diff_hunks
-                                    .into_iter()
-                                    .map(|hunk| hunk.buffer_range)
-                                    .collect(),
-                            ));
-                        }
-                    }
+        // let project = self.project.downgrade();
+        // self.git_diff_editor_updates = cx.spawn(|git_panel, mut cx| async move {
+        //     cx.background_executor()
+        //         .timer(UPDATE_DEBOUNCE)
+        //         .await;
+        //     let Some(project_buffers) = git_panel
+        //         .update(&mut cx, |git_panel, cx| {
+        //             futures::future::join_all(git_panel.visible_entries.iter_mut().flat_map(
+        //                 |worktree_entries| {
+        //                     worktree_entries
+        //                         .visible_entries
+        //                         .iter()
+        //                         .filter_map(|entry| {
+        //                             let git_status = entry.status;
+        //                             let entry_hunks = entry.hunks.clone();
+        //                             let (entry_path, unstaged_changes_task) =
+        //                                 project.update(cx, |project, cx| {
+        //                                     let entry_path = ProjectPath {
+        //                                         worktree_id: worktree_entries.worktree_id,
+        //                                         path: worktree_entries.work_directory.unrelativize(&entry.repo_path)?,
+        //                                     };
+        //                                     let open_task =
+        //                                         project.open_path(entry_path.clone(), cx);
+        //                                     let unstaged_changes_task =
+        //                                         cx.spawn(|project, mut cx| async move {
+        //                                             let (_, opened_model) = open_task
+        //                                                 .await
+        //                                                 .context("opening buffer")?;
+        //                                             let buffer = opened_model
+        //                                                 .downcast::<Buffer>()
+        //                                                 .map_err(|_| {
+        //                                                     anyhow::anyhow!(
+        //                                                         "accessing buffer for entry"
+        //                                                     )
+        //                                                 })?;
+        //                                             // TODO added files have noop changes and those are not expanded properly in the multi buffer
+        //                                             let unstaged_changes = project
+        //                                                 .update(&mut cx, |project, cx| {
+        //                                                     project.open_unstaged_changes(
+        //                                                         buffer.clone(),
+        //                                                         cx,
+        //                                                     )
+        //                                                 })?
+        //                                                 .await
+        //                                                 .context("opening unstaged changes")?;
+
+        //                                             let hunks = cx.update(|cx| {
+        //                                                 entry_hunks
+        //                                                     .get_or_init(|| {
+        //                                                         match git_status {
+        //                                                             GitFileStatus::Added => {
+        //                                                                 let buffer_snapshot = buffer.read(cx).snapshot();
+        //                                                                 let entire_buffer_range =
+        //                                                                     buffer_snapshot.anchor_after(0)
+        //                                                                         ..buffer_snapshot
+        //                                                                             .anchor_before(
+        //                                                                                 buffer_snapshot.len(),
+        //                                                                             );
+        //                                                                 let entire_buffer_point_range =
+        //                                                                     entire_buffer_range
+        //                                                                         .clone()
+        //                                                                         .to_point(&buffer_snapshot);
+
+        //                                                                 vec![DiffHunk {
+        //                                                                     row_range: entire_buffer_point_range
+        //                                                                         .start
+        //                                                                         .row
+        //                                                                         ..entire_buffer_point_range
+        //                                                                             .end
+        //                                                                             .row,
+        //                                                                     buffer_range: entire_buffer_range,
+        //                                                                     diff_base_byte_range: 0..0,
+        //                                                                 }]
+        //                                                             }
+        //                                                             GitFileStatus::Modified => {
+        //                                                                     let buffer_snapshot =
+        //                                                                         buffer.read(cx).snapshot();
+        //                                                                     unstaged_changes.read(cx)
+        //                                                                         .diff_to_buffer
+        //                                                                         .hunks_in_row_range(
+        //                                                                             0..BufferRow::MAX,
+        //                                                                             &buffer_snapshot,
+        //                                                                         )
+        //                                                                         .collect()
+        //                                                             }
+        //                                                             // TODO support these
+        //                                                             GitFileStatus::Conflict | GitFileStatus::Deleted | GitFileStatus::Untracked => Vec::new(),
+        //                                                         }
+        //                                                     }).clone()
+        //                                             })?;
+
+        //                                             anyhow::Ok((buffer, unstaged_changes, hunks))
+        //                                         });
+        //                                     Some((entry_path, unstaged_changes_task))
+        //                                 }).ok()??;
+        //                             Some((entry_path, unstaged_changes_task))
+        //                         })
+        //                         .map(|(entry_path, open_task)| async move {
+        //                             (entry_path, open_task.await)
+        //                         })
+        //                         .collect::<Vec<_>>()
+        //                 },
+        //             ))
+        //         })
+        //         .ok()
+        //     else {
+        //         return;
+        //     };
+
+        //     let project_buffers = project_buffers.await;
+        //     if project_buffers.is_empty() {
+        //         return;
+        //     }
+        //     let mut change_sets = Vec::with_capacity(project_buffers.len());
+        //     if let Some(buffer_update_task) = git_panel
+        //         .update(&mut cx, |git_panel, cx| {
+        //             let editor = git_panel.git_diff_editor.clone()?;
+        //             let multi_buffer = editor.read(cx).buffer().clone();
+        //             let mut buffers_with_ranges = Vec::with_capacity(project_buffers.len());
+        //             for (buffer_path, open_result) in project_buffers {
+        //                 if let Some((buffer, unstaged_changes, diff_hunks)) = open_result
+        //                     .with_context(|| format!("opening buffer {buffer_path:?}"))
+        //                     .log_err()
+        //                 {
+        //                     change_sets.push(unstaged_changes);
+        //                     buffers_with_ranges.push((
+        //                         buffer,
+        //                         diff_hunks
+        //                             .into_iter()
+        //                             .map(|hunk| hunk.buffer_range)
+        //                             .collect(),
+        //                     ));
+        //                 }
+        //             }
 
-                    Some(multi_buffer.update(cx, |multi_buffer, cx| {
-                        multi_buffer.clear(cx);
-                        multi_buffer.push_multiple_excerpts_with_context_lines(
-                            buffers_with_ranges,
-                            DEFAULT_MULTIBUFFER_CONTEXT,
-                            cx,
-                        )
-                    }))
-                })
-                .ok().flatten()
-            {
-                buffer_update_task.await;
-                git_panel
-                    .update(&mut cx, |git_panel, cx| {
-                        if let Some(diff_editor) = git_panel.git_diff_editor.as_ref() {
-                            diff_editor.update(cx, |editor, cx| {
-                                for change_set in change_sets {
-                                    editor.add_change_set(change_set, cx);
-                                }
-                            });
-                        }
-                    })
-                    .ok();
-            }
-        });
+        //             Some(multi_buffer.update(cx, |multi_buffer, cx| {
+        //                 multi_buffer.clear(cx);
+        //                 multi_buffer.push_multiple_excerpts_with_context_lines(
+        //                     buffers_with_ranges,
+        //                     DEFAULT_MULTIBUFFER_CONTEXT,
+        //                     cx,
+        //                 )
+        //             }))
+        //         })
+        //         .ok().flatten()
+        //     {
+        //         buffer_update_task.await;
+        //         git_panel
+        //             .update(&mut cx, |git_panel, cx| {
+        //                 if let Some(diff_editor) = git_panel.git_diff_editor.as_ref() {
+        //                     diff_editor.update(cx, |editor, cx| {
+        //                         for change_set in change_sets {
+        //                             editor.add_change_set(change_set, cx);
+        //                         }
+        //                     });
+        //                 }
+        //             })
+        //             .ok();
+        //     }
+        // });
 
         cx.notify();
     }
@@ -1058,94 +1051,94 @@ impl GitPanel {
 
     fn reveal_entry_in_git_editor(
         &mut self,
-        hunks: Rc<OnceCell<Vec<DiffHunk>>>,
-        change_focus: bool,
-        debounce: Option<Duration>,
-        cx: &mut ViewContext<Self>,
+        _hunks: Rc<OnceCell<Vec<DiffHunk>>>,
+        _change_focus: bool,
+        _debounce: Option<Duration>,
+        _cx: &mut ViewContext<Self>,
     ) {
-        let workspace = self.workspace.clone();
-        let Some(diff_editor) = self.git_diff_editor.clone() else {
-            return;
-        };
-        self.reveal_in_editor = cx.spawn(|_, mut cx| async move {
-            if let Some(debounce) = debounce {
-                cx.background_executor().timer(debounce).await;
-            }
-
-            let Some(editor) = workspace
-                .update(&mut cx, |workspace, cx| {
-                    let git_diff_editor = workspace
-                        .items_of_type::<Editor>(cx)
-                        .find(|editor| &diff_editor == editor);
-                    match git_diff_editor {
-                        Some(existing_editor) => {
-                            workspace.activate_item(&existing_editor, true, change_focus, cx);
-                            existing_editor
-                        }
-                        None => {
-                            workspace.active_pane().update(cx, |pane, cx| {
-                                pane.add_item(
-                                    diff_editor.boxed_clone(),
-                                    true,
-                                    change_focus,
-                                    None,
-                                    cx,
-                                )
-                            });
-                            diff_editor.clone()
-                        }
-                    }
-                })
-                .ok()
-            else {
-                return;
-            };
-
-            if let Some(first_hunk) = hunks.get().and_then(|hunks| hunks.first()) {
-                let hunk_buffer_range = &first_hunk.buffer_range;
-                if let Some(buffer_id) = hunk_buffer_range
-                    .start
-                    .buffer_id
-                    .or_else(|| first_hunk.buffer_range.end.buffer_id)
-                {
-                    editor
-                        .update(&mut cx, |editor, cx| {
-                            let multi_buffer = editor.buffer().read(cx);
-                            let buffer = multi_buffer.buffer(buffer_id)?;
-                            let buffer_snapshot = buffer.read(cx).snapshot();
-                            let (excerpt_id, _) = multi_buffer
-                                .excerpts_for_buffer(&buffer, cx)
-                                .into_iter()
-                                .find(|(_, excerpt)| {
-                                    hunk_buffer_range
-                                        .start
-                                        .cmp(&excerpt.context.start, &buffer_snapshot)
-                                        .is_ge()
-                                        && hunk_buffer_range
-                                            .end
-                                            .cmp(&excerpt.context.end, &buffer_snapshot)
-                                            .is_le()
-                                })?;
-                            let multi_buffer_hunk_start = multi_buffer
-                                .snapshot(cx)
-                                .anchor_in_excerpt(excerpt_id, hunk_buffer_range.start)?;
-                            editor.change_selections(
-                                Some(Autoscroll::Strategy(AutoscrollStrategy::Center)),
-                                cx,
-                                |s| {
-                                    s.select_ranges(Some(
-                                        multi_buffer_hunk_start..multi_buffer_hunk_start,
-                                    ))
-                                },
-                            );
-                            cx.notify();
-                            Some(())
-                        })
-                        .ok()
-                        .flatten();
-                }
-            }
-        });
+        // let workspace = self.workspace.clone();
+        // let Some(diff_editor) = self.git_diff_editor.clone() else {
+        //     return;
+        // };
+        // self.reveal_in_editor = cx.spawn(|_, mut cx| async move {
+        //     if let Some(debounce) = debounce {
+        //         cx.background_executor().timer(debounce).await;
+        //     }
+
+        //     let Some(editor) = workspace
+        //         .update(&mut cx, |workspace, cx| {
+        //             let git_diff_editor = workspace
+        //                 .items_of_type::<Editor>(cx)
+        //                 .find(|editor| &diff_editor == editor);
+        //             match git_diff_editor {
+        //                 Some(existing_editor) => {
+        //                     workspace.activate_item(&existing_editor, true, change_focus, cx);
+        //                     existing_editor
+        //                 }
+        //                 None => {
+        //                     workspace.active_pane().update(cx, |pane, cx| {
+        //                         pane.add_item(
+        //                          `   diff_editor.boxed_clone(),
+        //                             true,
+        //                             change_focus,
+        //                             None,
+        //                             cx,
+        //                         )
+        //                     });
+        //                     diff_editor.clone()
+        //                 }
+        //             }
+        //         })
+        //         .ok()
+        //     else {
+        //         return;
+        //     };
+
+        //     if let Some(first_hunk) = hunks.get().and_then(|hunks| hunks.first()) {
+        //         let hunk_buffer_range = &first_hunk.buffer_range;
+        //         if let Some(buffer_id) = hunk_buffer_range
+        //             .start
+        //             .buffer_id
+        //             .or_else(|| first_hunk.buffer_range.end.buffer_id)
+        //         {
+        //             editor
+        //                 .update(&mut cx, |editor, cx| {
+        //                     let multi_buffer = editor.buffer().read(cx);
+        //                     let buffer = multi_buffer.buffer(buffer_id)?;
+        //                     let buffer_snapshot = buffer.read(cx).snapshot();
+        //                     let (excerpt_id, _) = multi_buffer
+        //                         .excerpts_for_buffer(&buffer, cx)
+        //                         .into_iter()
+        //                         .find(|(_, excerpt)| {
+        //                             hunk_buffer_range
+        //                                 .start
+        //                                 .cmp(&excerpt.context.start, &buffer_snapshot)
+        //                                 .is_ge()
+        //                                 && hunk_buffer_range
+        //                                     .end
+        //                                     .cmp(&excerpt.context.end, &buffer_snapshot)
+        //                                     .is_le()
+        //                         })?;
+        //                     let multi_buffer_hunk_start = multi_buffer
+        //                         .snapshot(cx)
+        //                         .anchor_in_excerpt(excerpt_id, hunk_buffer_range.start)?;
+        //                     editor.change_selections(
+        //                         Some(Autoscroll::Strategy(AutoscrollStrategy::Center)),
+        //                         cx,
+        //                         |s| {
+        //                             s.select_ranges(Some(
+        //                                 multi_buffer_hunk_start..multi_buffer_hunk_start,
+        //                             ))
+        //                         },
+        //                     );
+        //                     cx.notify();
+        //                     Some(())
+        //                 })
+        //                 .ok()
+        //                 .flatten();
+        //         }
+        //     }
+        // });
     }
 }
 
@@ -1260,13 +1253,13 @@ impl Panel for GitPanel {
     }
 }
 
-fn diff_display_editor(cx: &mut WindowContext) -> View<Editor> {
-    cx.new_view(|cx| {
-        let multi_buffer = cx.new_model(|_| {
-            MultiBuffer::new(language::Capability::ReadWrite).with_title("Project diff".to_string())
-        });
-        let mut editor = Editor::for_multibuffer(multi_buffer, None, true, cx);
-        editor.set_expand_all_diff_hunks();
-        editor
-    })
-}
+// fn diff_display_editor(cx: &mut WindowContext) -> View<Editor> {
+//     cx.new_view(|cx| {
+//         let multi_buffer = cx.new_model(|_| {
+//             MultiBuffer::new(language::Capability::ReadWrite).with_title("Project diff".to_string())
+//         });
+//         let mut editor = Editor::for_multibuffer(multi_buffer, None, true, cx);
+//         editor.set_expand_all_diff_hunks();
+//         editor
+//     })
+// }

crates/project/src/lsp_store.rs 🔗

@@ -3108,7 +3108,6 @@ impl LspStore {
             WorktreeStoreEvent::WorktreeUpdateSent(worktree) => {
                 worktree.update(cx, |worktree, _cx| self.send_diagnostic_summaries(worktree));
             }
-            WorktreeStoreEvent::GitRepositoryUpdated => {}
         }
     }
 

crates/project/src/project.rs 🔗

@@ -244,7 +244,6 @@ pub enum Event {
     ActivateProjectPanel,
     WorktreeAdded(WorktreeId),
     WorktreeOrderChanged,
-    GitRepositoryUpdated,
     WorktreeRemoved(WorktreeId),
     WorktreeUpdatedEntries(WorktreeId, UpdatedEntriesSet),
     WorktreeUpdatedGitRepositories(WorktreeId),
@@ -2307,7 +2306,6 @@ impl Project {
             }
             WorktreeStoreEvent::WorktreeOrderChanged => cx.emit(Event::WorktreeOrderChanged),
             WorktreeStoreEvent::WorktreeUpdateSent(_) => {}
-            WorktreeStoreEvent::GitRepositoryUpdated => cx.emit(Event::GitRepositoryUpdated),
         }
     }
 

crates/project/src/worktree_store.rs 🔗

@@ -62,7 +62,6 @@ pub enum WorktreeStoreEvent {
     WorktreeReleased(EntityId, WorktreeId),
     WorktreeOrderChanged,
     WorktreeUpdateSent(Model<Worktree>),
-    GitRepositoryUpdated,
 }
 
 impl EventEmitter<WorktreeStoreEvent> for WorktreeStore {}
@@ -376,17 +375,6 @@ impl WorktreeStore {
             this.send_project_updates(cx);
         })
         .detach();
-
-        cx.subscribe(
-            worktree,
-            |_this, _, event: &worktree::Event, cx| match event {
-                worktree::Event::UpdatedGitRepositories(_) => {
-                    cx.emit(WorktreeStoreEvent::GitRepositoryUpdated);
-                }
-                worktree::Event::DeletedEntry(_) | worktree::Event::UpdatedEntries(_) => {}
-            },
-        )
-        .detach();
     }
 
     pub fn remove_worktree(&mut self, id_to_remove: WorktreeId, cx: &mut ModelContext<Self>) {

crates/project_panel/src/project_panel.rs 🔗

@@ -311,7 +311,7 @@ impl ProjectPanel {
                     this.update_visible_entries(None, cx);
                     cx.notify();
                 }
-                project::Event::GitRepositoryUpdated
+                project::Event::WorktreeUpdatedGitRepositories(_)
                 | project::Event::WorktreeUpdatedEntries(_, _)
                 | project::Event::WorktreeAdded(_)
                 | project::Event::WorktreeOrderChanged => {