From 5dbf68ddc480015b9f55a5c96d19599e915f6a26 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 22 Oct 2024 14:10:11 -0400 Subject: [PATCH] editor: Save base buffers when applying changes from their branches (#19562) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR makes it so that when we apply changes within a branch buffer—currently just the edits buffer—we save the underlying buffer. This also fixes an issue where new files created via edits were not properly flushed to disk. Release Notes: - N/A --------- Co-authored-by: Max --- crates/editor/src/editor.rs | 22 -------- crates/editor/src/hunk_diff.rs | 55 +++++++++++++++++--- crates/editor/src/items.rs | 4 ++ crates/editor/src/proposed_changes_editor.rs | 16 +++++- 4 files changed, 67 insertions(+), 30 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index e1280850a2..d3e2134eac 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -6260,28 +6260,6 @@ impl Editor { } } - fn apply_selected_diff_hunks(&mut self, _: &ApplyDiffHunk, cx: &mut ViewContext) { - let snapshot = self.buffer.read(cx).snapshot(cx); - let hunks = hunks_for_selections(&snapshot, &self.selections.disjoint_anchors()); - let mut ranges_by_buffer = HashMap::default(); - self.transact(cx, |editor, cx| { - for hunk in hunks { - if let Some(buffer) = editor.buffer.read(cx).buffer(hunk.buffer_id) { - ranges_by_buffer - .entry(buffer.clone()) - .or_insert_with(Vec::new) - .push(hunk.buffer_range.to_offset(buffer.read(cx))); - } - } - - for (buffer, ranges) in ranges_by_buffer { - buffer.update(cx, |buffer, cx| { - buffer.merge_into_base(ranges, cx); - }); - } - }); - } - pub fn open_active_item_in_terminal(&mut self, _: &OpenInTerminal, cx: &mut ViewContext) { if let Some(working_directory) = self.active_excerpt(cx).and_then(|(_, buffer, _)| { let project_path = buffer.read(cx).project_path(cx)?; diff --git a/crates/editor/src/hunk_diff.rs b/crates/editor/src/hunk_diff.rs index 60931f3380..1b9408df7e 100644 --- a/crates/editor/src/hunk_diff.rs +++ b/crates/editor/src/hunk_diff.rs @@ -7,11 +7,13 @@ use multi_buffer::{ MultiBufferSnapshot, ToPoint, }; use std::{ops::Range, sync::Arc}; +use text::OffsetRangeExt; use ui::{ prelude::*, ActiveTheme, ContextMenu, IconButtonShape, InteractiveElement, IntoElement, ParentElement, PopoverMenu, Styled, Tooltip, ViewContext, VisualContext, }; use util::RangeExt; +use workspace::Item; use crate::{ editor_settings::CurrentLineHighlight, hunk_status, hunks_for_selections, ApplyDiffHunk, @@ -327,7 +329,7 @@ impl Editor { Some(()) } - fn apply_changes_in_range( + fn apply_diff_hunks_in_range( &mut self, range: Range, cx: &mut ViewContext<'_, Editor>, @@ -343,16 +345,54 @@ impl Editor { branch_buffer.merge_into_base(vec![range], cx); }); + if let Some(project) = self.project.clone() { + self.save(true, project, cx).detach_and_log_err(cx); + } + None } - pub(crate) fn apply_all_changes(&self, cx: &mut ViewContext) { + pub(crate) fn apply_all_diff_hunks(&mut self, cx: &mut ViewContext) { let buffers = self.buffer.read(cx).all_buffers(); for branch_buffer in buffers { branch_buffer.update(cx, |branch_buffer, cx| { branch_buffer.merge_into_base(Vec::new(), cx); }); } + + if let Some(project) = self.project.clone() { + self.save(true, project, cx).detach_and_log_err(cx); + } + } + + pub(crate) fn apply_selected_diff_hunks( + &mut self, + _: &ApplyDiffHunk, + cx: &mut ViewContext, + ) { + let snapshot = self.buffer.read(cx).snapshot(cx); + let hunks = hunks_for_selections(&snapshot, &self.selections.disjoint_anchors()); + let mut ranges_by_buffer = HashMap::default(); + self.transact(cx, |editor, cx| { + for hunk in hunks { + if let Some(buffer) = editor.buffer.read(cx).buffer(hunk.buffer_id) { + ranges_by_buffer + .entry(buffer.clone()) + .or_insert_with(Vec::new) + .push(hunk.buffer_range.to_offset(buffer.read(cx))); + } + } + + for (buffer, ranges) in ranges_by_buffer { + buffer.update(cx, |buffer, cx| { + buffer.merge_into_base(ranges, cx); + }); + } + }); + + if let Some(project) = self.project.clone() { + self.save(true, project, cx).detach_and_log_err(cx); + } } fn hunk_header_block( @@ -548,11 +588,12 @@ impl Editor { let hunk = hunk.clone(); move |_event, cx| { editor.update(cx, |editor, cx| { - editor.apply_changes_in_range( - hunk.multi_buffer_range - .clone(), - cx, - ); + editor + .apply_diff_hunks_in_range( + hunk.multi_buffer_range + .clone(), + cx, + ); }); } }), diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index e84476fb08..2574aa00a4 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -720,6 +720,10 @@ impl Item for Editor { ) -> Task> { self.report_editor_event("save", None, cx); let buffers = self.buffer().clone().read(cx).all_buffers(); + let buffers = buffers + .into_iter() + .map(|handle| handle.read(cx).diff_base_buffer().unwrap_or(handle.clone())) + .collect::>(); cx.spawn(|this, mut cx| async move { if format { this.update(&mut cx, |editor, cx| { diff --git a/crates/editor/src/proposed_changes_editor.rs b/crates/editor/src/proposed_changes_editor.rs index 2c99b9d277..ae9f251a1f 100644 --- a/crates/editor/src/proposed_changes_editor.rs +++ b/crates/editor/src/proposed_changes_editor.rs @@ -298,6 +298,20 @@ impl Item for ProposedChangesEditor { Item::set_nav_history(editor, nav_history, cx) }); } + + fn can_save(&self, cx: &AppContext) -> bool { + self.editor.read(cx).can_save(cx) + } + + fn save( + &mut self, + format: bool, + project: Model, + cx: &mut ViewContext, + ) -> Task> { + self.editor + .update(cx, |editor, cx| Item::save(editor, format, project, cx)) + } } impl ProposedChangesEditorToolbar { @@ -323,7 +337,7 @@ impl Render for ProposedChangesEditorToolbar { if let Some(editor) = &editor { editor.update(cx, |editor, cx| { editor.editor.update(cx, |editor, cx| { - editor.apply_all_changes(cx); + editor.apply_all_diff_hunks(cx); }) }); }