From 1a8303b02003ce9ebb6b5ad2a2288b6d1cd19634 Mon Sep 17 00:00:00 2001 From: Cole Miller Date: Thu, 16 Jan 2025 16:32:11 -0500 Subject: [PATCH] git: Migrate some panel code away from visible_entries (#23251) To prepare for the introduction of folding in the git panel, these codepaths need to work with the canonical source of all git status entries, not just the ones that are visible in the panel. Release Notes: - N/A --------- Co-authored-by: Nate --- crates/git/src/status.rs | 49 ++++++----- crates/git_ui/src/git_panel.rs | 116 +++++++++++++++----------- crates/project/src/git.rs | 72 ++++++++-------- crates/worktree/src/worktree.rs | 8 +- crates/worktree/src/worktree_tests.rs | 107 ++++++++++++------------ 5 files changed, 190 insertions(+), 162 deletions(-) diff --git a/crates/git/src/status.rs b/crates/git/src/status.rs index edf4d58373..1c8b6e757a 100644 --- a/crates/git/src/status.rs +++ b/crates/git/src/status.rs @@ -171,7 +171,13 @@ impl FileStatus { FileStatus::Tracked(TrackedStatus { index_status, worktree_status, - }) => index_status.summary() + worktree_status.summary(), + }) => { + let mut summary = index_status.to_summary() + worktree_status.to_summary(); + if summary != GitSummary::UNCHANGED { + summary.count = 1; + }; + summary + } } } } @@ -190,11 +196,23 @@ impl StatusCode { } } - fn summary(self) -> GitSummary { + /// Returns the contribution of this status code to the Git summary. + /// + /// Note that this does not include the count field, which must be set manually. + fn to_summary(self) -> GitSummary { match self { - StatusCode::Modified | StatusCode::TypeChanged => GitSummary::MODIFIED, - StatusCode::Added => GitSummary::ADDED, - StatusCode::Deleted => GitSummary::DELETED, + StatusCode::Modified | StatusCode::TypeChanged => GitSummary { + modified: 1, + ..GitSummary::UNCHANGED + }, + StatusCode::Added => GitSummary { + added: 1, + ..GitSummary::UNCHANGED + }, + StatusCode::Deleted => GitSummary { + deleted: 1, + ..GitSummary::UNCHANGED + }, StatusCode::Renamed | StatusCode::Copied | StatusCode::Unmodified => { GitSummary::UNCHANGED } @@ -220,31 +238,19 @@ pub struct GitSummary { pub conflict: usize, pub untracked: usize, pub deleted: usize, + pub count: usize, } impl GitSummary { - pub const ADDED: Self = Self { - added: 1, - ..Self::UNCHANGED - }; - - pub const MODIFIED: Self = Self { - modified: 1, - ..Self::UNCHANGED - }; - pub const CONFLICT: Self = Self { conflict: 1, - ..Self::UNCHANGED - }; - - pub const DELETED: Self = Self { - deleted: 1, + count: 1, ..Self::UNCHANGED }; pub const UNTRACKED: Self = Self { untracked: 1, + count: 1, ..Self::UNCHANGED }; @@ -254,6 +260,7 @@ impl GitSummary { conflict: 0, untracked: 0, deleted: 0, + count: 0, }; } @@ -291,6 +298,7 @@ impl std::ops::AddAssign for GitSummary { self.conflict += rhs.conflict; self.untracked += rhs.untracked; self.deleted += rhs.deleted; + self.count += rhs.count; } } @@ -304,6 +312,7 @@ impl std::ops::Sub for GitSummary { conflict: self.conflict - rhs.conflict, untracked: self.untracked - rhs.untracked, deleted: self.deleted - rhs.deleted, + count: self.count - rhs.count, } } } diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs index 771113cf40..08f6ba6058 100644 --- a/crates/git_ui/src/git_panel.rs +++ b/crates/git_ui/src/git_panel.rs @@ -88,10 +88,6 @@ pub struct GitPanel { show_scrollbar: bool, rebuild_requested: Arc, commit_editor: View, - /// The visible entries in the list, accounting for folding & expanded state. - /// - /// At this point it doesn't matter what repository the entry belongs to, - /// as only one repositories' entries are visible in the list at a time. visible_entries: Vec, all_staged: Option, width: Option, @@ -363,8 +359,8 @@ impl GitPanel { git_panel } - fn git_state<'a>(&self, cx: &'a AppContext) -> Option<&'a Model> { - self.project.read(cx).git_state() + fn git_state(&self, cx: &AppContext) -> Option> { + self.project.read(cx).git_state().cloned() } fn active_repository<'a>( @@ -578,7 +574,7 @@ impl GitPanel { } fn select_first_entry_if_none(&mut self, cx: &mut ViewContext) { - if !self.no_entries() && self.selected_entry.is_none() { + if !self.no_entries(cx) && self.selected_entry.is_none() { self.selected_entry = Some(0); self.scroll_to_selected_entry(cx); cx.notify(); @@ -597,15 +593,24 @@ impl GitPanel { .and_then(|i| self.visible_entries.get(i)) } + fn open_selected(&mut self, _: &menu::Confirm, cx: &mut ViewContext) { + if let Some(entry) = self + .selected_entry + .and_then(|i| self.visible_entries.get(i)) + { + self.open_entry(entry, cx); + } + } + fn toggle_staged_for_entry(&mut self, entry: &GitListEntry, cx: &mut ViewContext) { - let Some(git_state) = self.git_state(cx).cloned() else { + let Some(git_state) = self.git_state(cx) else { return; }; git_state.update(cx, |git_state, _| { if entry.status.is_staged().unwrap_or(false) { - git_state.unstage_entry(entry.repo_path.clone()); + git_state.stage_entries(vec![entry.repo_path.clone()]); } else { - git_state.stage_entry(entry.repo_path.clone()); + git_state.stage_entries(vec![entry.repo_path.clone()]); } }); cx.notify(); @@ -617,15 +622,6 @@ impl GitPanel { } } - fn open_selected(&mut self, _: &menu::Confirm, cx: &mut ViewContext) { - if let Some(entry) = self - .selected_entry - .and_then(|i| self.visible_entries.get(i)) - { - self.open_entry(entry, cx); - } - } - fn open_entry(&self, entry: &GitListEntry, cx: &mut ViewContext) { let Some((worktree_id, path)) = maybe!({ let git_state = self.git_state(cx)?; @@ -646,32 +642,25 @@ impl GitPanel { } fn stage_all(&mut self, _: &git::StageAll, cx: &mut ViewContext) { - let to_stage = self - .visible_entries - .iter_mut() - .filter_map(|entry| { - let is_unstaged = !entry.is_staged.unwrap_or(false); - entry.is_staged = Some(true); - is_unstaged.then(|| entry.repo_path.clone()) - }) - .collect(); - self.all_staged = Some(true); - let Some(git_state) = self.git_state(cx).cloned() else { + let Some(git_state) = self.git_state(cx) else { return; }; - git_state.update(cx, |git_state, _| git_state.stage_entries(to_stage)); + for entry in &mut self.visible_entries { + entry.is_staged = Some(true); + } + self.all_staged = Some(true); + git_state.read(cx).stage_all(); } fn unstage_all(&mut self, _: &git::UnstageAll, cx: &mut ViewContext) { - // This should only be called when all entries are staged. + let Some(git_state) = self.git_state(cx) else { + return; + }; for entry in &mut self.visible_entries { entry.is_staged = Some(false); } self.all_staged = Some(false); - let Some(git_state) = self.git_state(cx).cloned() else { - return; - }; - git_state.update(cx, |git_state, _| git_state.unstage_all()); + git_state.read(cx).unstage_all(); } fn discard_all(&mut self, _: &git::RevertAll, _cx: &mut ViewContext) { @@ -680,7 +669,7 @@ impl GitPanel { } fn clear_message(&mut self, cx: &mut ViewContext) { - let Some(git_state) = self.git_state(cx).cloned() else { + let Some(git_state) = self.git_state(cx) else { return; }; git_state.update(cx, |git_state, _| { @@ -690,10 +679,28 @@ impl GitPanel { .update(cx, |editor, cx| editor.set_text("", cx)); } + fn can_commit(&self, commit_all: bool, cx: &AppContext) -> bool { + let Some(git_state) = self.git_state(cx) else { + return false; + }; + let has_message = !self.commit_editor.read(cx).text(cx).is_empty(); + let has_changes = git_state.read(cx).entry_count() > 0; + let has_staged_changes = self + .visible_entries + .iter() + .any(|entry| entry.is_staged == Some(true)); + + has_message && (commit_all || has_staged_changes) && has_changes + } + /// Commit all staged changes fn commit_changes(&mut self, _: &git::CommitChanges, cx: &mut ViewContext) { self.clear_message(cx); + if !self.can_commit(false, cx) { + return; + } + // TODO: Implement commit all staged println!("Commit staged changes triggered"); } @@ -702,16 +709,17 @@ impl GitPanel { fn commit_all_changes(&mut self, _: &git::CommitAllChanges, cx: &mut ViewContext) { self.clear_message(cx); + if !self.can_commit(true, cx) { + return; + } + // TODO: Implement commit all changes println!("Commit all changes triggered"); } - fn no_entries(&self) -> bool { - self.visible_entries.is_empty() - } - - fn entry_count(&self) -> usize { - self.visible_entries.len() + fn no_entries(&self, cx: &mut ViewContext) -> bool { + self.git_state(cx) + .map_or(true, |git_state| git_state.read(cx).entry_count() == 0) } fn for_each_visible_entry( @@ -828,7 +836,7 @@ impl GitPanel { if let language::BufferEvent::Reparsed | language::BufferEvent::Edited = event { let commit_message = self.commit_editor.update(cx, |editor, cx| editor.text(cx)); - let Some(git_state) = self.git_state(cx).cloned() else { + let Some(git_state) = self.git_state(cx) else { return; }; git_state.update(cx, |git_state, _| { @@ -866,8 +874,11 @@ impl GitPanel { pub fn render_panel_header(&self, cx: &mut ViewContext) -> impl IntoElement { let focus_handle = self.focus_handle(cx).clone(); + let entry_count = self + .git_state(cx) + .map_or(0, |git_state| git_state.read(cx).entry_count()); - let changes_string = match self.entry_count() { + let changes_string = match entry_count { 0 => "No changes".to_string(), 1 => "1 change".to_string(), n => format!("{} changes", n), @@ -887,7 +898,7 @@ impl GitPanel { .child( Checkbox::new( "all-changes", - if self.no_entries() { + if self.no_entries(cx) { ToggleState::Selected } else { self.all_staged @@ -1108,7 +1119,8 @@ impl GitPanel { } fn render_entries(&self, cx: &mut ViewContext) -> impl IntoElement { - let entry_count = self.entry_count(); + let entry_count = self.visible_entries.len(); + h_flex() .size_full() .overflow_hidden() @@ -1228,14 +1240,16 @@ impl GitPanel { ToggleState::Indeterminate => None, }; let repo_path = repo_path.clone(); - let Some(git_state) = this.git_state(cx).cloned() else { + let Some(git_state) = this.git_state(cx) else { return; }; git_state.update(cx, |git_state, _| match toggle { ToggleState::Selected | ToggleState::Indeterminate => { - git_state.stage_entry(repo_path); + git_state.stage_entries(vec![repo_path]); + } + ToggleState::Unselected => { + git_state.unstage_entries(vec![repo_path]) } - ToggleState::Unselected => git_state.unstage_entry(repo_path), }) }); } @@ -1330,7 +1344,7 @@ impl Render for GitPanel { .bg(ElevationIndex::Surface.bg(cx)) .child(self.render_panel_header(cx)) .child(self.render_divider(cx)) - .child(if !self.no_entries() { + .child(if !self.no_entries(cx) { self.render_entries(cx).into_any_element() } else { self.render_empty_state(cx).into_any_element() diff --git a/crates/project/src/git.rs b/crates/project/src/git.rs index 7c369c9337..cbb7ed90dc 100644 --- a/crates/project/src/git.rs +++ b/crates/project/src/git.rs @@ -73,52 +73,54 @@ impl GitState { self.commit_message = None; } - pub fn stage_entry(&mut self, repo_path: RepoPath) { + fn act_on_entries(&self, entries: Vec, action: StatusAction) { + if entries.is_empty() { + return; + } if let Some((_, _, git_repo)) = self.active_repository.as_ref() { - let _ = self.update_sender.unbounded_send(( - git_repo.clone(), - vec![repo_path], - StatusAction::Stage, - )); + let _ = self + .update_sender + .unbounded_send((git_repo.clone(), entries, action)); } } - pub fn unstage_entry(&mut self, repo_path: RepoPath) { - if let Some((_, _, git_repo)) = self.active_repository.as_ref() { - let _ = self.update_sender.unbounded_send(( - git_repo.clone(), - vec![repo_path], - StatusAction::Unstage, - )); - } + pub fn stage_entries(&self, entries: Vec) { + self.act_on_entries(entries, StatusAction::Stage); } - pub fn stage_entries(&mut self, entries: Vec) { - if let Some((_, _, git_repo)) = self.active_repository.as_ref() { - let _ = - self.update_sender - .unbounded_send((git_repo.clone(), entries, StatusAction::Stage)); - } + pub fn unstage_entries(&self, entries: Vec) { + self.act_on_entries(entries, StatusAction::Unstage); } - fn act_on_all(&mut self, action: StatusAction) { - if let Some((_, active_repository, git_repo)) = self.active_repository.as_ref() { - let _ = self.update_sender.unbounded_send(( - git_repo.clone(), - active_repository - .status() - .map(|entry| entry.repo_path) - .collect(), - action, - )); - } + pub fn stage_all(&self) { + let Some((_, entry, _)) = self.active_repository.as_ref() else { + return; + }; + let to_stage = entry + .status() + .filter(|entry| !entry.status.is_staged().unwrap_or(false)) + .map(|entry| entry.repo_path.clone()) + .collect(); + self.stage_entries(to_stage); } - pub fn stage_all(&mut self) { - self.act_on_all(StatusAction::Stage); + pub fn unstage_all(&self) { + let Some((_, entry, _)) = self.active_repository.as_ref() else { + return; + }; + let to_unstage = entry + .status() + .filter(|entry| entry.status.is_staged().unwrap_or(true)) + .map(|entry| entry.repo_path.clone()) + .collect(); + self.unstage_entries(to_unstage); } - pub fn unstage_all(&mut self) { - self.act_on_all(StatusAction::Unstage); + /// Get a count of all entries in the active repository, including + /// untracked files. + pub fn entry_count(&self) -> usize { + self.active_repository + .as_ref() + .map_or(0, |(_, entry, _)| entry.status_len()) } } diff --git a/crates/worktree/src/worktree.rs b/crates/worktree/src/worktree.rs index 4c65b41da4..2acbc15adb 100644 --- a/crates/worktree/src/worktree.rs +++ b/crates/worktree/src/worktree.rs @@ -227,6 +227,10 @@ impl RepositoryEntry { self.statuses_by_path.iter().cloned() } + pub fn status_len(&self) -> usize { + self.statuses_by_path.summary().item_summary.count + } + pub fn status_for_path(&self, path: &RepoPath) -> Option { self.statuses_by_path .get(&PathKey(path.0.clone()), &()) @@ -5718,7 +5722,7 @@ impl<'a> GitTraversal<'a> { if statuses.seek_forward(&PathTarget::Path(repo_path.as_ref()), Bias::Left, &()) { self.current_entry_summary = Some(statuses.item().unwrap().status.into()); } else { - self.current_entry_summary = Some(GitSummary::zero(&())); + self.current_entry_summary = Some(GitSummary::UNCHANGED); } } } @@ -5755,7 +5759,7 @@ impl<'a> GitTraversal<'a> { pub fn entry(&self) -> Option> { let entry = self.traversal.cursor.item()?; - let git_summary = self.current_entry_summary.unwrap_or_default(); + let git_summary = self.current_entry_summary.unwrap_or(GitSummary::UNCHANGED); Some(GitEntryRef { entry, git_summary }) } } diff --git a/crates/worktree/src/worktree_tests.rs b/crates/worktree/src/worktree_tests.rs index 87159548af..34c37626db 100644 --- a/crates/worktree/src/worktree_tests.rs +++ b/crates/worktree/src/worktree_tests.rs @@ -1512,9 +1512,9 @@ async fn test_bump_mtime_of_git_repo_workdir(cx: &mut TestAppContext) { check_git_statuses( &snapshot, &[ - (Path::new(""), GitSummary::MODIFIED), + (Path::new(""), MODIFIED), (Path::new("a.txt"), GitSummary::UNCHANGED), - (Path::new("b/c.txt"), GitSummary::MODIFIED), + (Path::new("b/c.txt"), MODIFIED), ], ); } @@ -2811,7 +2811,7 @@ async fn test_traverse_with_git_status(cx: &mut TestAppContext) { assert_eq!(entry.git_summary, GitSummary::UNCHANGED); let entry = traversal.next().unwrap(); assert_eq!(entry.path.as_ref(), Path::new("x/x2.txt")); - assert_eq!(entry.git_summary, GitSummary::MODIFIED); + assert_eq!(entry.git_summary, MODIFIED); let entry = traversal.next().unwrap(); assert_eq!(entry.path.as_ref(), Path::new("x/y/y1.txt")); assert_eq!(entry.git_summary, GitSummary::CONFLICT); @@ -2820,13 +2820,13 @@ async fn test_traverse_with_git_status(cx: &mut TestAppContext) { assert_eq!(entry.git_summary, GitSummary::UNCHANGED); let entry = traversal.next().unwrap(); assert_eq!(entry.path.as_ref(), Path::new("x/z.txt")); - assert_eq!(entry.git_summary, GitSummary::ADDED); + assert_eq!(entry.git_summary, ADDED); let entry = traversal.next().unwrap(); assert_eq!(entry.path.as_ref(), Path::new("z/z1.txt")); assert_eq!(entry.git_summary, GitSummary::UNCHANGED); let entry = traversal.next().unwrap(); assert_eq!(entry.path.as_ref(), Path::new("z/z2.txt")); - assert_eq!(entry.git_summary, GitSummary::ADDED); + assert_eq!(entry.git_summary, ADDED); } #[gpui::test] @@ -2893,10 +2893,7 @@ async fn test_propagate_git_statuses(cx: &mut TestAppContext) { check_git_statuses( &snapshot, &[ - ( - Path::new(""), - GitSummary::CONFLICT + GitSummary::MODIFIED + GitSummary::ADDED, - ), + (Path::new(""), GitSummary::CONFLICT + MODIFIED + ADDED), (Path::new("g"), GitSummary::CONFLICT), (Path::new("g/h2.txt"), GitSummary::CONFLICT), ], @@ -2905,16 +2902,13 @@ async fn test_propagate_git_statuses(cx: &mut TestAppContext) { check_git_statuses( &snapshot, &[ - ( - Path::new(""), - GitSummary::CONFLICT + GitSummary::ADDED + GitSummary::MODIFIED, - ), - (Path::new("a"), GitSummary::ADDED + GitSummary::MODIFIED), - (Path::new("a/b"), GitSummary::ADDED), - (Path::new("a/b/c1.txt"), GitSummary::ADDED), + (Path::new(""), GitSummary::CONFLICT + ADDED + MODIFIED), + (Path::new("a"), ADDED + MODIFIED), + (Path::new("a/b"), ADDED), + (Path::new("a/b/c1.txt"), ADDED), (Path::new("a/b/c2.txt"), GitSummary::UNCHANGED), - (Path::new("a/d"), GitSummary::MODIFIED), - (Path::new("a/d/e2.txt"), GitSummary::MODIFIED), + (Path::new("a/d"), MODIFIED), + (Path::new("a/d/e2.txt"), MODIFIED), (Path::new("f"), GitSummary::UNCHANGED), (Path::new("f/no-status.txt"), GitSummary::UNCHANGED), (Path::new("g"), GitSummary::CONFLICT), @@ -2925,12 +2919,12 @@ async fn test_propagate_git_statuses(cx: &mut TestAppContext) { check_git_statuses( &snapshot, &[ - (Path::new("a/b"), GitSummary::ADDED), - (Path::new("a/b/c1.txt"), GitSummary::ADDED), + (Path::new("a/b"), ADDED), + (Path::new("a/b/c1.txt"), ADDED), (Path::new("a/b/c2.txt"), GitSummary::UNCHANGED), - (Path::new("a/d"), GitSummary::MODIFIED), + (Path::new("a/d"), MODIFIED), (Path::new("a/d/e1.txt"), GitSummary::UNCHANGED), - (Path::new("a/d/e2.txt"), GitSummary::MODIFIED), + (Path::new("a/d/e2.txt"), MODIFIED), (Path::new("f"), GitSummary::UNCHANGED), (Path::new("f/no-status.txt"), GitSummary::UNCHANGED), (Path::new("g"), GitSummary::CONFLICT), @@ -2940,10 +2934,10 @@ async fn test_propagate_git_statuses(cx: &mut TestAppContext) { check_git_statuses( &snapshot, &[ - (Path::new("a/b/c1.txt"), GitSummary::ADDED), + (Path::new("a/b/c1.txt"), ADDED), (Path::new("a/b/c2.txt"), GitSummary::UNCHANGED), (Path::new("a/d/e1.txt"), GitSummary::UNCHANGED), - (Path::new("a/d/e2.txt"), GitSummary::MODIFIED), + (Path::new("a/d/e2.txt"), MODIFIED), (Path::new("f/no-status.txt"), GitSummary::UNCHANGED), ], ); @@ -3016,49 +3010,43 @@ async fn test_propagate_statuses_for_repos_under_project(cx: &mut TestAppContext check_git_statuses( &snapshot, - &[ - (Path::new("x"), GitSummary::ADDED), - (Path::new("x/x1.txt"), GitSummary::ADDED), - ], + &[(Path::new("x"), ADDED), (Path::new("x/x1.txt"), ADDED)], ); check_git_statuses( &snapshot, &[ - (Path::new("y"), GitSummary::CONFLICT + GitSummary::MODIFIED), + (Path::new("y"), GitSummary::CONFLICT + MODIFIED), (Path::new("y/y1.txt"), GitSummary::CONFLICT), - (Path::new("y/y2.txt"), GitSummary::MODIFIED), + (Path::new("y/y2.txt"), MODIFIED), ], ); check_git_statuses( &snapshot, &[ - (Path::new("z"), GitSummary::MODIFIED), - (Path::new("z/z2.txt"), GitSummary::MODIFIED), + (Path::new("z"), MODIFIED), + (Path::new("z/z2.txt"), MODIFIED), ], ); check_git_statuses( &snapshot, - &[ - (Path::new("x"), GitSummary::ADDED), - (Path::new("x/x1.txt"), GitSummary::ADDED), - ], + &[(Path::new("x"), ADDED), (Path::new("x/x1.txt"), ADDED)], ); check_git_statuses( &snapshot, &[ - (Path::new("x"), GitSummary::ADDED), - (Path::new("x/x1.txt"), GitSummary::ADDED), + (Path::new("x"), ADDED), + (Path::new("x/x1.txt"), ADDED), (Path::new("x/x2.txt"), GitSummary::UNCHANGED), - (Path::new("y"), GitSummary::CONFLICT + GitSummary::MODIFIED), + (Path::new("y"), GitSummary::CONFLICT + MODIFIED), (Path::new("y/y1.txt"), GitSummary::CONFLICT), - (Path::new("y/y2.txt"), GitSummary::MODIFIED), - (Path::new("z"), GitSummary::MODIFIED), + (Path::new("y/y2.txt"), MODIFIED), + (Path::new("z"), MODIFIED), (Path::new("z/z1.txt"), GitSummary::UNCHANGED), - (Path::new("z/z2.txt"), GitSummary::MODIFIED), + (Path::new("z/z2.txt"), MODIFIED), ], ); } @@ -3139,9 +3127,9 @@ async fn test_propagate_statuses_for_nested_repos(cx: &mut TestAppContext) { check_git_statuses( &snapshot, &[ - (Path::new("z"), GitSummary::ADDED), + (Path::new("z"), ADDED), (Path::new("z/z1.txt"), GitSummary::UNCHANGED), - (Path::new("z/z2.txt"), GitSummary::ADDED), + (Path::new("z/z2.txt"), ADDED), ], ); @@ -3149,7 +3137,7 @@ async fn test_propagate_statuses_for_nested_repos(cx: &mut TestAppContext) { check_git_statuses( &snapshot, &[ - (Path::new("x"), GitSummary::MODIFIED + GitSummary::ADDED), + (Path::new("x"), MODIFIED + ADDED), (Path::new("x/y"), GitSummary::CONFLICT), (Path::new("x/y/y1.txt"), GitSummary::CONFLICT), ], @@ -3159,13 +3147,13 @@ async fn test_propagate_statuses_for_nested_repos(cx: &mut TestAppContext) { check_git_statuses( &snapshot, &[ - (Path::new("x"), GitSummary::MODIFIED + GitSummary::ADDED), + (Path::new("x"), MODIFIED + ADDED), (Path::new("x/x1.txt"), GitSummary::UNCHANGED), - (Path::new("x/x2.txt"), GitSummary::MODIFIED), + (Path::new("x/x2.txt"), MODIFIED), (Path::new("x/y"), GitSummary::CONFLICT), (Path::new("x/y/y1.txt"), GitSummary::CONFLICT), (Path::new("x/y/y2.txt"), GitSummary::UNCHANGED), - (Path::new("x/z.txt"), GitSummary::ADDED), + (Path::new("x/z.txt"), ADDED), ], ); @@ -3174,7 +3162,7 @@ async fn test_propagate_statuses_for_nested_repos(cx: &mut TestAppContext) { &snapshot, &[ (Path::new(""), GitSummary::UNCHANGED), - (Path::new("x"), GitSummary::MODIFIED + GitSummary::ADDED), + (Path::new("x"), MODIFIED + ADDED), (Path::new("x/x1.txt"), GitSummary::UNCHANGED), ], ); @@ -3184,16 +3172,16 @@ async fn test_propagate_statuses_for_nested_repos(cx: &mut TestAppContext) { &snapshot, &[ (Path::new(""), GitSummary::UNCHANGED), - (Path::new("x"), GitSummary::MODIFIED + GitSummary::ADDED), + (Path::new("x"), MODIFIED + ADDED), (Path::new("x/x1.txt"), GitSummary::UNCHANGED), - (Path::new("x/x2.txt"), GitSummary::MODIFIED), + (Path::new("x/x2.txt"), MODIFIED), (Path::new("x/y"), GitSummary::CONFLICT), (Path::new("x/y/y1.txt"), GitSummary::CONFLICT), (Path::new("x/y/y2.txt"), GitSummary::UNCHANGED), - (Path::new("x/z.txt"), GitSummary::ADDED), - (Path::new("z"), GitSummary::ADDED), + (Path::new("x/z.txt"), ADDED), + (Path::new("z"), ADDED), (Path::new("z/z1.txt"), GitSummary::UNCHANGED), - (Path::new("z/z2.txt"), GitSummary::ADDED), + (Path::new("z/z2.txt"), ADDED), ], ); } @@ -3238,6 +3226,17 @@ fn check_git_statuses(snapshot: &Snapshot, expected_statuses: &[(&Path, GitSumma assert_eq!(found_statuses, expected_statuses); } +const ADDED: GitSummary = GitSummary { + added: 1, + count: 1, + ..GitSummary::UNCHANGED +}; +const MODIFIED: GitSummary = GitSummary { + modified: 1, + count: 1, + ..GitSummary::UNCHANGED +}; + #[track_caller] fn git_init(path: &Path) -> git2::Repository { git2::Repository::init(path).expect("Failed to initialize git repository")