Do not show diffs for files with \r\n contents (#11519)

This commit is contained in:
Kirill Bulatov 2024-05-08 00:37:09 +03:00 committed by GitHub
parent 6a64b732b6
commit 3d9f0087ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 56 additions and 33 deletions

View File

@ -2826,6 +2826,31 @@ async fn test_join_lines_with_git_diff_base(
); );
} }
#[gpui::test]
async fn test_custom_newlines_cause_no_false_positive_diffs(
executor: BackgroundExecutor,
cx: &mut gpui::TestAppContext,
) {
init_test(cx, |_| {});
let mut cx = EditorTestContext::new(cx).await;
cx.set_state("Line 0\r\nLine 1\rˇ\nLine 2\r\nLine 3");
cx.set_diff_base(Some("Line 0\r\nLine 1\r\nLine 2\r\nLine 3"));
executor.run_until_parked();
cx.update_editor(|editor, cx| {
assert_eq!(
editor
.buffer()
.read(cx)
.snapshot(cx)
.git_diff_hunks_in_range(0..u32::MAX)
.collect::<Vec<_>>(),
Vec::new(),
"Should not have any diffs for files with custom newlines"
);
});
}
#[gpui::test] #[gpui::test]
async fn test_manipulate_lines_with_single_selection(cx: &mut TestAppContext) { async fn test_manipulate_lines_with_single_selection(cx: &mut TestAppContext) {
init_test(cx, |_| {}); init_test(cx, |_| {});
@ -9026,7 +9051,7 @@ async fn test_multibuffer_reverts(cx: &mut gpui::TestAppContext) {
.collect::<String>(), .collect::<String>(),
cx, cx,
); );
buffer.set_diff_base(Some(sample_text.into()), cx); buffer.set_diff_base(Some(sample_text), cx);
}); });
cx.executor().run_until_parked(); cx.executor().run_until_parked();
} }
@ -10041,17 +10066,17 @@ async fn test_toggle_diff_expand_in_multi_buffer(cx: &mut gpui::TestAppContext)
"vvvv\nwwww\nxxxx\nyyyy\nzzzz\n@@@@\n{{{{\n||||\n}}}}\n~~~~\n\u{7f}\u{7f}\u{7f}\u{7f}"; "vvvv\nwwww\nxxxx\nyyyy\nzzzz\n@@@@\n{{{{\n||||\n}}}}\n~~~~\n\u{7f}\u{7f}\u{7f}\u{7f}";
let buffer_1 = cx.new_model(|cx| { let buffer_1 = cx.new_model(|cx| {
let mut buffer = Buffer::local(modified_sample_text_1.to_string(), cx); let mut buffer = Buffer::local(modified_sample_text_1.to_string(), cx);
buffer.set_diff_base(Some(sample_text_1.clone().into()), cx); buffer.set_diff_base(Some(sample_text_1.clone()), cx);
buffer buffer
}); });
let buffer_2 = cx.new_model(|cx| { let buffer_2 = cx.new_model(|cx| {
let mut buffer = Buffer::local(modified_sample_text_2.to_string(), cx); let mut buffer = Buffer::local(modified_sample_text_2.to_string(), cx);
buffer.set_diff_base(Some(sample_text_2.clone().into()), cx); buffer.set_diff_base(Some(sample_text_2.clone()), cx);
buffer buffer
}); });
let buffer_3 = cx.new_model(|cx| { let buffer_3 = cx.new_model(|cx| {
let mut buffer = Buffer::local(modified_sample_text_3.to_string(), cx); let mut buffer = Buffer::local(modified_sample_text_3.to_string(), cx);
buffer.set_diff_base(Some(sample_text_3.clone().into()), cx); buffer.set_diff_base(Some(sample_text_3.clone()), cx);
buffer buffer
}); });

View File

@ -145,8 +145,7 @@ mod tests {
1.five 1.five
1.six 1.six
" "
.unindent() .unindent(),
.into(),
), ),
cx, cx,
); );
@ -182,8 +181,7 @@ mod tests {
2.four 2.four
2.six 2.six
" "
.unindent() .unindent(),
.into(),
), ),
cx, cx,
); );

