git: Correct logic for updating companion excerpt IDs mapping (#48906)
We try to remove old excerpt IDs from the companion when mutating excerpts for a path, but we were incorrectly doing this using the excerpt IDs for the right-hand side multibuffer _after_ any excerpt mutations had occurred, causing stale excerpt IDs to accumulate. Release Notes: - N/A
This commit is contained in:
1 parent
ba1253c210
commit
56e2ec022c
1 file changed
+108
-93
+108
-93
@@ -1002,41 +1002,33 @@ impl SplittableEditor {
|
||||
cx: &mut Context<Self>,
|
||||
) -> (Vec<Range<Anchor>>, bool) {
|
||||
let rhs_display_map = self.rhs_editor.read(cx).display_map.clone();
|
||||
let lhs = &mut self.lhs;
|
||||
let (anchors, added_a_new_excerpt) =
|
||||
self.rhs_multibuffer.update(cx, |rhs_multibuffer, cx| {
|
||||
let (anchors, added_a_new_excerpt) = rhs_multibuffer.set_excerpts_for_path(
|
||||
path.clone(),
|
||||
buffer.clone(),
|
||||
ranges,
|
||||
context_line_count,
|
||||
cx,
|
||||
);
|
||||
if !anchors.is_empty()
|
||||
&& rhs_multibuffer
|
||||
.diff_for(buffer.read(cx).remote_id())
|
||||
.is_none_or(|old_diff| old_diff.entity_id() != diff.entity_id())
|
||||
{
|
||||
rhs_multibuffer.add_diff(diff.clone(), cx);
|
||||
}
|
||||
|
||||
if let Some(lhs) = lhs {
|
||||
lhs.multibuffer.update(cx, |lhs_multibuffer, lhs_cx| {
|
||||
LhsEditor::sync_path_excerpts(
|
||||
path,
|
||||
rhs_multibuffer,
|
||||
lhs_multibuffer,
|
||||
diff,
|
||||
&rhs_display_map,
|
||||
lhs_cx,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
(anchors, added_a_new_excerpt)
|
||||
});
|
||||
|
||||
(anchors, added_a_new_excerpt)
|
||||
let lhs = self.lhs.as_ref();
|
||||
self.rhs_multibuffer.update(cx, |rhs_multibuffer, cx| {
|
||||
mutate_excerpts_for_paths(
|
||||
rhs_multibuffer,
|
||||
lhs,
|
||||
&rhs_display_map,
|
||||
vec![(path.clone(), diff.clone())],
|
||||
cx,
|
||||
|rhs_multibuffer, cx| {
|
||||
let (anchors, added_a_new_excerpt) = rhs_multibuffer.set_excerpts_for_path(
|
||||
path.clone(),
|
||||
buffer.clone(),
|
||||
ranges,
|
||||
context_line_count,
|
||||
cx,
|
||||
);
|
||||
if !anchors.is_empty()
|
||||
&& rhs_multibuffer
|
||||
.diff_for(buffer.read(cx).remote_id())
|
||||
.is_none_or(|old_diff| old_diff.entity_id() != diff.entity_id())
|
||||
{
|
||||
rhs_multibuffer.add_diff(diff.clone(), cx);
|
||||
}
|
||||
(anchors, added_a_new_excerpt)
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn expand_excerpts(
|
||||
@@ -1047,37 +1039,35 @@ impl SplittableEditor {
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let rhs_display_map = self.rhs_editor.read(cx).display_map.clone();
|
||||
|
||||
let lhs = &mut self.lhs;
|
||||
let lhs_multibuffer = lhs.as_ref().map(|l| l.multibuffer.clone());
|
||||
let lhs = self.lhs.as_ref();
|
||||
self.rhs_multibuffer.update(cx, |rhs_multibuffer, cx| {
|
||||
if let Some(lhs_multibuffer) = lhs_multibuffer {
|
||||
if lhs.is_some() {
|
||||
let snapshot = rhs_multibuffer.snapshot(cx);
|
||||
let affected_paths: HashMap<_, _> = excerpt_ids
|
||||
let paths_with_diffs: Vec<_> = excerpt_ids
|
||||
.clone()
|
||||
.map(|excerpt_id| {
|
||||
let path = rhs_multibuffer.path_for_excerpt(excerpt_id).unwrap();
|
||||
let buffer = snapshot.buffer_for_excerpt(excerpt_id).unwrap();
|
||||
let diff = rhs_multibuffer.diff_for(buffer.remote_id()).unwrap();
|
||||
(path, diff)
|
||||
.filter_map(|excerpt_id| {
|
||||
let path = rhs_multibuffer.path_for_excerpt(excerpt_id)?;
|
||||
let buffer = snapshot.buffer_for_excerpt(excerpt_id)?;
|
||||
let diff = rhs_multibuffer.diff_for(buffer.remote_id())?;
|
||||
Some((path, diff))
|
||||
})
|
||||
.collect::<HashMap<_, _>>()
|
||||
.into_iter()
|
||||
.collect();
|
||||
rhs_multibuffer.expand_excerpts(excerpt_ids.clone(), lines, direction, cx);
|
||||
for (path, diff) in affected_paths {
|
||||
lhs_multibuffer.update(cx, |lhs_multibuffer, lhs_cx| {
|
||||
LhsEditor::sync_path_excerpts(
|
||||
path,
|
||||
rhs_multibuffer,
|
||||
lhs_multibuffer,
|
||||
diff,
|
||||
&rhs_display_map,
|
||||
lhs_cx,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
mutate_excerpts_for_paths(
|
||||
rhs_multibuffer,
|
||||
lhs,
|
||||
&rhs_display_map,
|
||||
paths_with_diffs,
|
||||
cx,
|
||||
|rhs_multibuffer, cx| {
|
||||
rhs_multibuffer.expand_excerpts(excerpt_ids.clone(), lines, direction, cx);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
rhs_multibuffer.expand_excerpts(excerpt_ids.clone(), lines, direction, cx);
|
||||
};
|
||||
rhs_multibuffer.expand_excerpts(excerpt_ids, lines, direction, cx);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1086,15 +1076,17 @@ impl SplittableEditor {
|
||||
|
||||
if let Some(lhs) = &self.lhs {
|
||||
self.rhs_multibuffer.update(cx, |rhs_multibuffer, cx| {
|
||||
lhs.multibuffer.update(cx, |lhs_multibuffer, cx| {
|
||||
LhsEditor::remove_mappings_for_path(
|
||||
&path,
|
||||
rhs_multibuffer,
|
||||
lhs_multibuffer,
|
||||
&rhs_display_map,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
let rhs_excerpt_ids: Vec<ExcerptId> =
|
||||
rhs_multibuffer.excerpts_for_path(&path).collect();
|
||||
let lhs_excerpt_ids: Vec<ExcerptId> =
|
||||
lhs.multibuffer.read(cx).excerpts_for_path(&path).collect();
|
||||
|
||||
if let Some(companion) = rhs_display_map.read(cx).companion().cloned() {
|
||||
companion.update(cx, |c, _| {
|
||||
c.remove_excerpt_mappings(lhs_excerpt_ids, rhs_excerpt_ids);
|
||||
});
|
||||
}
|
||||
|
||||
rhs_multibuffer.remove_excerpts_for_path(path.clone(), cx);
|
||||
});
|
||||
lhs.multibuffer.update(cx, |lhs_multibuffer, cx| {
|
||||
@@ -1938,6 +1930,44 @@ impl Render for SplittableEditor {
|
||||
}
|
||||
}
|
||||
|
||||
fn mutate_excerpts_for_paths<R>(
|
||||
rhs_multibuffer: &mut MultiBuffer,
|
||||
lhs: Option<&LhsEditor>,
|
||||
rhs_display_map: &Entity<DisplayMap>,
|
||||
paths_with_diffs: Vec<(PathKey, Entity<BufferDiff>)>,
|
||||
cx: &mut Context<MultiBuffer>,
|
||||
mutate: impl FnOnce(&mut MultiBuffer, &mut Context<MultiBuffer>) -> R,
|
||||
) -> R {
|
||||
let old_rhs_ids: Vec<_> = paths_with_diffs
|
||||
.iter()
|
||||
.map(|(path, _)| {
|
||||
rhs_multibuffer
|
||||
.excerpts_for_path(path)
|
||||
.collect::<Vec<ExcerptId>>()
|
||||
})
|
||||
.collect();
|
||||
|
||||
let result = mutate(rhs_multibuffer, cx);
|
||||
|
||||
if let Some(lhs) = lhs {
|
||||
for ((path, diff), old_rhs_ids) in paths_with_diffs.into_iter().zip(old_rhs_ids) {
|
||||
lhs.multibuffer.update(cx, |lhs_multibuffer, lhs_cx| {
|
||||
LhsEditor::sync_path_excerpts(
|
||||
path,
|
||||
old_rhs_ids,
|
||||
rhs_multibuffer,
|
||||
lhs_multibuffer,
|
||||
diff,
|
||||
rhs_display_map,
|
||||
lhs_cx,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
impl LhsEditor {
|
||||
fn update_path_excerpts_from_rhs(
|
||||
path_key: PathKey,
|
||||
@@ -2012,19 +2042,21 @@ impl LhsEditor {
|
||||
|
||||
fn sync_path_excerpts(
|
||||
path_key: PathKey,
|
||||
old_rhs_excerpt_ids: Vec<ExcerptId>,
|
||||
rhs_multibuffer: &MultiBuffer,
|
||||
lhs_multibuffer: &mut MultiBuffer,
|
||||
diff: Entity<BufferDiff>,
|
||||
rhs_display_map: &Entity<DisplayMap>,
|
||||
lhs_cx: &mut Context<MultiBuffer>,
|
||||
) {
|
||||
Self::remove_mappings_for_path(
|
||||
&path_key,
|
||||
rhs_multibuffer,
|
||||
lhs_multibuffer,
|
||||
rhs_display_map,
|
||||
lhs_cx,
|
||||
);
|
||||
let old_lhs_excerpt_ids: Vec<ExcerptId> =
|
||||
lhs_multibuffer.excerpts_for_path(&path_key).collect();
|
||||
|
||||
if let Some(companion) = rhs_display_map.read(lhs_cx).companion().cloned() {
|
||||
companion.update(lhs_cx, |c, _| {
|
||||
c.remove_excerpt_mappings(old_lhs_excerpt_ids, old_rhs_excerpt_ids);
|
||||
});
|
||||
}
|
||||
|
||||
let mappings = Self::update_path_excerpts_from_rhs(
|
||||
path_key,
|
||||
@@ -2046,23 +2078,6 @@ impl LhsEditor {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_mappings_for_path(
|
||||
path_key: &PathKey,
|
||||
rhs_multibuffer: &MultiBuffer,
|
||||
lhs_multibuffer: &MultiBuffer,
|
||||
rhs_display_map: &Entity<DisplayMap>,
|
||||
cx: &mut App,
|
||||
) {
|
||||
let rhs_excerpt_ids: Vec<ExcerptId> = rhs_multibuffer.excerpts_for_path(path_key).collect();
|
||||
let lhs_excerpt_ids: Vec<ExcerptId> = lhs_multibuffer.excerpts_for_path(path_key).collect();
|
||||
|
||||
if let Some(companion) = rhs_display_map.read(cx).companion().cloned() {
|
||||
companion.update(cx, |c, _| {
|
||||
c.remove_excerpt_mappings(lhs_excerpt_ids, rhs_excerpt_ids);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in new issue
Block a user