Fix staging/unstaging hunks remotely (#28560)

Max Brunsfeld created

Fixes a regression introduced in
https://github.com/zed-industries/zed/pull/28377 where the pending hunks
didn't get cleared properly when staging/unstaging hunks remotely. I
didn't add new tests, because the fix was to simplify some code.

Release Notes:

- N/A

Change summary

crates/project/src/git_store.rs     | 76 +++++++++++-------------------
crates/project/src/project_tests.rs |  2 
2 files changed, 29 insertions(+), 49 deletions(-)

Detailed changes

crates/project/src/git_store.rs 🔗

@@ -96,16 +96,12 @@ struct BufferDiffState {
     /// values read from the git repository are up-to-date with any hunk staging
     /// operations that have been performed on the BufferDiff.
     ///
-    /// The operation_count is incremented immediately when the user initiates a
-    /// hunk stage/unstage operation. Then, upon writing the new index text do
-    /// disk, the `operation_count_as_of_write` is updated to reflect the
-    /// operation_count that prompted the write. Finally, when reloading
-    /// index/head text from disk in response to a filesystem event, the
-    /// `operation_count_as_of_read` is updated to reflect the latest previous
-    /// write.
+    /// The operation count is incremented immediately when the user initiates a
+    /// hunk stage/unstage operation. Then, upon finishing writing the new index
+    /// text do disk, the `operation count as of write` is updated to reflect
+    /// the operation count that prompted the write.
     hunk_staging_operation_count: usize,
     hunk_staging_operation_count_as_of_write: usize,
-    hunk_staging_operation_count_as_of_read: usize,
 
     head_text: Option<Arc<String>>,
     index_text: Option<Arc<String>>,
@@ -1270,7 +1266,7 @@ impl GitStore {
                         repo.spawn_set_index_text_job(
                             path,
                             new_index_text.as_ref().map(|rope| rope.to_string()),
-                            hunk_staging_operation_count,
+                            Some(hunk_staging_operation_count),
                             cx,
                         )
                     });
@@ -1630,26 +1626,12 @@ impl GitStore {
         let repository_handle = Self::repository_for_request(&this, repository_id, &mut cx)?;
         let repo_path = RepoPath::from_str(&envelope.payload.path);
 
-        let hunk_staging_operation_count = this
-            .read_with(&cx, |this, cx| {
-                let project_path = repository_handle
-                    .read(cx)
-                    .repo_path_to_project_path(&repo_path, cx)?;
-                let buffer_id = this
-                    .buffer_store
-                    .read(cx)
-                    .buffer_id_for_project_path(&project_path)?;
-                let diff_state = this.diffs.get(buffer_id)?;
-                Some(diff_state.read(cx).hunk_staging_operation_count)
-            })?
-            .ok_or_else(|| anyhow!("unknown buffer"))?;
-
         repository_handle
             .update(&mut cx, |repository_handle, cx| {
                 repository_handle.spawn_set_index_text_job(
                     repo_path,
                     envelope.payload.text,
-                    hunk_staging_operation_count,
+                    None,
                     cx,
                 )
             })?
@@ -2045,8 +2027,6 @@ impl GitStore {
                 if let Some(buffer) = this.buffer_store.read(cx).get(buffer_id) {
                     let buffer = buffer.read(cx).text_snapshot();
                     diff_state.update(cx, |diff_state, cx| {
-                        diff_state.hunk_staging_operation_count_as_of_read =
-                            diff_state.hunk_staging_operation_count_as_of_write;
                         diff_state.handle_base_texts_updated(buffer, request.payload, cx);
                     })
                 }
@@ -2242,7 +2222,7 @@ impl BufferDiffState {
         let index_changed = self.index_changed;
         let head_changed = self.head_changed;
         let language_changed = self.language_changed;
-        let prev_hunk_staging_operation_count = self.hunk_staging_operation_count_as_of_read;
+        let prev_hunk_staging_operation_count = self.hunk_staging_operation_count_as_of_write;
         let index_matches_head = match (self.index_text.as_ref(), self.head_text.as_ref()) {
             (Some(index), Some(head)) => Arc::ptr_eq(index, head),
             (None, None) => true,
@@ -2376,7 +2356,6 @@ impl Default for BufferDiffState {
             language_registry: Default::default(),
             recalculating_tx: postage::watch::channel_with(false).0,
             hunk_staging_operation_count: 0,
-            hunk_staging_operation_count_as_of_read: 0,
             hunk_staging_operation_count_as_of_write: 0,
             head_text: Default::default(),
             index_text: Default::default(),
@@ -2649,9 +2628,6 @@ impl Repository {
                                     repo_path.0.display()
                                 );
                                 diff_state.update(cx, |diff_state, _| {
-                                    diff_state.hunk_staging_operation_count_as_of_read =
-                                        diff_state.hunk_staging_operation_count_as_of_write;
-
                                     let has_unstaged_diff = diff_state
                                         .unstaged_diff
                                         .as_ref()
@@ -3494,7 +3470,7 @@ impl Repository {
         &mut self,
         path: RepoPath,
         content: Option<String>,
-        hunk_staging_operation_count: usize,
+        hunk_staging_operation_count: Option<usize>,
         cx: &mut Context<Self>,
     ) -> oneshot::Receiver<anyhow::Result<()>> {
         let id = self.id;
@@ -3528,22 +3504,26 @@ impl Repository {
                 }
                 log::debug!("finish updating index text for buffer {}", path.display());
 
-                let project_path = this
-                    .read_with(&cx, |this, cx| this.repo_path_to_project_path(&path, cx))
-                    .ok()
-                    .flatten();
-                git_store.update(&mut cx, |git_store, cx| {
-                    let buffer_id = git_store
-                        .buffer_store
-                        .read(cx)
-                        .buffer_id_for_project_path(&project_path?)?;
-                    let diff_state = git_store.diffs.get(buffer_id)?;
-                    diff_state.update(cx, |diff_state, _| {
-                        diff_state.hunk_staging_operation_count_as_of_write =
-                            hunk_staging_operation_count;
-                    });
-                    Some(())
-                })?;
+                if let Some(hunk_staging_operation_count) = hunk_staging_operation_count {
+                    let project_path = this
+                        .read_with(&cx, |this, cx| this.repo_path_to_project_path(&path, cx))
+                        .ok()
+                        .flatten();
+                    git_store.update(&mut cx, |git_store, cx| {
+                        let buffer_id = git_store
+                            .buffer_store
+                            .read(cx)
+                            .get_by_path(&project_path?, cx)?
+                            .read(cx)
+                            .remote_id();
+                        let diff_state = git_store.diffs.get(&buffer_id)?;
+                        diff_state.update(cx, |diff_state, _| {
+                            diff_state.hunk_staging_operation_count_as_of_write =
+                                hunk_staging_operation_count;
+                        });
+                        Some(())
+                    })?;
+                }
                 Ok(())
             },
         )

crates/project/src/project_tests.rs 🔗

@@ -6967,7 +6967,7 @@ async fn test_staging_hunks_with_delayed_fs_event(cx: &mut gpui::TestAppContext)
     });
 }
 
-#[gpui::test]
+#[gpui::test(iterations = 25)]
 async fn test_staging_random_hunks(
     mut rng: StdRng,
     executor: BackgroundExecutor,