Cargo.lock 🔗
@@ -5439,7 +5439,6 @@ dependencies = [
"panel",
"picker",
"postage",
- "pretty_assertions",
"project",
"schemars",
"serde",
Cole Miller created
This reverts commit e7b3b8bf03f5f8693f8c330b98b656b16ab8f931.
Release Notes:
- N/A
Cargo.lock | 1
crates/git_ui/Cargo.toml | 1
crates/git_ui/src/git_panel.rs | 313 ++++++++++-------------------------
crates/zed/src/zed.rs | 6
4 files changed, 92 insertions(+), 229 deletions(-)
@@ -5439,7 +5439,6 @@ dependencies = [
"panel",
"picker",
"postage",
- "pretty_assertions",
"project",
"schemars",
"serde",
@@ -61,7 +61,6 @@ ctor.workspace = true
env_logger.workspace = true
editor = { workspace = true, features = ["test-support"] }
gpui = { workspace = true, features = ["test-support"] }
-pretty_assertions.workspace = true
project = { workspace = true, features = ["test-support"] }
settings = { workspace = true, features = ["test-support"] }
unindent.workspace = true
@@ -18,14 +18,7 @@ use git::repository::{
};
use git::{repository::RepoPath, status::FileStatus, Commit, ToggleStaged};
use git::{RestoreTrackedFiles, StageAll, TrashUntrackedFiles, UnstageAll};
-use gpui::{
- actions, anchored, deferred, hsla, percentage, point, uniform_list, Action, Animation,
- AnimationExt as _, AnyView, BoxShadow, ClickEvent, Corner, DismissEvent, Entity, EventEmitter,
- FocusHandle, Focusable, KeyContext, ListHorizontalSizingBehavior, ListSizingBehavior,
- Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, Point, PromptLevel,
- ScrollStrategy, Stateful, Subscription, Task, Transformation, UniformListScrollHandle,
- WeakEntity,
-};
+use gpui::*;
use itertools::Itertools;
use language::{Buffer, File};
use menu::{Confirm, SecondaryConfirm, SelectFirst, SelectLast, SelectNext, SelectPrevious};
@@ -42,7 +35,6 @@ use settings::Settings as _;
use smallvec::smallvec;
use std::cell::RefCell;
use std::future::Future;
-use std::path::Path;
use std::rc::Rc;
use std::{collections::HashSet, sync::Arc, time::Duration, usize};
use strum::{IntoEnumIterator, VariantNames};
@@ -52,7 +44,6 @@ use ui::{
Scrollbar, ScrollbarState, Tooltip,
};
use util::{maybe, post_inc, ResultExt, TryFutureExt};
-use workspace::AppState;
use workspace::{
dock::{DockPosition, Panel, PanelEvent},
@@ -72,12 +63,7 @@ actions!(
]
);
-fn prompt<T>(
- msg: &str,
- detail: Option<&str>,
- window: &mut Window,
- cx: &mut App,
-) -> Task<anyhow::Result<T>>
+fn prompt<T>(msg: &str, detail: Option<&str>, window: &mut Window, cx: &mut App) -> Task<Result<T>>
where
T: IntoEnumIterator + VariantNames + 'static,
{
@@ -179,7 +165,6 @@ impl GitListEntry {
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct GitStatusEntry {
pub(crate) repo_path: RepoPath,
- pub(crate) worktree_path: Arc<Path>,
pub(crate) status: FileStatus,
pub(crate) is_staged: Option<bool>,
}
@@ -277,94 +262,96 @@ pub(crate) fn commit_message_editor(
impl GitPanel {
pub fn new(
- workspace: Entity<Workspace>,
- project: Entity<Project>,
- app_state: Arc<AppState>,
+ workspace: &mut Workspace,
window: &mut Window,
- cx: &mut Context<Self>,
- ) -> Self {
- let fs = app_state.fs.clone();
+ cx: &mut Context<Workspace>,
+ ) -> Entity<Self> {
+ let fs = workspace.app_state().fs.clone();
+ let project = workspace.project().clone();
let git_store = project.read(cx).git_store().clone();
let active_repository = project.read(cx).active_repository(cx);
- let workspace = workspace.downgrade();
-
- let focus_handle = cx.focus_handle();
- cx.on_focus(&focus_handle, window, Self::focus_in).detach();
- cx.on_focus_out(&focus_handle, window, |this, _, window, cx| {
- this.hide_scrollbar(window, cx);
- })
- .detach();
+ let workspace = cx.entity().downgrade();
- // just to let us render a placeholder editor.
- // Once the active git repo is set, this buffer will be replaced.
- let temporary_buffer = cx.new(|cx| Buffer::local("", cx));
- let commit_editor = cx.new(|cx| {
- commit_message_editor(temporary_buffer, None, project.clone(), true, window, cx)
- });
-
- commit_editor.update(cx, |editor, cx| {
- editor.clear(window, cx);
- });
+ cx.new(|cx| {
+ let focus_handle = cx.focus_handle();
+ cx.on_focus(&focus_handle, window, Self::focus_in).detach();
+ cx.on_focus_out(&focus_handle, window, |this, _, window, cx| {
+ this.hide_scrollbar(window, cx);
+ })
+ .detach();
- let scroll_handle = UniformListScrollHandle::new();
+ // just to let us render a placeholder editor.
+ // Once the active git repo is set, this buffer will be replaced.
+ let temporary_buffer = cx.new(|cx| Buffer::local("", cx));
+ let commit_editor = cx.new(|cx| {
+ commit_message_editor(temporary_buffer, None, project.clone(), true, window, cx)
+ });
- cx.subscribe_in(
- &git_store,
- window,
- move |this, git_store, event, window, cx| match event {
- GitEvent::FileSystemUpdated => {
- this.schedule_update(false, window, cx);
- }
- GitEvent::ActiveRepositoryChanged | GitEvent::GitStateUpdated => {
- this.active_repository = git_store.read(cx).active_repository();
- this.schedule_update(true, window, cx);
- }
- },
- )
- .detach();
+ commit_editor.update(cx, |editor, cx| {
+ editor.clear(window, cx);
+ });
- let scrollbar_state =
- ScrollbarState::new(scroll_handle.clone()).parent_entity(&cx.entity());
+ let scroll_handle = UniformListScrollHandle::new();
- let repository_selector = cx.new(|cx| RepositorySelector::new(project.clone(), window, cx));
+ cx.subscribe_in(
+ &git_store,
+ window,
+ move |this, git_store, event, window, cx| match event {
+ GitEvent::FileSystemUpdated => {
+ this.schedule_update(false, window, cx);
+ }
+ GitEvent::ActiveRepositoryChanged | GitEvent::GitStateUpdated => {
+ this.active_repository = git_store.read(cx).active_repository();
+ this.schedule_update(true, window, cx);
+ }
+ },
+ )
+ .detach();
- let mut git_panel = Self {
- pending_remote_operations: Default::default(),
- remote_operation_id: 0,
- active_repository,
- commit_editor,
- suggested_commit_message: None,
- conflicted_count: 0,
- conflicted_staged_count: 0,
- current_modifiers: window.modifiers(),
- add_coauthors: true,
- entries: Vec::new(),
- focus_handle: cx.focus_handle(),
- fs,
- hide_scrollbar_task: None,
- new_count: 0,
- new_staged_count: 0,
- pending: Vec::new(),
- pending_commit: None,
- pending_serialization: Task::ready(None),
- project,
- repository_selector,
- scroll_handle,
- scrollbar_state,
- selected_entry: None,
- marked_entries: Vec::new(),
- show_scrollbar: false,
- tracked_count: 0,
- tracked_staged_count: 0,
- update_visible_entries_task: Task::ready(()),
- width: Some(px(360.)),
- context_menu: None,
- workspace,
- modal_open: false,
- };
- git_panel.schedule_update(false, window, cx);
- git_panel.show_scrollbar = git_panel.should_show_scrollbar(cx);
- git_panel
+ let scrollbar_state =
+ ScrollbarState::new(scroll_handle.clone()).parent_entity(&cx.entity());
+
+ let repository_selector =
+ cx.new(|cx| RepositorySelector::new(project.clone(), window, cx));
+
+ let mut git_panel = Self {
+ pending_remote_operations: Default::default(),
+ remote_operation_id: 0,
+ active_repository,
+ commit_editor,
+ suggested_commit_message: None,
+ conflicted_count: 0,
+ conflicted_staged_count: 0,
+ current_modifiers: window.modifiers(),
+ add_coauthors: true,
+ entries: Vec::new(),
+ focus_handle: cx.focus_handle(),
+ fs,
+ hide_scrollbar_task: None,
+ new_count: 0,
+ new_staged_count: 0,
+ pending: Vec::new(),
+ pending_commit: None,
+ pending_serialization: Task::ready(None),
+ project,
+ repository_selector,
+ scroll_handle,
+ scrollbar_state,
+ selected_entry: None,
+ marked_entries: Vec::new(),
+ show_scrollbar: false,
+ tracked_count: 0,
+ tracked_staged_count: 0,
+ update_visible_entries_task: Task::ready(()),
+ width: Some(px(360.)),
+ context_menu: None,
+ workspace,
+ modal_open: false,
+ };
+ git_panel.schedule_update(false, window, cx);
+ git_panel.show_scrollbar = git_panel.should_show_scrollbar(cx);
+ git_panel
+ })
}
pub fn entry_by_path(&self, path: &RepoPath) -> Option<usize> {
@@ -1489,7 +1476,7 @@ impl GitPanel {
&mut self,
window: &mut Window,
cx: &mut Context<Self>,
- ) -> impl Future<Output = anyhow::Result<Option<Remote>>> {
+ ) -> impl Future<Output = Result<Option<Remote>>> {
let repo = self.active_repository.clone();
let workspace = self.workspace.clone();
let mut cx = window.to_async(cx);
@@ -1726,8 +1713,10 @@ impl GitPanel {
return;
};
+ // First pass - collect all paths
let repo = repo.read(cx);
+ // Second pass - create entries with proper depth calculation
for entry in repo.status() {
let is_conflict = repo.has_conflict(&entry.repo_path);
let is_new = entry.status.is_created();
@@ -1741,12 +1730,8 @@ impl GitPanel {
continue;
}
- let Some(worktree_path) = repo.repository_entry.unrelativize(&entry.repo_path) else {
- continue;
- };
let entry = GitStatusEntry {
repo_path: entry.repo_path.clone(),
- worktree_path,
status: entry.status,
is_staged,
};
@@ -2394,7 +2379,7 @@ impl GitPanel {
&self,
sha: &str,
cx: &mut Context<Self>,
- ) -> Task<anyhow::Result<CommitDetails>> {
+ ) -> Task<Result<CommitDetails>> {
let Some(repo) = self.active_repository.clone() else {
return Task::ready(Err(anyhow::anyhow!("no active repo")));
};
@@ -2479,12 +2464,12 @@ impl GitPanel {
cx: &Context<Self>,
) -> AnyElement {
let display_name = entry
- .worktree_path
+ .repo_path
.file_name()
.map(|name| name.to_string_lossy().into_owned())
- .unwrap_or_else(|| entry.worktree_path.to_string_lossy().into_owned());
+ .unwrap_or_else(|| entry.repo_path.to_string_lossy().into_owned());
- let worktree_path = entry.worktree_path.clone();
+ let repo_path = entry.repo_path.clone();
let selected = self.selected_entry == Some(ix);
let marked = self.marked_entries.contains(&ix);
let status_style = GitPanelSettings::get_global(cx).status_style;
@@ -2655,7 +2640,7 @@ impl GitPanel {
h_flex()
.items_center()
.overflow_hidden()
- .when_some(worktree_path.parent(), |this, parent| {
+ .when_some(repo_path.parent(), |this, parent| {
let parent_str = parent.to_string_lossy();
if !parent_str.is_empty() {
this.child(
@@ -3703,119 +3688,3 @@ impl ComponentPreview for PanelRepoFooter {
.into_any_element()
}
}
-
-#[cfg(test)]
-mod tests {
- use git::status::StatusCode;
- use gpui::TestAppContext;
- use project::{FakeFs, WorktreeSettings};
- use serde_json::json;
- use settings::SettingsStore;
- use theme::LoadThemes;
- use util::path;
-
- use super::*;
-
- fn init_test(cx: &mut gpui::TestAppContext) {
- if std::env::var("RUST_LOG").is_ok() {
- env_logger::try_init().ok();
- }
-
- cx.update(|cx| {
- let settings_store = SettingsStore::test(cx);
- cx.set_global(settings_store);
- WorktreeSettings::register(cx);
- workspace::init_settings(cx);
- theme::init(LoadThemes::JustBase, cx);
- language::init(cx);
- editor::init(cx);
- Project::init_settings(cx);
- crate::init(cx);
- });
- }
-
- #[gpui::test]
- async fn test_entry_worktree_paths(cx: &mut TestAppContext) {
- init_test(cx);
- let fs = FakeFs::new(cx.background_executor.clone());
- fs.insert_tree(
- "/root",
- json!({
- "zed": {
- ".git": {},
- "crates": {
- "gpui": {
- "gpui.rs": "fn main() {}"
- },
- "util": {
- "util.rs": "fn do_it() {}"
- }
- }
- },
- }),
- )
- .await;
-
- fs.set_status_for_repo_via_git_operation(
- Path::new("/root/zed/.git"),
- &[
- (
- Path::new("crates/gpui/gpui.rs"),
- StatusCode::Modified.worktree(),
- ),
- (
- Path::new("crates/util/util.rs"),
- StatusCode::Modified.worktree(),
- ),
- ],
- );
-
- let project =
- Project::test(fs.clone(), [path!("/root/zed/crates/gpui").as_ref()], cx).await;
- let (workspace, cx) =
- cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
-
- cx.read(|cx| {
- project
- .read(cx)
- .worktrees(cx)
- .nth(0)
- .unwrap()
- .read(cx)
- .as_local()
- .unwrap()
- .scan_complete()
- })
- .await;
-
- cx.executor().run_until_parked();
-
- let app_state = workspace.update(cx, |workspace, _| workspace.app_state().clone());
- let panel = cx.new_window_entity(|window, cx| {
- GitPanel::new(workspace, project, app_state, window, cx)
- });
-
- let handle = cx.update_window_entity(&panel, |panel, window, cx| {
- panel.schedule_update(false, window, cx);
- std::mem::replace(&mut panel.update_visible_entries_task, Task::ready(()))
- });
- cx.executor().advance_clock(2 * UPDATE_DEBOUNCE);
- handle.await;
-
- let entries = panel.update(cx, |panel, _| panel.entries.clone());
- pretty_assertions::assert_eq!(
- entries,
- [
- GitListEntry::Header(GitHeaderEntry {
- header: Section::Tracked
- }),
- GitListEntry::GitStatusEntry(GitStatusEntry {
- repo_path: "crates/gpui/gpui.rs".into(),
- worktree_path: Path::new("gpui.rs").into(),
- status: StatusCode::Modified.worktree(),
- is_staged: Some(false),
- })
- ],
- )
- }
-}
@@ -22,7 +22,6 @@ use editor::ProposedChangesEditorToolbar;
use editor::{scroll::Autoscroll, Editor, MultiBuffer};
use feature_flags::{FeatureFlagAppExt, FeatureFlagViewExt, GitUiFeatureFlag};
use futures::{channel::mpsc, select_biased, StreamExt};
-use git_ui::git_panel::GitPanel;
use git_ui::project_diff::ProjectDiffToolbar;
use gpui::{
actions, point, px, Action, App, AppContext as _, AsyncApp, Context, DismissEvent, Element,
@@ -430,10 +429,7 @@ fn initialize_panels(
workspace.add_panel(chat_panel, window, cx);
workspace.add_panel(notification_panel, window, cx);
cx.when_flag_enabled::<GitUiFeatureFlag>(window, |workspace, window, cx| {
- let entity = cx.entity();
- let project = workspace.project().clone();
- let app_state = workspace.app_state().clone();
- let git_panel = cx.new(|cx| GitPanel::new(entity, project, app_state, window, cx));
+ let git_panel = git_ui::git_panel::GitPanel::new(workspace, window, cx);
workspace.add_panel(git_panel, window, cx);
});
})?;