From b710945949ed19559779e11332bda39cba76093b Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 5 Feb 2025 12:37:32 -0800 Subject: [PATCH] Fix replication of head text when head matches index (#24306) Release Notes: - N/A --------- Co-authored-by: cole-miller --- Cargo.lock | 1 + crates/project/src/buffer_store.rs | 8 +- crates/remote_server/Cargo.toml | 2 +- .../remote_server/src/remote_editing_tests.rs | 120 ++++++++++++++++++ 4 files changed, 126 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c679633fae3f97d50f6e514535e35c294542a611..de606b70d99f14e221187f5671ba675c246387e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10700,6 +10700,7 @@ dependencies = [ "sysinfo", "telemetry_events", "toml 0.8.19", + "unindent", "util", "worktree", ] diff --git a/crates/project/src/buffer_store.rs b/crates/project/src/buffer_store.rs index 10bc83da7a330bbf2288fab263663b5e663610e4..d3831dcce30f6234ac993ca094d82f638186e47d 100644 --- a/crates/project/src/buffer_store.rs +++ b/crates/project/src/buffer_store.rs @@ -131,7 +131,7 @@ impl BufferChangeSetState { let diff_bases_change = match mode { Mode::HeadOnly => DiffBasesChange::SetHead(message.committed_text), Mode::IndexOnly => DiffBasesChange::SetIndex(message.staged_text), - Mode::IndexMatchesHead => DiffBasesChange::SetBoth(message.staged_text), + Mode::IndexMatchesHead => DiffBasesChange::SetBoth(message.committed_text), Mode::IndexAndHead => DiffBasesChange::SetEach { index: message.staged_text, head: message.committed_text, @@ -402,7 +402,7 @@ impl RemoteBufferStore { .await?; let mode = Mode::from_i32(response.mode).ok_or_else(|| anyhow!("Invalid mode"))?; let bases = match mode { - Mode::IndexMatchesHead => DiffBasesChange::SetBoth(response.staged_text), + Mode::IndexMatchesHead => DiffBasesChange::SetBoth(response.committed_text), Mode::IndexAndHead => DiffBasesChange::SetEach { head: response.committed_text, index: response.staged_text, @@ -896,7 +896,7 @@ impl LocalBufferStore { let diff_bases_change = match (needs_staged_text, needs_committed_text) { (true, true) => Some(if staged_text == committed_text { - DiffBasesChange::SetBoth(staged_text) + DiffBasesChange::SetBoth(committed_text) } else { DiffBasesChange::SetEach { index: staged_text, @@ -944,7 +944,7 @@ impl LocalBufferStore { (index, head, Mode::IndexAndHead) } DiffBasesChange::SetBoth(text) => { - (text, None, Mode::IndexMatchesHead) + (None, text, Mode::IndexMatchesHead) } }; let message = proto::UpdateDiffBases { diff --git a/crates/remote_server/Cargo.toml b/crates/remote_server/Cargo.toml index f2238d91fa2d3956a469cdf3d2acbc79cfba77a7..5286f4574a7aed5aa13d7f7d33f98a05a1f942e1 100644 --- a/crates/remote_server/Cargo.toml +++ b/crates/remote_server/Cargo.toml @@ -77,7 +77,7 @@ node_runtime = { workspace = true, features = ["test-support"] } project = { workspace = true, features = ["test-support"] } remote = { workspace = true, features = ["test-support"] } lsp = { workspace = true, features=["test-support"] } - +unindent.workspace = true serde_json.workspace = true [build-dependencies] diff --git a/crates/remote_server/src/remote_editing_tests.rs b/crates/remote_server/src/remote_editing_tests.rs index b39df8edce3f8c9ae210d00565ddf006f4ef19b6..4e34953ea26417866cf603a31bd7ae013d327ca5 100644 --- a/crates/remote_server/src/remote_editing_tests.rs +++ b/crates/remote_server/src/remote_editing_tests.rs @@ -27,6 +27,7 @@ use std::{ path::{Path, PathBuf}, sync::Arc, }; +use unindent::Unindent as _; use util::{path, separator}; #[gpui::test] @@ -1183,6 +1184,125 @@ async fn test_remote_rename_entry(cx: &mut TestAppContext, server_cx: &mut TestA assert_eq!(worktree.entry_for_path("README.rst").unwrap().id, entry.id) }); } + +#[gpui::test] +async fn test_remote_git_diffs(cx: &mut TestAppContext, server_cx: &mut TestAppContext) { + let text_2 = " + fn one() -> usize { + 1 + } + " + .unindent(); + let text_1 = " + fn one() -> usize { + 0 + } + " + .unindent(); + + let fs = FakeFs::new(server_cx.executor()); + fs.insert_tree( + "/code", + json!({ + "project1": { + ".git": {}, + "src": { + "lib.rs": text_2 + }, + "README.md": "# project 1", + }, + }), + ) + .await; + fs.set_index_for_repo( + Path::new("/code/project1/.git"), + &[("src/lib.rs".into(), text_1.clone())], + ); + fs.set_head_for_repo( + Path::new("/code/project1/.git"), + &[("src/lib.rs".into(), text_1.clone())], + ); + + let (project, _headless) = init_test(&fs, cx, server_cx).await; + let (worktree, _) = project + .update(cx, |project, cx| { + project.find_or_create_worktree("/code/project1", true, cx) + }) + .await + .unwrap(); + let worktree_id = cx.update(|cx| worktree.read(cx).id()); + cx.executor().run_until_parked(); + + let buffer = project + .update(cx, |project, cx| { + project.open_buffer((worktree_id, Path::new("src/lib.rs")), cx) + }) + .await + .unwrap(); + let change_set = project + .update(cx, |project, cx| { + project.open_uncommitted_changes(buffer.clone(), cx) + }) + .await + .unwrap(); + + change_set.read_with(cx, |change_set, cx| { + assert_eq!(change_set.base_text_string().unwrap(), text_1); + assert_eq!( + change_set + .unstaged_change_set + .as_ref() + .unwrap() + .read(cx) + .base_text_string() + .unwrap(), + text_1 + ); + }); + + // stage the current buffer's contents + fs.set_index_for_repo( + Path::new("/code/project1/.git"), + &[("src/lib.rs".into(), text_2.clone())], + ); + + cx.executor().run_until_parked(); + change_set.read_with(cx, |change_set, cx| { + assert_eq!(change_set.base_text_string().unwrap(), text_1); + assert_eq!( + change_set + .unstaged_change_set + .as_ref() + .unwrap() + .read(cx) + .base_text_string() + .unwrap(), + text_2 + ); + }); + + // commit the current buffer's contents + fs.set_head_for_repo( + Path::new("/code/project1/.git"), + &[("src/lib.rs".into(), text_2.clone())], + ); + + cx.executor().run_until_parked(); + change_set.read_with(cx, |change_set, cx| { + assert_eq!(change_set.base_text_string().unwrap(), text_2); + assert_eq!( + change_set + .unstaged_change_set + .as_ref() + .unwrap() + .read(cx) + .base_text_string() + .unwrap(), + text_2 + ); + }); +} + #[gpui::test] async fn test_remote_git_branches(cx: &mut TestAppContext, server_cx: &mut TestAppContext) { let fs = FakeFs::new(server_cx.executor());