Save buffers after restoring hunks in the project diff (#25620)
This PR fixes a bug where using the project diff editor to restore hunks from a file that's not open in its own buffer would cause those reverts to be lost once the project diff drops its excerpts for that file. The fix is to save the buffers after restoring them but before the excerpts are (potentially) dropped. This is done for the project diff editor only. If we fail to save the affected files, we add their buffers to the active workspace, so that the reverted contents are preserved and the user can try again to save them. - [x] Get it working - [x] Test - [ ] ~~Clean up boolean soup~~ Co-authored-by: Max <max@zed.dev> Release Notes: - N/A
This commit is contained in:
parent
add7ae8052
commit
7a34dd9888
10 changed files with 195 additions and 19 deletions
|
@ -47,6 +47,14 @@ zed_actions.workspace = true
|
|||
[target.'cfg(windows)'.dependencies]
|
||||
windows.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
editor = { workspace = true, features = ["test-support"] }
|
||||
gpui = { workspace = true, features = ["test-support"] }
|
||||
project = { workspace = true, features = ["test-support"] }
|
||||
settings = { workspace = true, features = ["test-support"] }
|
||||
workspace = { workspace = true, features = ["test-support"] }
|
||||
unindent.workspace = true
|
||||
|
||||
[features]
|
||||
default = []
|
||||
test-support = ["multi_buffer/test-support"]
|
||||
|
|
|
@ -693,7 +693,7 @@ impl GitPanel {
|
|||
self.workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
workspace
|
||||
.open_path_preview(path, None, false, false, window, cx)
|
||||
.open_path_preview(path, None, false, false, true, window, cx)
|
||||
.detach_and_prompt_err("Failed to open file", window, cx, |e, _, _| {
|
||||
Some(format!("{e}"))
|
||||
});
|
||||
|
|
|
@ -47,6 +47,7 @@ pub struct ProjectDiff {
|
|||
_subscription: Subscription,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DiffBuffer {
|
||||
path_key: PathKey,
|
||||
buffer: Entity<Buffer>,
|
||||
|
@ -923,3 +924,93 @@ impl Render for ProjectDiffToolbar {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use collections::HashMap;
|
||||
use editor::test::editor_test_context::assert_state_with_diff;
|
||||
use git::status::{StatusCode, TrackedStatus};
|
||||
use gpui::TestAppContext;
|
||||
use project::FakeFs;
|
||||
use serde_json::json;
|
||||
use settings::SettingsStore;
|
||||
use unindent::Unindent as _;
|
||||
use util::path;
|
||||
|
||||
use super::*;
|
||||
|
||||
fn init_test(cx: &mut TestAppContext) {
|
||||
cx.update(|cx| {
|
||||
let store = SettingsStore::test(cx);
|
||||
cx.set_global(store);
|
||||
theme::init(theme::LoadThemes::JustBase, cx);
|
||||
language::init(cx);
|
||||
Project::init_settings(cx);
|
||||
workspace::init_settings(cx);
|
||||
editor::init(cx);
|
||||
crate::init(cx);
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_save_after_restore(cx: &mut TestAppContext) {
|
||||
init_test(cx);
|
||||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_tree(
|
||||
path!("/project"),
|
||||
json!({
|
||||
".git": {},
|
||||
"foo": "FOO\n",
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
let project = Project::test(fs.clone(), [path!("/project").as_ref()], cx).await;
|
||||
let (workspace, cx) =
|
||||
cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
|
||||
let diff = cx.new_window_entity(|window, cx| {
|
||||
ProjectDiff::new(project.clone(), workspace, window, cx)
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
fs.set_head_for_repo(
|
||||
path!("/project/.git").as_ref(),
|
||||
&[("foo".into(), "foo\n".into())],
|
||||
);
|
||||
fs.with_git_state(path!("/project/.git").as_ref(), true, |state| {
|
||||
state.statuses = HashMap::from_iter([(
|
||||
"foo".into(),
|
||||
TrackedStatus {
|
||||
index_status: StatusCode::Unmodified,
|
||||
worktree_status: StatusCode::Modified,
|
||||
}
|
||||
.into(),
|
||||
)]);
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
let editor = diff.update(cx, |diff, _| diff.editor.clone());
|
||||
assert_state_with_diff(
|
||||
&editor,
|
||||
cx,
|
||||
&"
|
||||
- foo
|
||||
+ FOO
|
||||
ˇ"
|
||||
.unindent(),
|
||||
);
|
||||
|
||||
editor.update_in(cx, |editor, window, cx| {
|
||||
editor.restore_file(&Default::default(), window, cx);
|
||||
});
|
||||
fs.with_git_state(path!("/project/.git").as_ref(), true, |state| {
|
||||
state.statuses = HashMap::default();
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
assert_state_with_diff(&editor, cx, &"ˇ".unindent());
|
||||
|
||||
let text = String::from_utf8(fs.read_file_sync("/project/foo").unwrap()).unwrap();
|
||||
assert_eq!(text, "foo\n");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue