@@ -184,17 +184,31 @@ impl BufferDiffSnapshot {
cx: &mut App,
) -> Option<Rope> {
let secondary_diff = self.secondary_diff()?;
- let index_base = if let Some(index_base) = secondary_diff.base_text() {
- index_base.text.as_rope().clone()
- } else if stage {
- Rope::from("")
- } else {
- return None;
+ let head_text = self.base_text().map(|text| text.as_rope().clone());
+ let index_text = secondary_diff
+ .base_text()
+ .map(|text| text.as_rope().clone());
+ let (index_text, head_text) = match (index_text, head_text) {
+ (Some(index_text), Some(head_text)) => (index_text, head_text),
+ // file is deleted in both index and head
+ (None, None) => return None,
+ // file is deleted in index
+ (None, Some(head_text)) => {
+ return if stage {
+ Some(buffer.as_rope().clone())
+ } else {
+ Some(head_text)
+ }
+ }
+ // file exists in the index, but is deleted in head
+ (Some(_), None) => {
+ return if stage {
+ Some(buffer.as_rope().clone())
+ } else {
+ None
+ }
+ }
};
- let head_base = self.base_text().map_or_else(
- || Rope::from(""),
- |snapshot| snapshot.text.as_rope().clone(),
- );
let mut secondary_cursor = secondary_diff.inner.hunks.cursor::<DiffHunkSummary>(buffer);
secondary_cursor.next(buffer);
@@ -251,7 +265,7 @@ impl BufferDiffSnapshot {
.collect::<String>()
} else {
log::debug!("unstaging");
- head_base
+ head_text
.chunks_in_range(diff_base_byte_range.clone())
.collect::<String>()
};
@@ -259,7 +273,7 @@ impl BufferDiffSnapshot {
}
let buffer = cx.new(|cx| {
- language::Buffer::local_normalized(index_base, text::LineEnding::default(), cx)
+ language::Buffer::local_normalized(index_text, text::LineEnding::default(), cx)
});
let new_text = buffer.update(cx, |buffer, cx| {
buffer.edit(edits, None, cx);
@@ -102,9 +102,9 @@ use language::{
self, all_language_settings, language_settings, InlayHintSettings, RewrapBehavior,
},
point_from_lsp, text_diff_with_options, AutoindentMode, BracketMatch, BracketPair, Buffer,
- Capability, CharKind, CodeLabel, CursorShape, Diagnostic, DiffOptions, DiskState,
- EditPredictionsMode, EditPreview, HighlightedText, IndentKind, IndentSize, Language,
- OffsetRangeExt, Point, Selection, SelectionGoal, TextObject, TransactionId, TreeSitterOptions,
+ Capability, CharKind, CodeLabel, CursorShape, Diagnostic, DiffOptions, EditPredictionsMode,
+ EditPreview, HighlightedText, IndentKind, IndentSize, Language, OffsetRangeExt, Point,
+ Selection, SelectionGoal, TextObject, TransactionId, TreeSitterOptions,
};
use language::{point_to_lsp, BufferRow, CharClassifier, Runnable, RunnableRange};
use linked_editing_ranges::refresh_linked_ranges;
@@ -13483,13 +13483,16 @@ impl Editor {
buffer_id: BufferId,
hunks: impl Iterator<Item = MultiBufferDiffHunk>,
snapshot: &MultiBufferSnapshot,
- cx: &mut Context<Self>,
+ cx: &mut App,
) {
let Some(buffer) = project.read(cx).buffer_for_id(buffer_id, cx) else {
log::debug!("no buffer for id");
return;
};
let buffer_snapshot = buffer.read(cx).snapshot();
+ let file_exists = buffer_snapshot
+ .file()
+ .is_some_and(|file| file.disk_state().exists());
let Some((repo, path)) = project
.read(cx)
.repository_and_path_for_buffer_id(buffer_id, cx)
@@ -13502,40 +13505,33 @@ impl Editor {
return;
};
- let Some(new_index_text) = diff.new_secondary_text_for_stage_or_unstage(
- stage,
- hunks.filter_map(|hunk| {
- if stage && hunk.secondary_status == DiffHunkSecondaryStatus::None {
- return None;
- } else if !stage
- && hunk.secondary_status == DiffHunkSecondaryStatus::HasSecondaryHunk
- {
- return None;
- }
- Some((hunk.buffer_range.clone(), hunk.diff_base_byte_range.clone()))
- }),
- &buffer_snapshot,
- cx,
- ) else {
- log::debug!("missing secondary diff or index text");
- return;
- };
- let new_index_text = if new_index_text.is_empty()
- && !stage
- && (diff.is_single_insertion
- || buffer_snapshot
- .file()
- .map_or(false, |file| file.disk_state() == DiskState::New))
- {
+ let new_index_text = if !stage && diff.is_single_insertion || stage && !file_exists {
log::debug!("removing from index");
None
} else {
- Some(new_index_text)
+ diff.new_secondary_text_for_stage_or_unstage(
+ stage,
+ hunks.filter_map(|hunk| {
+ if stage && hunk.secondary_status == DiffHunkSecondaryStatus::None {
+ return None;
+ } else if !stage
+ && hunk.secondary_status == DiffHunkSecondaryStatus::HasSecondaryHunk
+ {
+ return None;
+ }
+ Some((hunk.buffer_range.clone(), hunk.diff_base_byte_range.clone()))
+ }),
+ &buffer_snapshot,
+ cx,
+ )
};
- let buffer_store = project.read(cx).buffer_store().clone();
- buffer_store
- .update(cx, |buffer_store, cx| buffer_store.save_buffer(buffer, cx))
- .detach_and_log_err(cx);
+
+ if file_exists {
+ let buffer_store = project.read(cx).buffer_store().clone();
+ buffer_store
+ .update(cx, |buffer_store, cx| buffer_store.save_buffer(buffer, cx))
+ .detach_and_log_err(cx);
+ }
cx.background_spawn(
repo.read(cx)
@@ -1071,7 +1071,13 @@ impl Repository {
};
let project_path = (self.worktree_id, path).into();
if let Some(buffer) = buffer_store.get_by_path(&project_path, cx) {
- save_futures.push(buffer_store.save_buffer(buffer, cx));
+ if buffer
+ .read(cx)
+ .file()
+ .map_or(false, |file| file.disk_state().exists())
+ {
+ save_futures.push(buffer_store.save_buffer(buffer, cx));
+ }
}
}
})
@@ -1110,7 +1116,13 @@ impl Repository {
};
let project_path = (self.worktree_id, path).into();
if let Some(buffer) = buffer_store.get_by_path(&project_path, cx) {
- save_futures.push(buffer_store.save_buffer(buffer, cx));
+ if buffer
+ .read(cx)
+ .file()
+ .map_or(false, |file| file.disk_state().exists())
+ {
+ save_futures.push(buffer_store.save_buffer(buffer, cx));
+ }
}
}
})