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.
Showing the changes to crates/buffer_diff/src/buffer_diff.rs (1 of 33 files). Show all
Unified · Split
| @@ -25,6 +25,23 @@ pub struct BufferDiff { · 24 unmodified lines | |||
| 25 | diff_snapshot: Option<BufferDiffSnapshot>, | 25 | diff_snapshot: Option<BufferDiffSnapshot>, |
| 26 | secondary_diff: Option<Entity<BufferDiff>>, | 26 | secondary_diff: Option<Entity<BufferDiff>>, |
| 27 | buffer_snapshot: text::BufferSnapshot, | 27 | 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, | ||
| 28 | } | 45 | } |
| 29 | 46 | ||
| 30 | #[derive(Clone)] | 47 | #[derive(Clone)] |
| @@ -1553,6 +1570,7 @@ impl BufferDiff { · 1522 unmodified lines | |||
| 1553 | buffer: &text::BufferSnapshot, | 1570 | buffer: &text::BufferSnapshot, |
| 1554 | language: Option<Arc<Language>>, | 1571 | language: Option<Arc<Language>>, |
| 1555 | language_registry: Option<Arc<LanguageRegistry>>, | 1572 | language_registry: Option<Arc<LanguageRegistry>>, |
| 1573 | base_kind: DiffBaseKind, | ||
| 1556 | cx: &mut App, | 1574 | cx: &mut App, |
| 1557 | ) -> Self { | 1575 | ) -> Self { |
| 1558 | let base_text = cx.new(|cx| { | 1576 | let base_text = cx.new(|cx| { |
| @@ -1571,12 +1589,14 @@ impl BufferDiff { · 12 unmodified lines | |||
| 1571 | diff_snapshot: None, | 1589 | diff_snapshot: None, |
| 1572 | buffer_snapshot: buffer.clone(), | 1590 | buffer_snapshot: buffer.clone(), |
| 1573 | secondary_diff: None, | 1591 | secondary_diff: None, |
| 1592 | base_kind, | ||
| 1574 | } | 1593 | } |
| 1575 | } | 1594 | } |
| 1576 | 1595 | ||
| 1577 | pub fn new_with_base_text_buffer( | 1596 | pub fn new_with_base_text_buffer( |
| 1578 | buffer: &text::BufferSnapshot, | 1597 | buffer: &text::BufferSnapshot, |
| 1579 | base_text_buffer: Entity<language::Buffer>, | 1598 | base_text_buffer: Entity<language::Buffer>, |
| 1599 | base_kind: DiffBaseKind, | ||
| 1580 | _cx: &mut App, | 1600 | _cx: &mut App, |
| 1581 | ) -> Self { | 1601 | ) -> Self { |
| 1582 | BufferDiff { | 1602 | BufferDiff { |
| @@ -1585,6 +1605,7 @@ impl BufferDiff { · 2 unmodified lines | |||
| 1585 | diff_snapshot: None, | 1605 | diff_snapshot: None, |
| 1586 | buffer_snapshot: buffer.clone(), | 1606 | buffer_snapshot: buffer.clone(), |
| 1587 | secondary_diff: None, | 1607 | secondary_diff: None, |
| 1608 | base_kind, | ||
| 1588 | } | 1609 | } |
| 1589 | } | 1610 | } |
| 1590 | 1611 | ||
| @@ -1592,6 +1613,7 @@ impl BufferDiff { · 1 unmodified line | |||
| 1592 | buffer: &text::BufferSnapshot, | 1613 | buffer: &text::BufferSnapshot, |
| 1593 | language: Option<Arc<Language>>, | 1614 | language: Option<Arc<Language>>, |
| 1594 | language_registry: Option<Arc<LanguageRegistry>>, | 1615 | language_registry: Option<Arc<LanguageRegistry>>, |
| 1616 | base_kind: DiffBaseKind, | ||
| 1595 | cx: &mut Context<Self>, | 1617 | cx: &mut Context<Self>, |
| 1596 | ) -> Self { | 1618 | ) -> Self { |
| 1597 | let base_text = buffer.text(); | 1619 | let base_text = buffer.text(); |
| @@ -1622,6 +1644,7 @@ impl BufferDiff { · 24 unmodified lines | |||
| 1622 | diff_snapshot: Some(diff_snapshot), | 1644 | diff_snapshot: Some(diff_snapshot), |
| 1623 | buffer_snapshot: buffer.clone(), | 1645 | buffer_snapshot: buffer.clone(), |
| 1624 | secondary_diff: None, | 1646 | secondary_diff: None, |
| 1647 | base_kind, | ||
| 1625 | } | 1648 | } |
| 1626 | } | 1649 | } |
| 1627 | 1650 | ||
| @@ -1631,7 +1654,7 @@ impl BufferDiff { · 3 unmodified lines | |||
| 1631 | buffer: &text::BufferSnapshot, | 1654 | buffer: &text::BufferSnapshot, |
| 1632 | cx: &mut Context<Self>, | 1655 | cx: &mut Context<Self>, |
| 1633 | ) -> Self { | 1656 | ) -> Self { |
| 1634 | let mut this = BufferDiff::new(buffer, None, None, cx); | 1657 | let mut this = BufferDiff::new(buffer, None, None, DiffBaseKind::Head, cx); |
| 1635 | let mut base_text = base_text.to_owned(); | 1658 | let mut base_text = base_text.to_owned(); |
| 1636 | text::LineEnding::normalize(&mut base_text); | 1659 | text::LineEnding::normalize(&mut base_text); |
| 1637 | let base_text_buffer = cx.new(|cx| { | 1660 | let base_text_buffer = cx.new(|cx| { |
| @@ -1655,6 +1678,16 @@ impl BufferDiff { · 17 unmodified lines | |||
| 1655 | self.secondary_diff = Some(diff); | 1678 | self.secondary_diff = Some(diff); |
| 1656 | } | 1679 | } |
| 1657 | 1680 | ||
| 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 | |||
| 1658 | pub fn secondary_diff(&self) -> Option<Entity<BufferDiff>> { | 1691 | pub fn secondary_diff(&self) -> Option<Entity<BufferDiff>> { |
| 1659 | self.secondary_diff.clone() | 1692 | self.secondary_diff.clone() |
| 1660 | } | 1693 | } |
| @@ -2449,7 +2482,8 @@ mod tests { · 788 unmodified lines | |||
| 2449 | ], | 2482 | ], |
| 2450 | ); | 2483 | ); |
| 2451 | 2484 | ||
| 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)); | ||
| 2453 | assert_hunks::<&str, _>( | 2487 | assert_hunks::<&str, _>( |
| 2454 | diff.hunks_intersecting_range( | 2488 | diff.hunks_intersecting_range( |
| 2455 | Anchor::min_max_range_for_buffer(buffer.remote_id()), | 2489 | Anchor::min_max_range_for_buffer(buffer.remote_id()), |
| @@ -3154,7 +3188,8 @@ mod tests { · 698 unmodified lines | |||
| 3154 | 3188 | ||
| 3155 | let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), buffer_text_1); | 3189 | let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), buffer_text_1); |
| 3156 | 3190 | ||
| 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)); | ||
| 3158 | let diff_1 = BufferDiffSnapshot::new_sync(&buffer, base_text.clone(), cx); | 3193 | let diff_1 = BufferDiffSnapshot::new_sync(&buffer, base_text.clone(), cx); |
| 3159 | let DiffChanged { | 3194 | let DiffChanged { |
| 3160 | changed_range, | 3195 | changed_range, |
| @@ -4312,7 +4347,8 @@ mod tests { · 1151 unmodified lines | |||
| 4312 | ); | 4347 | ); |
| 4313 | let buffer_snapshot = buffer.snapshot(); | 4348 | let buffer_snapshot = buffer.snapshot(); |
| 4314 | 4349 | ||
| 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)); | ||
| 4316 | diff.update(cx, |diff, cx| { | 4352 | diff.update(cx, |diff, cx| { |
| 4317 | diff.set_base_text(Some(Arc::from(base_text_crlf)), buffer_snapshot.clone(), cx) | 4353 | diff.set_base_text(Some(Arc::from(base_text_crlf)), buffer_snapshot.clone(), cx) |
| 4318 | }) | 4354 | }) |