git: Ensure folded buffers are synced when deploying side-by-side diff (#47498)

Cole Miller and Zed Zippy created

Release Notes:

- N/A

---------

Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>

Change summary

crates/editor/src/display_map.rs           | 46 ++++++++++++++++++++++++
crates/editor/src/display_map/block_map.rs |  1 
crates/editor/src/split.rs                 |  3 +
3 files changed, 50 insertions(+)

Detailed changes

crates/editor/src/display_map.rs 🔗

@@ -199,6 +199,7 @@ pub struct DisplayMap {
 
 pub(crate) struct Companion {
     rhs_display_map_id: EntityId,
+    rhs_folded_buffers: HashSet<BufferId>,
     rhs_buffer_to_lhs_buffer: HashMap<BufferId, BufferId>,
     lhs_buffer_to_rhs_buffer: HashMap<BufferId, BufferId>,
     rhs_excerpt_to_lhs_excerpt: HashMap<ExcerptId, ExcerptId>,
@@ -210,11 +211,13 @@ pub(crate) struct Companion {
 impl Companion {
     pub(crate) fn new(
         rhs_display_map_id: EntityId,
+        rhs_folded_buffers: HashSet<BufferId>,
         rhs_rows_to_lhs_rows: ConvertMultiBufferRows,
         lhs_rows_to_rhs_rows: ConvertMultiBufferRows,
     ) -> Self {
         Self {
             rhs_display_map_id,
+            rhs_folded_buffers,
             rhs_buffer_to_lhs_buffer: Default::default(),
             lhs_buffer_to_rhs_buffer: Default::default(),
             rhs_excerpt_to_lhs_excerpt: Default::default(),
@@ -347,6 +350,18 @@ impl DisplayMap {
         companion: Option<(WeakEntity<DisplayMap>, Entity<Companion>)>,
         cx: &mut Context<Self>,
     ) {
+        if let Some((_, ref companion_entity)) = companion {
+            let c = companion_entity.read(cx);
+            if self.entity_id != c.rhs_display_map_id {
+                let buffer_mapping = c.buffer_to_companion_buffer(c.rhs_display_map_id);
+                self.block_map.folded_buffers = c
+                    .rhs_folded_buffers
+                    .iter()
+                    .filter_map(|id| buffer_mapping.get(id).copied())
+                    .collect();
+            }
+        }
+
         self.companion = companion;
 
         let buffer_snapshot = self.buffer.read(cx).snapshot(cx);
@@ -806,6 +821,21 @@ impl DisplayMap {
     ) {
         let buffer_ids: Vec<_> = buffer_ids.into_iter().collect();
 
+        if let Some((_, companion_entity)) = &self.companion {
+            companion_entity.update(cx, |companion, _| {
+                if self.entity_id == companion.rhs_display_map_id {
+                    companion
+                        .rhs_folded_buffers
+                        .extend(buffer_ids.iter().copied());
+                } else {
+                    let rhs_ids = buffer_ids
+                        .iter()
+                        .filter_map(|id| companion.lhs_buffer_to_rhs_buffer.get(id).copied());
+                    companion.rhs_folded_buffers.extend(rhs_ids);
+                }
+            });
+        }
+
         let (self_wrap_snapshot, self_wrap_edits) = self.sync_through_wrap(cx);
 
         let companion_wrap_data = self.companion.as_ref().and_then(|(companion_dm, _)| {
@@ -861,6 +891,22 @@ impl DisplayMap {
     ) {
         let buffer_ids: Vec<_> = buffer_ids.into_iter().collect();
 
+        if let Some((_, companion_entity)) = &self.companion {
+            companion_entity.update(cx, |companion, _| {
+                if self.entity_id == companion.rhs_display_map_id {
+                    for id in &buffer_ids {
+                        companion.rhs_folded_buffers.remove(id);
+                    }
+                } else {
+                    for id in &buffer_ids {
+                        if let Some(rhs_id) = companion.lhs_buffer_to_rhs_buffer.get(id) {
+                            companion.rhs_folded_buffers.remove(rhs_id);
+                        }
+                    }
+                }
+            });
+        }
+
         let (self_wrap_snapshot, self_wrap_edits) = self.sync_through_wrap(cx);
 
         let companion_wrap_data = self.companion.as_ref().and_then(|(companion_dm, _)| {

crates/editor/src/display_map/block_map.rs 🔗

@@ -4266,6 +4266,7 @@ mod tests {
         let companion = cx.new(|_| {
             let mut c = Companion::new(
                 rhs_entity_id,
+                Default::default(),
                 convert_rhs_rows_to_lhs,
                 convert_lhs_rows_to_rhs,
             );

crates/editor/src/split.rs 🔗

@@ -503,8 +503,11 @@ impl SplittableEditor {
                 .collect()
         };
 
+        let primary_folded_buffers = primary_display_map.read(cx).folded_buffers().clone();
+
         let mut companion = Companion::new(
             rhs_display_map_id,
+            primary_folded_buffers,
             convert_rhs_rows_to_lhs,
             convert_lhs_rows_to_rhs,
         );