History

Git: Fix hunks being skipped when staging too quickly (#27552)

Release Notes: - Git: Fix hunks being skipped when staging too quickly. ---------

João Marcos committed 1 year ago

Commit 47b94e51 parent 29e2e132 files · +83 −53Browse files

Showing the changes to crates/buffer_diff/src/buffer_diff.rs (1 of 2 files). Show all

Unified · Split

crates/buffer_diff/src/buffer_diff.rs+34−44
@@ -187,13 +187,13 @@ impl BufferDiffSnapshot { · 186 unmodified lines
187impl BufferDiffInner {187impl BufferDiffInner {
188 /// Returns the new index text and new pending hunks.188 /// Returns the new index text and new pending hunks.
189 fn stage_or_unstage_hunks_impl(189 fn stage_or_unstage_hunks_impl(
190 &self,190 &mut self,
191 unstaged_diff: &Self,191 unstaged_diff: &Self,
192 stage: bool,192 stage: bool,
193 hunks: &[DiffHunk],193 hunks: &[DiffHunk],
194 buffer: &text::BufferSnapshot,194 buffer: &text::BufferSnapshot,
195 file_exists: bool,195 file_exists: bool,
196 ) -> (Option<Rope>, SumTree<PendingHunk>) {196 ) -> Option<Rope> {
197 let head_text = self197 let head_text = self
198 .base_text_exists198 .base_text_exists
199 .then(|| self.base_text.as_rope().clone());199 .then(|| self.base_text.as_rope().clone());
@@ -206,7 +206,7 @@ impl BufferDiffInner { · 6 unmodified lines
206 let (index_text, head_text) = match (index_text, head_text) {206 let (index_text, head_text) = match (index_text, head_text) {
207 (Some(index_text), Some(head_text)) if file_exists || !stage => (index_text, head_text),207 (Some(index_text), Some(head_text)) if file_exists || !stage => (index_text, head_text),
208 (index_text, head_text) => {208 (index_text, head_text) => {
209 let (rope, new_status) = if stage {209 let (new_index_text, new_status) = if stage {
210 log::debug!("stage all");210 log::debug!("stage all");
211 (211 (
212 file_exists.then(|| buffer.as_rope().clone()),212 file_exists.then(|| buffer.as_rope().clone()),
@@ -226,15 +226,13 @@ impl BufferDiffInner { · 13 unmodified lines
226 buffer_version: buffer.version().clone(),226 buffer_version: buffer.version().clone(),
227 new_status,227 new_status,
228 };228 };
229 let tree = SumTree::from_item(hunk, buffer);229 self.pending_hunks = SumTree::from_item(hunk, buffer);
230 return (rope, tree);230 return new_index_text;
231 }231 }
232 };232 };
233 233
234 let mut pending_hunks = SumTree::new(buffer);234 let mut pending_hunks = SumTree::new(buffer);
235 let mut old_pending_hunks = unstaged_diff235 let mut old_pending_hunks = self.pending_hunks.cursor::<DiffHunkSummary>(buffer);
236 .pending_hunks
237 .cursor::<DiffHunkSummary>(buffer);
238 236
239 // first, merge new hunks into pending_hunks237 // first, merge new hunks into pending_hunks
240 for DiffHunk {238 for DiffHunk {
@@ -366,6 +364,8 @@ impl BufferDiffInner { · 125 unmodified lines
366 edits.push((index_byte_range, replacement_text));364 edits.push((index_byte_range, replacement_text));
367 }365 }
368 drop(pending_hunks_iter);366 drop(pending_hunks_iter);
367 drop(old_pending_hunks);
368 self.pending_hunks = pending_hunks;
369 369
370 #[cfg(debug_assertions)] // invariants: non-overlapping and sorted370 #[cfg(debug_assertions)] // invariants: non-overlapping and sorted
371 {371 {
@@ -384,7 +384,7 @@ impl BufferDiffInner { · 12 unmodified lines
384 new_index_text.push(&replacement_text);384 new_index_text.push(&replacement_text);
385 }385 }
386 new_index_text.append(index_cursor.suffix());386 new_index_text.append(index_cursor.suffix());
387 (Some(new_index_text), pending_hunks)387 Some(new_index_text)
388 }388 }
389 389
390 fn hunks_intersecting_range<'a>(390 fn hunks_intersecting_range<'a>(
@@ -421,15 +421,14 @@ impl BufferDiffInner { · 30 unmodified lines
421 ]421 ]
422 });422 });
423 423
424 let mut pending_hunks_cursor = self.pending_hunks.cursor::<DiffHunkSummary>(buffer);
425 pending_hunks_cursor.next(buffer);
426
424 let mut secondary_cursor = None;427 let mut secondary_cursor = None;
425 let mut pending_hunks_cursor = None;
426 if let Some(secondary) = secondary.as_ref() {428 if let Some(secondary) = secondary.as_ref() {
427 let mut cursor = secondary.hunks.cursor::<DiffHunkSummary>(buffer);429 let mut cursor = secondary.hunks.cursor::<DiffHunkSummary>(buffer);
428 cursor.next(buffer);430 cursor.next(buffer);
429 secondary_cursor = Some(cursor);431 secondary_cursor = Some(cursor);
430 let mut cursor = secondary.pending_hunks.cursor::<DiffHunkSummary>(buffer);
431 cursor.next(buffer);
432 pending_hunks_cursor = Some(cursor);
433 }432 }
434 433
435 let max_point = buffer.max_point();434 let max_point = buffer.max_point();
@@ -451,29 +450,27 @@ impl BufferDiffInner { · 15 unmodified lines
451 let mut secondary_status = DiffHunkSecondaryStatus::NoSecondaryHunk;450 let mut secondary_status = DiffHunkSecondaryStatus::NoSecondaryHunk;
452 451
453 let mut has_pending = false;452 let mut has_pending = false;
454 if let Some(pending_cursor) = pending_hunks_cursor.as_mut() {453 if start_anchor
455 if start_anchor454 .cmp(&pending_hunks_cursor.start().buffer_range.start, buffer)
456 .cmp(&pending_cursor.start().buffer_range.start, buffer)455 .is_gt()
457 .is_gt()456 {
458 {457 pending_hunks_cursor.seek_forward(&start_anchor, Bias::Left, buffer);
459 pending_cursor.seek_forward(&start_anchor, Bias::Left, buffer);458 }
460 }
461 459
462 if let Some(pending_hunk) = pending_cursor.item() {460 if let Some(pending_hunk) = pending_hunks_cursor.item() {
463 let mut pending_range = pending_hunk.buffer_range.to_point(buffer);461 let mut pending_range = pending_hunk.buffer_range.to_point(buffer);
464 if pending_range.end.column > 0 {462 if pending_range.end.column > 0 {
465 pending_range.end.row += 1;463 pending_range.end.row += 1;
466 pending_range.end.column = 0;464 pending_range.end.column = 0;
467 }465 }
468 466
469 if pending_range == (start_point..end_point) {467 if pending_range == (start_point..end_point) {
470 if !buffer.has_edits_since_in_range(468 if !buffer.has_edits_since_in_range(
471 &pending_hunk.buffer_version,469 &pending_hunk.buffer_version,
472 start_anchor..end_anchor,470 start_anchor..end_anchor,
473 ) {471 ) {
474 has_pending = true;472 has_pending = true;
475 secondary_status = pending_hunk.new_status;473 secondary_status = pending_hunk.new_status;
476 }
477 }474 }
478 }475 }
479 }476 }
@@ -852,10 +849,8 @@ impl BufferDiff { · 372 unmodified lines
852 }849 }
853 850
854 pub fn clear_pending_hunks(&mut self, cx: &mut Context<Self>) {851 pub fn clear_pending_hunks(&mut self, cx: &mut Context<Self>) {
855 if let Some(secondary_diff) = &self.secondary_diff {852 if self.secondary_diff.is_some() {
856 secondary_diff.update(cx, |diff, _| {853 self.inner.pending_hunks = SumTree::from_summary(DiffHunkSummary::default());
857 diff.inner.pending_hunks = SumTree::from_summary(DiffHunkSummary::default());
858 });
859 cx.emit(BufferDiffEvent::DiffChanged {854 cx.emit(BufferDiffEvent::DiffChanged {
860 changed_range: Some(Anchor::MIN..Anchor::MAX),855 changed_range: Some(Anchor::MIN..Anchor::MAX),
861 });856 });
@@ -870,7 +865,7 @@ impl BufferDiff { · 8 unmodified lines
870 file_exists: bool,865 file_exists: bool,
871 cx: &mut Context<Self>,866 cx: &mut Context<Self>,
872 ) -> Option<Rope> {867 ) -> Option<Rope> {
873 let (new_index_text, new_pending_hunks) = self.inner.stage_or_unstage_hunks_impl(868 let new_index_text = self.inner.stage_or_unstage_hunks_impl(
874 &self.secondary_diff.as_ref()?.read(cx).inner,869 &self.secondary_diff.as_ref()?.read(cx).inner,
875 stage,870 stage,
876 &hunks,871 &hunks,
@@ -878,11 +873,6 @@ impl BufferDiff { · 1 unmodified line
878 file_exists,873 file_exists,
879 );874 );
880 875
881 if let Some(unstaged_diff) = &self.secondary_diff {
882 unstaged_diff.update(cx, |diff, _| {
883 diff.inner.pending_hunks = new_pending_hunks;
884 });
885 }
886 cx.emit(BufferDiffEvent::HunksStagedOrUnstaged(876 cx.emit(BufferDiffEvent::HunksStagedOrUnstaged(
887 new_index_text.clone(),877 new_index_text.clone(),
888 ));878 ));