diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs index a6c6113a33b61cd16f007b6d2d818e42ad2a191e..4a5cd56ec90fd95fe94d55edfdeb7e2114fea820 100644 --- a/crates/git_ui/src/git_panel.rs +++ b/crates/git_ui/src/git_panel.rs @@ -2868,20 +2868,19 @@ impl GitPanel { if ops.staged() { self.single_staged_entry = single_staged_entry; } + } else { + self.single_staged_entry = single_staged_entry; } - } else if repo.pending_ops_summary().item_summary.staging_count == 1 { - self.single_staged_entry = repo.pending_ops().find_map(|ops| { - if ops.staging() { - repo.status_for_path(&ops.repo_path) - .map(|status| GitStatusEntry { - repo_path: ops.repo_path.clone(), - status: status.status, - staging: StageStatus::Staged, - }) - } else { - None - } - }); + } else if repo.pending_ops_summary().item_summary.staging_count == 1 + && let Some(ops) = repo.pending_ops().find(|ops| ops.staging()) + { + self.single_staged_entry = + repo.status_for_path(&ops.repo_path) + .map(|status| GitStatusEntry { + repo_path: ops.repo_path.clone(), + status: status.status, + staging: StageStatus::Staged, + }); } } @@ -5942,4 +5941,197 @@ mod tests { "}; assert_eq!(result, expected); } + + #[gpui::test] + async fn test_suggest_commit_message(cx: &mut TestAppContext) { + init_test(cx); + + let fs = FakeFs::new(cx.background_executor.clone()); + fs.insert_tree( + path!("/project"), + json!({ + ".git": {}, + "tracked": "tracked\n", + "untracked": "\n", + }), + ) + .await; + + fs.set_head_and_index_for_repo( + path!("/project/.git").as_ref(), + &[("tracked", "old tracked\n".into())], + ); + + let project = Project::test(fs.clone(), [Path::new(path!("/project"))], cx).await; + let workspace = + cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx)); + let cx = &mut VisualTestContext::from_window(*workspace, cx); + let panel = workspace.update(cx, GitPanel::new).unwrap(); + + let handle = cx.update_window_entity(&panel, |panel, _, _| { + std::mem::replace(&mut panel.update_visible_entries_task, Task::ready(())) + }); + cx.executor().advance_clock(2 * UPDATE_DEBOUNCE); + handle.await; + + let entries = panel.read_with(cx, |panel, _| panel.entries.clone()); + + // GitPanel + // - Tracked: + // - [] tracked + // - Untracked + // - [] untracked + // + // The commit message should now read: + // "Update tracked" + let message = panel.update(cx, |panel, cx| panel.suggest_commit_message(cx)); + assert_eq!(message, Some("Update tracked".to_string())); + + let first_status_entry = entries[1].clone(); + panel.update_in(cx, |panel, window, cx| { + panel.toggle_staged_for_entry(&first_status_entry, window, cx); + }); + + cx.read(|cx| { + project + .read(cx) + .worktrees(cx) + .next() + .unwrap() + .read(cx) + .as_local() + .unwrap() + .scan_complete() + }) + .await; + + cx.executor().run_until_parked(); + + let handle = cx.update_window_entity(&panel, |panel, _, _| { + std::mem::replace(&mut panel.update_visible_entries_task, Task::ready(())) + }); + cx.executor().advance_clock(2 * UPDATE_DEBOUNCE); + handle.await; + + // GitPanel + // - Tracked: + // - [x] tracked + // - Untracked + // - [] untracked + // + // The commit message should still read: + // "Update tracked" + let message = panel.update(cx, |panel, cx| panel.suggest_commit_message(cx)); + assert_eq!(message, Some("Update tracked".to_string())); + + let second_status_entry = entries[3].clone(); + panel.update_in(cx, |panel, window, cx| { + panel.toggle_staged_for_entry(&second_status_entry, window, cx); + }); + + cx.read(|cx| { + project + .read(cx) + .worktrees(cx) + .next() + .unwrap() + .read(cx) + .as_local() + .unwrap() + .scan_complete() + }) + .await; + + cx.executor().run_until_parked(); + + let handle = cx.update_window_entity(&panel, |panel, _, _| { + std::mem::replace(&mut panel.update_visible_entries_task, Task::ready(())) + }); + cx.executor().advance_clock(2 * UPDATE_DEBOUNCE); + handle.await; + + // GitPanel + // - Tracked: + // - [x] tracked + // - Untracked + // - [x] untracked + // + // The commit message should now read: + // "Enter commit message" + // (which means we should see None returned). + let message = panel.update(cx, |panel, cx| panel.suggest_commit_message(cx)); + assert!(message.is_none()); + + panel.update_in(cx, |panel, window, cx| { + panel.toggle_staged_for_entry(&first_status_entry, window, cx); + }); + + cx.read(|cx| { + project + .read(cx) + .worktrees(cx) + .next() + .unwrap() + .read(cx) + .as_local() + .unwrap() + .scan_complete() + }) + .await; + + cx.executor().run_until_parked(); + + let handle = cx.update_window_entity(&panel, |panel, _, _| { + std::mem::replace(&mut panel.update_visible_entries_task, Task::ready(())) + }); + cx.executor().advance_clock(2 * UPDATE_DEBOUNCE); + handle.await; + + // GitPanel + // - Tracked: + // - [] tracked + // - Untracked + // - [x] untracked + // + // The commit message should now read: + // "Update untracked" + let message = panel.update(cx, |panel, cx| panel.suggest_commit_message(cx)); + assert_eq!(message, Some("Create untracked".to_string())); + + panel.update_in(cx, |panel, window, cx| { + panel.toggle_staged_for_entry(&second_status_entry, window, cx); + }); + + cx.read(|cx| { + project + .read(cx) + .worktrees(cx) + .next() + .unwrap() + .read(cx) + .as_local() + .unwrap() + .scan_complete() + }) + .await; + + cx.executor().run_until_parked(); + + let handle = cx.update_window_entity(&panel, |panel, _, _| { + std::mem::replace(&mut panel.update_visible_entries_task, Task::ready(())) + }); + cx.executor().advance_clock(2 * UPDATE_DEBOUNCE); + handle.await; + + // GitPanel + // - Tracked: + // - [] tracked + // - Untracked + // - [] untracked + // + // The commit message should now read: + // "Update tracked" + let message = panel.update(cx, |panel, cx| panel.suggest_commit_message(cx)); + assert_eq!(message, Some("Update tracked".to_string())); + } }