Fix staging/unstaging hunks remotely (#28560)

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
This commit is contained in:
Max Brunsfeld 2025-04-10 21:31:43 -07:00 committed by GitHub
parent ad39d3226f
commit 353ae2335b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 29 additions and 49 deletions

View file

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

View file

@ -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( async fn test_staging_random_hunks(
mut rng: StdRng, mut rng: StdRng,
executor: BackgroundExecutor, executor: BackgroundExecutor,