View File

@ -21,7 +21,6 @@ use std::{
Arc, Arc,
}, },
}; };
use text::Rope;
use ui::Context; use ui::Context;
use util::{ use util::{
assert_set_eq, assert_set_eq,
@ -272,8 +271,7 @@ impl EditorTestContext {
} }
pub fn set_diff_base(&mut self, diff_base: Option<&str>) { pub fn set_diff_base(&mut self, diff_base: Option<&str>) {
let diff_base = diff_base.map(Rope::from); self.update_buffer(|buffer, cx| buffer.set_diff_base(diff_base.map(ToOwned::to_owned), cx));
self.update_buffer(|buffer, cx| buffer.set_diff_base(diff_base, cx));
} }
/// Change the editor's text and selections using a string containing /// Change the editor's text and selections using a string containing

View File

@ -564,12 +564,7 @@ impl Buffer {
let buffer_id = BufferId::new(message.id) let buffer_id = BufferId::new(message.id)
.with_context(|| anyhow!("Could not deserialize buffer_id"))?; .with_context(|| anyhow!("Could not deserialize buffer_id"))?;
let buffer = TextBuffer::new(replica_id, buffer_id, message.base_text); let buffer = TextBuffer::new(replica_id, buffer_id, message.base_text);
let mut this = Self::build( let mut this = Self::build(buffer, message.diff_base, file, capability);
buffer,
message.diff_base.map(|text| text.into()),
file,
capability,
);
this.text.set_line_ending(proto::deserialize_line_ending( this.text.set_line_ending(proto::deserialize_line_ending(
rpc::proto::LineEnding::from_i32(message.line_ending) rpc::proto::LineEnding::from_i32(message.line_ending)
.ok_or_else(|| anyhow!("missing line_ending"))?, .ok_or_else(|| anyhow!("missing line_ending"))?,
@ -658,7 +653,7 @@ impl Buffer {
/// Builds a [Buffer] with the given underlying [TextBuffer], diff base, [File] and [Capability]. /// Builds a [Buffer] with the given underlying [TextBuffer], diff base, [File] and [Capability].
pub fn build( pub fn build(
buffer: TextBuffer, buffer: TextBuffer,
diff_base: Option<Rope>, diff_base: Option<String>,
file: Option<Arc<dyn File>>, file: Option<Arc<dyn File>>,
capability: Capability, capability: Capability,
) -> Self { ) -> Self {
@ -671,7 +666,12 @@ impl Buffer {
transaction_depth: 0, transaction_depth: 0,
was_dirty_before_starting_transaction: None, was_dirty_before_starting_transaction: None,
text: buffer, text: buffer,
diff_base, diff_base: diff_base
.map(|mut raw_diff_base| {
LineEnding::normalize(&mut raw_diff_base);
raw_diff_base
})
.map(Rope::from),
diff_base_version: 0, diff_base_version: 0,
git_diff: git::diff::BufferDiff::new(), git_diff: git::diff::BufferDiff::new(),
file, file,
@ -900,8 +900,13 @@ impl Buffer {
/// Sets the text that will be used to compute a Git diff /// Sets the text that will be used to compute a Git diff
/// against the buffer text. /// against the buffer text.
pub fn set_diff_base(&mut self, diff_base: Option<Rope>, cx: &mut ModelContext<Self>) { pub fn set_diff_base(&mut self, diff_base: Option<String>, cx: &mut ModelContext<Self>) {
self.diff_base = diff_base; self.diff_base = diff_base
.map(|mut raw_diff_base| {
LineEnding::normalize(&mut raw_diff_base);
raw_diff_base
})
.map(Rope::from);
self.diff_base_version += 1; self.diff_base_version += 1;
if let Some(recalc_task) = self.git_diff_recalc(cx) { if let Some(recalc_task) = self.git_diff_recalc(cx) {
cx.spawn(|buffer, mut cx| async move { cx.spawn(|buffer, mut cx| async move {
@ -923,7 +928,7 @@ impl Buffer {
/// Recomputes the Git diff status. /// Recomputes the Git diff status.
pub fn git_diff_recalc(&mut self, cx: &mut ModelContext<Self>) -> Option<Task<()>> { pub fn git_diff_recalc(&mut self, cx: &mut ModelContext<Self>) -> Option<Task<()>> {
let diff_base = self.diff_base.clone()?; // TODO: Make this an Arc let diff_base = self.diff_base.clone()?;
let snapshot = self.snapshot(); let snapshot = self.snapshot();
let mut diff = self.git_diff.clone(); let mut diff = self.git_diff.clone();

View File

@ -97,7 +97,7 @@ use std::{
}; };
use task::static_source::{StaticSource, TrackedFile}; use task::static_source::{StaticSource, TrackedFile};
use terminals::Terminals; use terminals::Terminals;
use text::{Anchor, BufferId, LineEnding, Rope}; use text::{Anchor, BufferId, LineEnding};
use util::{ use util::{
debug_panic, defer, debug_panic, defer,
http::{HttpClient, Url}, http::{HttpClient, Url},
@ -7559,11 +7559,7 @@ impl Project {
None None
} else { } else {
let relative_path = path.strip_prefix(&work_directory).ok()?; let relative_path = path.strip_prefix(&work_directory).ok()?;
repo_entry repo_entry.repo().lock().load_index_text(relative_path)
.repo()
.lock()
.load_index_text(relative_path)
.map(Rope::from)
}; };
Some((buffer, base_text)) Some((buffer, base_text))
} }
@ -7591,7 +7587,7 @@ impl Project {
.send(proto::UpdateDiffBase { .send(proto::UpdateDiffBase {
project_id, project_id,
buffer_id, buffer_id,
diff_base: diff_base.map(|rope| rope.to_string()), diff_base,
}) })
.log_err(); .log_err();
} }
@ -8666,14 +8662,15 @@ impl Project {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
let buffer_id = envelope.payload.buffer_id; let buffer_id = envelope.payload.buffer_id;
let buffer_id = BufferId::new(buffer_id)?; let buffer_id = BufferId::new(buffer_id)?;
let diff_base = envelope.payload.diff_base.map(Rope::from);
if let Some(buffer) = this if let Some(buffer) = this
.opened_buffers .opened_buffers
.get_mut(&buffer_id) .get_mut(&buffer_id)
.and_then(|b| b.upgrade()) .and_then(|b| b.upgrade())
.or_else(|| this.incomplete_remote_buffers.get(&buffer_id).cloned()) .or_else(|| this.incomplete_remote_buffers.get(&buffer_id).cloned())
{ {
buffer.update(cx, |buffer, cx| buffer.set_diff_base(diff_base, cx)); buffer.update(cx, |buffer, cx| {
buffer.set_diff_base(envelope.payload.diff_base, cx)
});
} }
Ok(()) Ok(())
})? })?

View File

@ -1069,7 +1069,7 @@ impl LocalWorktree {
&self, &self,
path: &Path, path: &Path,
cx: &mut ModelContext<Worktree>, cx: &mut ModelContext<Worktree>,
) -> Task<Result<(File, String, Option<Rope>)>> { ) -> Task<Result<(File, String, Option<String>)>> {
let path = Arc::from(path); let path = Arc::from(path);
let abs_path = self.absolutize(&path); let abs_path = self.absolutize(&path);
let fs = self.fs.clone(); let fs = self.fs.clone();
@ -1100,7 +1100,7 @@ impl LocalWorktree {
if abs_path_metadata.is_dir || abs_path_metadata.is_symlink { if abs_path_metadata.is_dir || abs_path_metadata.is_symlink {
None None
} else { } else {
git_repo.lock().load_index_text(&repo_path).map(Rope::from) git_repo.lock().load_index_text(&repo_path)
} }
} }
})); }));