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 <nate@zed.dev>
This commit is contained in:
parent
1b1c2e55f3
commit
1a8303b020
5 changed files with 190 additions and 162 deletions
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,10 +88,6 @@ pub struct GitPanel {
|
|||
show_scrollbar: bool,
|
||||
rebuild_requested: Arc<AtomicBool>,
|
||||
commit_editor: View<Editor>,
|
||||
/// 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<GitListEntry>,
|
||||
all_staged: Option<bool>,
|
||||
width: Option<Pixels>,
|
||||
|
@ -363,8 +359,8 @@ impl GitPanel {
|
|||
git_panel
|
||||
}
|
||||
|
||||
fn git_state<'a>(&self, cx: &'a AppContext) -> Option<&'a Model<GitState>> {
|
||||
self.project.read(cx).git_state()
|
||||
fn git_state(&self, cx: &AppContext) -> Option<Model<GitState>> {
|
||||
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<Self>) {
|
||||
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<Self>) {
|
||||
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<Self>) {
|
||||
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<Self>) {
|
||||
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<Self>) {
|
||||
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<Self>) {
|
||||
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<Self>) {
|
||||
// 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<Self>) {
|
||||
|
@ -680,7 +669,7 @@ impl GitPanel {
|
|||
}
|
||||
|
||||
fn clear_message(&mut self, cx: &mut ViewContext<Self>) {
|
||||
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>) {
|
||||
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>) {
|
||||
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<Self>) -> 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<Self>) -> 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<Self>) -> 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()
|
||||
|
|
|
@ -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<RepoPath>, 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<RepoPath>) {
|
||||
self.act_on_entries(entries, StatusAction::Stage);
|
||||
}
|
||||
|
||||
pub fn stage_entries(&mut self, entries: Vec<RepoPath>) {
|
||||
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<RepoPath>) {
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<StatusEntry> {
|
||||
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<GitEntryRef<'a>> {
|
||||
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 })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue