Implement staging and unstaging hunks (#24606)

- [x] Staging hunks
- [x] Unstaging hunks
- [x] Write a randomized test
- [x] Get test passing
- [x] Fix existing bug in diff_base_byte_range computation
- [x] Remote project support
- [ ] ~~Improve performance of
buffer_range_to_unchanged_diff_base_range~~
- [ ] ~~Bug: project diff editor scrolls to top when staging/unstaging
hunk~~ existing issue
- [ ] ~~UI~~ deferred
- [x] Tricky cases
  - [x] Correctly handle acting on multiple hunks for a single file
- [x] Remove path from index when unstaging the last staged hunk, if
it's absent from HEAD, or staging the only hunk, if it's deleted in the
working copy

Release Notes:

- Add `ToggleStagedSelectedDiffHunks` action for staging and unstaging
individual diff hunks
This commit is contained in:
Cole Miller
2025-02-12 19:46:42 +00:00
committed by GitHub
parent ea8da43c6b
commit eea6b526dc
18 changed files with 768 additions and 70 deletions
+53
View File
@@ -14047,6 +14047,59 @@ async fn test_edit_after_expanded_modification_hunk(
);
}
#[gpui::test]
async fn test_stage_and_unstage_added_file_hunk(
executor: BackgroundExecutor,
cx: &mut gpui::TestAppContext,
) {
init_test(cx, |_| {});
let mut cx = EditorTestContext::new(cx).await;
cx.update_editor(|editor, _, cx| {
editor.set_expand_all_diff_hunks(cx);
});
let working_copy = r#"
ˇfn main() {
println!("hello, world!");
}
"#
.unindent();
cx.set_state(&working_copy);
executor.run_until_parked();
cx.assert_state_with_diff(
r#"
+ ˇfn main() {
+ println!("hello, world!");
+ }
"#
.unindent(),
);
cx.assert_index_text(None);
cx.update_editor(|editor, window, cx| {
editor.toggle_staged_selected_diff_hunks(&ToggleStagedSelectedDiffHunks, window, cx);
});
executor.run_until_parked();
cx.assert_index_text(Some(&working_copy.replace("ˇ", "")));
cx.assert_state_with_diff(
r#"
+ ˇfn main() {
+ println!("hello, world!");
+ }
"#
.unindent(),
);
cx.update_editor(|editor, window, cx| {
editor.toggle_staged_selected_diff_hunks(&ToggleStagedSelectedDiffHunks, window, cx);
});
executor.run_until_parked();
cx.assert_index_text(None);
}
async fn setup_indent_guides_editor(
text: &str,
cx: &mut gpui::TestAppContext,