History

Compute branch diff statuses from worktree contents

Replace the status-combination table with a real merge-base-to-worktree tree diff, make GitStore share one DiffBufferList per repository with the branch diff view, keep repo_snapshots as index/worktree truth with separate display status APIs, and make non-HEAD gutter hunks read-only. The git.diff_base setting values are now "head" and "default_branch", applied live and toggleable from the editor controls menu. git::Diff follows the setting; git::DiffHead always opens the HEAD diff; and git::BranchDiff is renamed to git::DiffBranch with a deprecated alias.

Ben Kunkle committed 3 months ago

Commit ecb8e7e1 parent b10f68333 files · +1552 −1324Browse files

Showing the changes to crates/buffer_diff/src/buffer_diff.rs (1 of 33 files). Show all

Unified · Split

crates/buffer_diff/src/buffer_diff.rs+40−4
@@ -25,6 +25,23 @@ pub struct BufferDiff { · 24 unmodified lines
2525 diff_snapshot: Option<BufferDiffSnapshot>,
2626 secondary_diff: Option<Entity<BufferDiff>>,
2727 buffer_snapshot: text::BufferSnapshot,
28+ base_kind: DiffBaseKind,
29+}
30+
31+/// Where this diff's base text came from. Only diffs whose base is HEAD
32+/// support staging and restoring hunks; a diff against any other base (e.g.
33+/// the merge base with another branch) would rewrite committed work.
34+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
35+pub enum DiffBaseKind {
36+ /// The buffer's committed (HEAD) content.
37+ Head,
38+ /// The buffer's index (staged) content.
39+ Index,
40+ /// An arbitrary blob, such as the merge base with another branch.
41+ Oid,
42+ /// Arbitrary caller-provided text, such as an agent's original text,
43+ /// the clipboard, or another file.
44+ Custom,
2845 }
2946
3047 #[derive(Clone)]
@@ -1553,6 +1570,7 @@ impl BufferDiff { · 1522 unmodified lines
15531570 buffer: &text::BufferSnapshot,
15541571 language: Option<Arc<Language>>,
15551572 language_registry: Option<Arc<LanguageRegistry>>,
1573+ base_kind: DiffBaseKind,
15561574 cx: &mut App,
15571575 ) -> Self {
15581576 let base_text = cx.new(|cx| {
@@ -1571,12 +1589,14 @@ impl BufferDiff { · 12 unmodified lines
15711589 diff_snapshot: None,
15721590 buffer_snapshot: buffer.clone(),
15731591 secondary_diff: None,
1592+ base_kind,
15741593 }
15751594 }
15761595
15771596 pub fn new_with_base_text_buffer(
15781597 buffer: &text::BufferSnapshot,
15791598 base_text_buffer: Entity<language::Buffer>,
1599+ base_kind: DiffBaseKind,
15801600 _cx: &mut App,
15811601 ) -> Self {
15821602 BufferDiff {
@@ -1585,6 +1605,7 @@ impl BufferDiff { · 2 unmodified lines
15851605 diff_snapshot: None,
15861606 buffer_snapshot: buffer.clone(),
15871607 secondary_diff: None,
1608+ base_kind,
15881609 }
15891610 }
15901611
@@ -1592,6 +1613,7 @@ impl BufferDiff { · 1 unmodified line
15921613 buffer: &text::BufferSnapshot,
15931614 language: Option<Arc<Language>>,
15941615 language_registry: Option<Arc<LanguageRegistry>>,
1616+ base_kind: DiffBaseKind,
15951617 cx: &mut Context<Self>,
15961618 ) -> Self {
15971619 let base_text = buffer.text();
@@ -1622,6 +1644,7 @@ impl BufferDiff { · 24 unmodified lines
16221644 diff_snapshot: Some(diff_snapshot),
16231645 buffer_snapshot: buffer.clone(),
16241646 secondary_diff: None,
1647+ base_kind,
16251648 }
16261649 }
16271650
@@ -1631,7 +1654,7 @@ impl BufferDiff { · 3 unmodified lines
16311654 buffer: &text::BufferSnapshot,
16321655 cx: &mut Context<Self>,
16331656 ) -> Self {
1634− let mut this = BufferDiff::new(buffer, None, None, cx);
1657+ let mut this = BufferDiff::new(buffer, None, None, DiffBaseKind::Head, cx);
16351658 let mut base_text = base_text.to_owned();
16361659 text::LineEnding::normalize(&mut base_text);
16371660 let base_text_buffer = cx.new(|cx| {
@@ -1655,6 +1678,16 @@ impl BufferDiff { · 17 unmodified lines
16551678 self.secondary_diff = Some(diff);
16561679 }
16571680
1681+ pub fn base_kind(&self) -> DiffBaseKind {
1682+ self.base_kind
1683+ }
1684+
1685+ /// Whether hunks in this diff can be staged or restored: true only when
1686+ /// the diff's base is HEAD.
1687+ pub fn is_stageable(&self) -> bool {
1688+ self.base_kind == DiffBaseKind::Head
1689+ }
1690+
16581691 pub fn secondary_diff(&self) -> Option<Entity<BufferDiff>> {
16591692 self.secondary_diff.clone()
16601693 }
@@ -2449,7 +2482,8 @@ mod tests { · 788 unmodified lines
24492482 ],
24502483 );
24512484
2452− diff = cx.update(|cx| BufferDiff::new(&buffer, None, None, cx).snapshot(cx));
2485+ diff = cx
2486+ .update(|cx| BufferDiff::new(&buffer, None, None, DiffBaseKind::Head, cx).snapshot(cx));
24532487 assert_hunks::<&str, _>(
24542488 diff.hunks_intersecting_range(
24552489 Anchor::min_max_range_for_buffer(buffer.remote_id()),
@@ -3154,7 +3188,8 @@ mod tests { · 698 unmodified lines
31543188
31553189 let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), buffer_text_1);
31563190
3157− let empty_diff = cx.update(|cx| BufferDiff::new(&buffer, None, None, cx).snapshot(cx));
3191+ let empty_diff = cx
3192+ .update(|cx| BufferDiff::new(&buffer, None, None, DiffBaseKind::Head, cx).snapshot(cx));
31583193 let diff_1 = BufferDiffSnapshot::new_sync(&buffer, base_text.clone(), cx);
31593194 let DiffChanged {
31603195 changed_range,
@@ -4312,7 +4347,8 @@ mod tests { · 1151 unmodified lines
43124347 );
43134348 let buffer_snapshot = buffer.snapshot();
43144349
4315− let diff = cx.new(|cx| BufferDiff::new(&buffer_snapshot, None, None, cx));
4350+ let diff =
4351+ cx.new(|cx| BufferDiff::new(&buffer_snapshot, None, None, DiffBaseKind::Head, cx));
43164352 diff.update(cx, |diff, cx| {
43174353 diff.set_base_text(Some(Arc::from(base_text_crlf)), buffer_snapshot.clone(), cx)
43184354 })