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 14:46:42 -05:00 committed by GitHub
parent ea8da43c6b
commit eea6b526dc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 768 additions and 70 deletions

View file

@ -133,6 +133,7 @@ pub struct MultiBufferDiffHunk {
pub diff_base_byte_range: Range<usize>,
/// Whether or not this hunk also appears in the 'secondary diff'.
pub secondary_status: DiffHunkSecondaryStatus,
pub secondary_diff_base_byte_range: Option<Range<usize>>,
}
impl MultiBufferDiffHunk {
@ -2191,7 +2192,11 @@ impl MultiBuffer {
let secondary_diff_insertion = new_diff
.secondary_diff()
.map_or(true, |secondary_diff| secondary_diff.base_text().is_none());
new_diff = BufferDiff::build_with_single_insertion(secondary_diff_insertion, cx);
new_diff = BufferDiff::build_with_single_insertion(
secondary_diff_insertion,
buffer.snapshot(),
cx,
);
}
let mut snapshot = self.snapshot.borrow_mut();
@ -3477,6 +3482,7 @@ impl MultiBufferSnapshot {
buffer_range: hunk.buffer_range.clone(),
diff_base_byte_range: hunk.diff_base_byte_range.clone(),
secondary_status: hunk.secondary_status,
secondary_diff_base_byte_range: hunk.secondary_diff_base_byte_range,
})
})
}
@ -3846,6 +3852,7 @@ impl MultiBufferSnapshot {
buffer_range: hunk.buffer_range.clone(),
diff_base_byte_range: hunk.diff_base_byte_range.clone(),
secondary_status: hunk.secondary_status,
secondary_diff_base_byte_range: hunk.secondary_diff_base_byte_range,
});
}
}
@ -5937,6 +5944,10 @@ impl MultiBufferSnapshot {
pub fn show_headers(&self) -> bool {
self.show_headers
}
pub fn diff_for_buffer_id(&self, buffer_id: BufferId) -> Option<&BufferDiffSnapshot> {
self.diffs.get(&buffer_id)
}
}
#[cfg(any(test, feature = "test-support"))]