Git actions v2 (#25197)

Closes #ISSUE

Release Notes:

- Rename `editor::RevertSelectedHunks` and `editor::RevertFile` to
`git::Restore` and `git::RestoreFile` for consistency with git
This commit is contained in:
Conrad Irwin 2025-02-19 21:22:31 -07:00 committed by GitHub
parent e3836712d6
commit d0f7dede79
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 195 additions and 1688 deletions

View file

@ -116,7 +116,7 @@
// "alt-v": ["editor::MovePageUp", { "center_cursor": true }], // "alt-v": ["editor::MovePageUp", { "center_cursor": true }],
"ctrl-alt-space": "editor::ShowCharacterPalette", "ctrl-alt-space": "editor::ShowCharacterPalette",
"ctrl-;": "editor::ToggleLineNumbers", "ctrl-;": "editor::ToggleLineNumbers",
"ctrl-k ctrl-r": "editor::RevertSelectedHunks", "ctrl-k ctrl-r": "git::Restore",
"ctrl-'": "editor::ToggleSelectedDiffHunks", "ctrl-'": "editor::ToggleSelectedDiffHunks",
"ctrl-\"": "editor::ExpandAllHunkDiffs", "ctrl-\"": "editor::ExpandAllHunkDiffs",
"ctrl-i": "editor::ShowSignatureHelp", "ctrl-i": "editor::ShowSignatureHelp",

View file

@ -126,7 +126,10 @@
"ctrl-shift-v": ["editor::MovePageUp", { "center_cursor": true }], "ctrl-shift-v": ["editor::MovePageUp", { "center_cursor": true }],
"ctrl-cmd-space": "editor::ShowCharacterPalette", "ctrl-cmd-space": "editor::ShowCharacterPalette",
"cmd-;": "editor::ToggleLineNumbers", "cmd-;": "editor::ToggleLineNumbers",
"cmd-alt-z": "editor::RevertSelectedHunks", "cmd-alt-z": "git::Restore",
"cmd-alt-y": "git::ToggleStaged",
"cmd-y": "git::StageAndNext",
"cmd-shift-y": "git::UnstageAndNext",
"cmd-'": "editor::ToggleSelectedDiffHunks", "cmd-'": "editor::ToggleSelectedDiffHunks",
"cmd-\"": "editor::ExpandAllHunkDiffs", "cmd-\"": "editor::ExpandAllHunkDiffs",
"cmd-alt-g b": "editor::ToggleGitBlame", "cmd-alt-g b": "editor::ToggleGitBlame",

View file

@ -44,7 +44,7 @@
"shift-f2": "editor::GoToPrevDiagnostic", "shift-f2": "editor::GoToPrevDiagnostic",
"ctrl-alt-shift-down": "editor::GoToHunk", "ctrl-alt-shift-down": "editor::GoToHunk",
"ctrl-alt-shift-up": "editor::GoToPrevHunk", "ctrl-alt-shift-up": "editor::GoToPrevHunk",
"ctrl-alt-z": "editor::RevertSelectedHunks", "ctrl-alt-z": "git::Restore",
"ctrl-home": "editor::MoveToBeginning", "ctrl-home": "editor::MoveToBeginning",
"ctrl-end": "editor::MoveToEnd", "ctrl-end": "editor::MoveToEnd",
"ctrl-shift-home": "editor::SelectToBeginning", "ctrl-shift-home": "editor::SelectToBeginning",

View file

@ -446,7 +446,7 @@
"d": "vim::CurrentLine", "d": "vim::CurrentLine",
"s": "vim::PushDeleteSurrounds", "s": "vim::PushDeleteSurrounds",
"o": "editor::ToggleSelectedDiffHunks", // "d o" "o": "editor::ToggleSelectedDiffHunks", // "d o"
"p": "editor::RevertSelectedHunks" // "d p" "p": "git::Restore" // "d p"
} }
}, },
{ {

View file

@ -357,7 +357,6 @@ gpui::actions!(
ReverseLines, ReverseLines,
RevertFile, RevertFile,
ReloadFile, ReloadFile,
RevertSelectedHunks,
Rewrap, Rewrap,
ScrollCursorBottom, ScrollCursorBottom,
ScrollCursorCenter, ScrollCursorCenter,
@ -400,7 +399,6 @@ gpui::actions!(
ToggleInlayHints, ToggleInlayHints,
ToggleEditPrediction, ToggleEditPrediction,
ToggleLineNumbers, ToggleLineNumbers,
ToggleStagedSelectedDiffHunks,
SwapSelectionEnds, SwapSelectionEnds,
SetMark, SetMark,
ToggleRelativeLineNumbers, ToggleRelativeLineNumbers,

View file

@ -73,6 +73,7 @@ use futures::{
}; };
use fuzzy::StringMatchCandidate; use fuzzy::StringMatchCandidate;
use ::git::Restore;
use code_context_menus::{ use code_context_menus::{
AvailableCodeAction, CodeActionContents, CodeActionsItem, CodeActionsMenu, CodeContextMenu, AvailableCodeAction, CodeActionContents, CodeActionsItem, CodeActionsMenu, CodeContextMenu,
CompletionsMenu, ContextMenuOrigin, CompletionsMenu, ContextMenuOrigin,
@ -7025,21 +7026,6 @@ impl Editor {
}) })
} }
pub fn revert_file(&mut self, _: &RevertFile, window: &mut Window, cx: &mut Context<Self>) {
let mut revert_changes = HashMap::default();
let snapshot = self.snapshot(window, cx);
for hunk in snapshot
.hunks_for_ranges(Some(Point::zero()..snapshot.buffer_snapshot.max_point()).into_iter())
{
self.prepare_revert_change(&mut revert_changes, &hunk, cx);
}
if !revert_changes.is_empty() {
self.transact(window, cx, |editor, window, cx| {
editor.revert(revert_changes, window, cx);
});
}
}
pub fn reload_file(&mut self, _: &ReloadFile, window: &mut Window, cx: &mut Context<Self>) { pub fn reload_file(&mut self, _: &ReloadFile, window: &mut Window, cx: &mut Context<Self>) {
let Some(project) = self.project.clone() else { let Some(project) = self.project.clone() else {
return; return;
@ -7048,27 +7034,62 @@ impl Editor {
.detach_and_notify_err(window, cx); .detach_and_notify_err(window, cx);
} }
pub fn revert_selected_hunks( pub fn restore_file(
&mut self, &mut self,
_: &RevertSelectedHunks, _: &::git::RestoreFile,
window: &mut Window, window: &mut Window,
cx: &mut Context<Self>, cx: &mut Context<Self>,
) { ) {
let selections = self.selections.all(cx).into_iter().map(|s| s.range()); let mut buffer_ids = HashSet::default();
self.revert_hunks_in_ranges(selections, window, cx); let snapshot = self.buffer().read(cx).snapshot(cx);
for selection in self.selections.all::<usize>(cx) {
buffer_ids.extend(snapshot.buffer_ids_for_range(selection.range()))
} }
fn revert_hunks_in_ranges( let buffer = self.buffer().read(cx);
let ranges = buffer_ids
.into_iter()
.flat_map(|buffer_id| buffer.excerpt_ranges_for_buffer(buffer_id, cx))
.collect::<Vec<_>>();
self.restore_hunks_in_ranges(ranges, window, cx);
}
pub fn git_restore(&mut self, _: &Restore, window: &mut Window, cx: &mut Context<Self>) {
let selections = self
.selections
.all(cx)
.into_iter()
.map(|s| s.range())
.collect();
self.restore_hunks_in_ranges(selections, window, cx);
}
fn restore_hunks_in_ranges(
&mut self, &mut self,
ranges: impl Iterator<Item = Range<Point>>, ranges: Vec<Range<Point>>,
window: &mut Window, window: &mut Window,
cx: &mut Context<Editor>, cx: &mut Context<Editor>,
) { ) {
let mut revert_changes = HashMap::default(); let mut revert_changes = HashMap::default();
let snapshot = self.snapshot(window, cx); let snapshot = self.buffer.read(cx).snapshot(cx);
for hunk in &snapshot.hunks_for_ranges(ranges) { let Some(project) = &self.project else {
self.prepare_revert_change(&mut revert_changes, &hunk, cx); return;
};
let chunk_by = self
.snapshot(window, cx)
.hunks_for_ranges(ranges.into_iter())
.into_iter()
.chunk_by(|hunk| hunk.buffer_id);
for (buffer_id, hunks) in &chunk_by {
let hunks = hunks.collect::<Vec<_>>();
for hunk in &hunks {
self.prepare_restore_change(&mut revert_changes, hunk, cx);
} }
Self::do_stage_or_unstage(project, false, buffer_id, hunks.into_iter(), &snapshot, cx);
}
drop(chunk_by);
if !revert_changes.is_empty() { if !revert_changes.is_empty() {
self.transact(window, cx, |editor, window, cx| { self.transact(window, cx, |editor, window, cx| {
editor.revert(revert_changes, window, cx); editor.revert(revert_changes, window, cx);
@ -7098,7 +7119,7 @@ impl Editor {
} }
} }
pub fn prepare_revert_change( pub fn prepare_restore_change(
&self, &self,
revert_changes: &mut HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>, revert_changes: &mut HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
hunk: &MultiBufferDiffHunk, hunk: &MultiBufferDiffHunk,
@ -12576,32 +12597,68 @@ impl Editor {
pub fn toggle_staged_selected_diff_hunks( pub fn toggle_staged_selected_diff_hunks(
&mut self, &mut self,
_: &ToggleStagedSelectedDiffHunks, _: &::git::ToggleStaged,
_window: &mut Window, _window: &mut Window,
cx: &mut Context<Self>, cx: &mut Context<Self>,
) { ) {
let snapshot = self.buffer.read(cx).snapshot(cx);
let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect(); let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
self.stage_or_unstage_diff_hunks(&ranges, cx); let stage = self.has_stageable_diff_hunks_in_ranges(&ranges, &snapshot);
self.stage_or_unstage_diff_hunks(stage, &ranges, cx);
}
pub fn stage_and_next(
&mut self,
_: &::git::StageAndNext,
window: &mut Window,
cx: &mut Context<Self>,
) {
let head = self.selections.newest_anchor().head();
self.stage_or_unstage_diff_hunks(true, &[head..head], cx);
self.go_to_next_hunk(&Default::default(), window, cx);
}
pub fn unstage_and_next(
&mut self,
_: &::git::UnstageAndNext,
window: &mut Window,
cx: &mut Context<Self>,
) {
let head = self.selections.newest_anchor().head();
self.stage_or_unstage_diff_hunks(false, &[head..head], cx);
self.go_to_next_hunk(&Default::default(), window, cx);
} }
pub fn stage_or_unstage_diff_hunks( pub fn stage_or_unstage_diff_hunks(
&mut self, &mut self,
stage: bool,
ranges: &[Range<Anchor>], ranges: &[Range<Anchor>],
cx: &mut Context<Self>, cx: &mut Context<Self>,
) { ) {
let snapshot = self.buffer.read(cx).snapshot(cx);
let Some(project) = &self.project else { let Some(project) = &self.project else {
return; return;
}; };
let snapshot = self.buffer.read(cx).snapshot(cx);
let stage = self.has_stageable_diff_hunks_in_ranges(ranges, &snapshot);
let chunk_by = self let chunk_by = self
.diff_hunks_in_ranges(&ranges, &snapshot) .diff_hunks_in_ranges(&ranges, &snapshot)
.chunk_by(|hunk| hunk.buffer_id); .chunk_by(|hunk| hunk.buffer_id);
for (buffer_id, hunks) in &chunk_by { for (buffer_id, hunks) in &chunk_by {
Self::do_stage_or_unstage(project, stage, buffer_id, hunks, &snapshot, cx);
}
}
fn do_stage_or_unstage(
project: &Entity<Project>,
stage: bool,
buffer_id: BufferId,
hunks: impl Iterator<Item = MultiBufferDiffHunk>,
snapshot: &MultiBufferSnapshot,
cx: &mut Context<Self>,
) {
let Some(buffer) = project.read(cx).buffer_for_id(buffer_id, cx) else { let Some(buffer) = project.read(cx).buffer_for_id(buffer_id, cx) else {
log::debug!("no buffer for id"); log::debug!("no buffer for id");
continue; return;
}; };
let buffer = buffer.read(cx).snapshot(); let buffer = buffer.read(cx).snapshot();
let Some((repo, path)) = project let Some((repo, path)) = project
@ -12609,33 +12666,43 @@ impl Editor {
.repository_and_path_for_buffer_id(buffer_id, cx) .repository_and_path_for_buffer_id(buffer_id, cx)
else { else {
log::debug!("no git repo for buffer id"); log::debug!("no git repo for buffer id");
continue; return;
}; };
let Some(diff) = snapshot.diff_for_buffer_id(buffer_id) else { let Some(diff) = snapshot.diff_for_buffer_id(buffer_id) else {
log::debug!("no diff for buffer id"); log::debug!("no diff for buffer id");
continue; return;
}; };
let Some(secondary_diff) = diff.secondary_diff() else { let Some(secondary_diff) = diff.secondary_diff() else {
log::debug!("no secondary diff for buffer id"); log::debug!("no secondary diff for buffer id");
continue; return;
}; };
let edits = diff.secondary_edits_for_stage_or_unstage( let edits = diff.secondary_edits_for_stage_or_unstage(
stage, stage,
hunks.map(|hunk| { 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.diff_base_byte_range.clone(), hunk.diff_base_byte_range.clone(),
hunk.secondary_diff_base_byte_range.clone(), hunk.secondary_diff_base_byte_range.clone(),
hunk.buffer_range.clone(), hunk.buffer_range.clone(),
) ))
}), }),
&buffer, &buffer,
); );
let index_base = secondary_diff.base_text().map_or_else( let Some(index_base) = secondary_diff
|| Rope::from(""), .base_text()
|snapshot| snapshot.text.as_rope().clone(), .map(|snapshot| snapshot.text.as_rope().clone())
); else {
log::debug!("no index base");
return;
};
let index_buffer = cx.new(|cx| { let index_buffer = cx.new(|cx| {
Buffer::local_normalized(index_base.clone(), text::LineEnding::default(), cx) Buffer::local_normalized(index_base.clone(), text::LineEnding::default(), cx)
}); });
@ -12657,7 +12724,6 @@ impl Editor {
let _ = repo.read(cx).set_index_text(&path, new_index_text); let _ = repo.read(cx).set_index_text(&path, new_index_text);
} }
}
pub fn expand_selected_diff_hunks(&mut self, cx: &mut Context<Self>) { pub fn expand_selected_diff_hunks(&mut self, cx: &mut Context<Self>) {
let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect(); let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();

View file

@ -12718,7 +12718,10 @@ async fn test_multibuffer_reverts(cx: &mut gpui::TestAppContext) {
multibuffer multibuffer
}); });
let (editor, cx) = cx.add_window_view(|window, cx| build_editor(multibuffer, window, cx)); let fs = FakeFs::new(cx.executor());
let project = Project::test(fs, [path!("/").as_ref()], cx).await;
let (editor, cx) = cx
.add_window_view(|window, cx| build_editor_with_project(project, multibuffer, window, cx));
editor.update_in(cx, |editor, _window, cx| { editor.update_in(cx, |editor, _window, cx| {
for (buffer, diff_base) in [ for (buffer, diff_base) in [
(buffer_1.clone(), base_text_1), (buffer_1.clone(), base_text_1),
@ -12736,7 +12739,7 @@ async fn test_multibuffer_reverts(cx: &mut gpui::TestAppContext) {
editor.update_in(cx, |editor, window, cx| { editor.update_in(cx, |editor, window, cx| {
assert_eq!(editor.text(cx), "Xaaa\nXbbb\nXccc\n\nXfff\nXggg\n\nXjjj\nXlll\nXmmm\nXnnn\n\nXqqq\nXrrr\n\nXuuu\nXvvv\nXwww\nXxxx\n\nX{{{\nX|||\n\nX\u{7f}\u{7f}\u{7f}"); assert_eq!(editor.text(cx), "Xaaa\nXbbb\nXccc\n\nXfff\nXggg\n\nXjjj\nXlll\nXmmm\nXnnn\n\nXqqq\nXrrr\n\nXuuu\nXvvv\nXwww\nXxxx\n\nX{{{\nX|||\n\nX\u{7f}\u{7f}\u{7f}");
editor.select_all(&SelectAll, window, cx); editor.select_all(&SelectAll, window, cx);
editor.revert_selected_hunks(&RevertSelectedHunks, window, cx); editor.git_restore(&Default::default(), window, cx);
}); });
cx.executor().run_until_parked(); cx.executor().run_until_parked();
@ -12762,7 +12765,7 @@ async fn test_multibuffer_reverts(cx: &mut gpui::TestAppContext) {
editor.change_selections(None, window, cx, |s| { editor.change_selections(None, window, cx, |s| {
s.select_ranges(Some(Point::new(0, 0)..Point::new(6, 0))); s.select_ranges(Some(Point::new(0, 0)..Point::new(6, 0)));
}); });
editor.revert_selected_hunks(&RevertSelectedHunks, window, cx); editor.git_restore(&Default::default(), window, cx);
}); });
// Now, when all ranges selected belong to buffer_1, the revert should succeed, // Now, when all ranges selected belong to buffer_1, the revert should succeed,
@ -14157,7 +14160,7 @@ async fn test_stage_and_unstage_added_file_hunk(
cx.assert_index_text(None); cx.assert_index_text(None);
cx.update_editor(|editor, window, cx| { cx.update_editor(|editor, window, cx| {
editor.toggle_staged_selected_diff_hunks(&ToggleStagedSelectedDiffHunks, window, cx); editor.toggle_staged_selected_diff_hunks(&Default::default(), window, cx);
}); });
executor.run_until_parked(); executor.run_until_parked();
cx.assert_index_text(Some(&working_copy.replace("ˇ", ""))); cx.assert_index_text(Some(&working_copy.replace("ˇ", "")));
@ -14171,7 +14174,7 @@ async fn test_stage_and_unstage_added_file_hunk(
); );
cx.update_editor(|editor, window, cx| { cx.update_editor(|editor, window, cx| {
editor.toggle_staged_selected_diff_hunks(&ToggleStagedSelectedDiffHunks, window, cx); editor.toggle_staged_selected_diff_hunks(&Default::default(), window, cx);
}); });
executor.run_until_parked(); executor.run_until_parked();
cx.assert_index_text(None); cx.assert_index_text(None);
@ -16103,7 +16106,7 @@ fn assert_hunk_revert(
.map(|hunk| hunk.status()) .map(|hunk| hunk.status())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
editor.revert_selected_hunks(&RevertSelectedHunks, window, cx); editor.git_restore(&Default::default(), window, cx);
reverted_hunk_statuses reverted_hunk_statuses
}); });
cx.executor().run_until_parked(); cx.executor().run_until_parked();

View file

@ -19,11 +19,10 @@ use crate::{
DocumentHighlightRead, DocumentHighlightWrite, EditDisplayMode, Editor, EditorMode, DocumentHighlightRead, DocumentHighlightWrite, EditDisplayMode, Editor, EditorMode,
EditorSettings, EditorSnapshot, EditorStyle, ExpandExcerpts, FocusedBlock, GoToHunk, EditorSettings, EditorSnapshot, EditorStyle, ExpandExcerpts, FocusedBlock, GoToHunk,
GoToPrevHunk, GutterDimensions, HalfPageDown, HalfPageUp, HandleInput, HoveredCursor, GoToPrevHunk, GutterDimensions, HalfPageDown, HalfPageUp, HandleInput, HoveredCursor,
InlineCompletion, JumpData, LineDown, LineUp, OpenExcerpts, PageDown, PageUp, Point, InlineCompletion, JumpData, LineDown, LineUp, OpenExcerpts, PageDown, PageUp, Point, RowExt,
RevertSelectedHunks, RowExt, RowRangeExt, SelectPhase, SelectedTextHighlight, Selection, RowRangeExt, SelectPhase, SelectedTextHighlight, Selection, SoftWrap, StickyHeaderExcerpt,
SoftWrap, StickyHeaderExcerpt, ToPoint, ToggleFold, COLUMNAR_SELECTION_MODIFIERS, ToPoint, ToggleFold, COLUMNAR_SELECTION_MODIFIERS, CURSORS_VISIBLE_FOR, FILE_HEADER_HEIGHT,
CURSORS_VISIBLE_FOR, FILE_HEADER_HEIGHT, GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED, MAX_LINE_LEN, GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED, MAX_LINE_LEN, MULTI_BUFFER_EXCERPT_HEADER_HEIGHT,
MULTI_BUFFER_EXCERPT_HEADER_HEIGHT,
}; };
use buffer_diff::{DiffHunkSecondaryStatus, DiffHunkStatus, DiffHunkStatusKind}; use buffer_diff::{DiffHunkSecondaryStatus, DiffHunkStatus, DiffHunkStatusKind};
use client::ParticipantIndex; use client::ParticipantIndex;
@ -418,6 +417,8 @@ impl EditorElement {
register_action(editor, window, Editor::toggle_git_blame_inline); register_action(editor, window, Editor::toggle_git_blame_inline);
register_action(editor, window, Editor::toggle_selected_diff_hunks); register_action(editor, window, Editor::toggle_selected_diff_hunks);
register_action(editor, window, Editor::toggle_staged_selected_diff_hunks); register_action(editor, window, Editor::toggle_staged_selected_diff_hunks);
register_action(editor, window, Editor::stage_and_next);
register_action(editor, window, Editor::unstage_and_next);
register_action(editor, window, Editor::expand_all_diff_hunks); register_action(editor, window, Editor::expand_all_diff_hunks);
register_action(editor, window, |editor, action, window, cx| { register_action(editor, window, |editor, action, window, cx| {
@ -491,8 +492,8 @@ impl EditorElement {
register_action(editor, window, Editor::unique_lines_case_sensitive); register_action(editor, window, Editor::unique_lines_case_sensitive);
register_action(editor, window, Editor::accept_partial_inline_completion); register_action(editor, window, Editor::accept_partial_inline_completion);
register_action(editor, window, Editor::accept_edit_prediction); register_action(editor, window, Editor::accept_edit_prediction);
register_action(editor, window, Editor::revert_file); register_action(editor, window, Editor::restore_file);
register_action(editor, window, Editor::revert_selected_hunks); register_action(editor, window, Editor::git_restore);
register_action(editor, window, Editor::apply_all_diff_hunks); register_action(editor, window, Editor::apply_all_diff_hunks);
register_action(editor, window, Editor::apply_selected_diff_hunks); register_action(editor, window, Editor::apply_selected_diff_hunks);
register_action(editor, window, Editor::open_active_item_in_terminal); register_action(editor, window, Editor::open_active_item_in_terminal);
@ -9004,8 +9005,8 @@ fn diff_hunk_controls(
let focus_handle = editor.focus_handle(cx); let focus_handle = editor.focus_handle(cx);
move |window, cx| { move |window, cx| {
Tooltip::for_action_in( Tooltip::for_action_in(
"Discard Hunk", "Restore Hunk",
&RevertSelectedHunks, &::git::Restore,
&focus_handle, &focus_handle,
window, window,
cx, cx,
@ -9018,7 +9019,7 @@ fn diff_hunk_controls(
editor.update(cx, |editor, cx| { editor.update(cx, |editor, cx| {
let snapshot = editor.snapshot(window, cx); let snapshot = editor.snapshot(window, cx);
let point = hunk_range.start.to_point(&snapshot.buffer_snapshot); let point = hunk_range.start.to_point(&snapshot.buffer_snapshot);
editor.revert_hunks_in_ranges([point..point].into_iter(), window, cx); editor.restore_hunks_in_ranges(vec![point..point], window, cx);
}); });
} }
}), }),

File diff suppressed because it is too large Load diff

View file

@ -6,6 +6,7 @@ pub mod repository;
pub mod status; pub mod status;
use anyhow::{anyhow, Context as _, Result}; use anyhow::{anyhow, Context as _, Result};
use gpui::action_with_deprecated_aliases;
use gpui::actions; use gpui::actions;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::ffi::OsStr; use std::ffi::OsStr;
@ -29,21 +30,24 @@ pub static INDEX_LOCK: LazyLock<&'static OsStr> = LazyLock::new(|| OsStr::new("i
actions!( actions!(
git, git,
[ [
// per-hunk
ToggleStaged,
StageAndNext,
UnstageAndNext,
// per-file
StageFile, StageFile,
UnstageFile, UnstageFile,
ToggleStaged, // repo-wide
// Revert actions are currently in the editor crate:
// editor::RevertFile,
// editor::RevertSelectedHunks
StageAll, StageAll,
UnstageAll, UnstageAll,
DiscardTrackedChanges, RestoreTrackedFiles,
TrashUntrackedFiles, TrashUntrackedFiles,
Uncommit, Uncommit,
Commit, Commit,
ClearCommitMessage
] ]
); );
action_with_deprecated_aliases!(git, RestoreFile, ["editor::RevertFile"]);
action_with_deprecated_aliases!(git, Restore, ["editor::RevertSelectedHunks"]);
/// The length of a Git short SHA. /// The length of a Git short SHA.
pub const SHORT_SHA_LENGTH: usize = 7; pub const SHORT_SHA_LENGTH: usize = 7;

View file

@ -13,7 +13,7 @@ use editor::{
}; };
use git::repository::{CommitDetails, ResetMode}; use git::repository::{CommitDetails, ResetMode};
use git::{repository::RepoPath, status::FileStatus, Commit, ToggleStaged}; use git::{repository::RepoPath, status::FileStatus, Commit, ToggleStaged};
use git::{DiscardTrackedChanges, StageAll, TrashUntrackedFiles, UnstageAll}; use git::{RestoreTrackedFiles, StageAll, TrashUntrackedFiles, UnstageAll};
use gpui::*; use gpui::*;
use itertools::Itertools; use itertools::Itertools;
use language::{Buffer, File}; use language::{Buffer, File};
@ -625,7 +625,7 @@ impl GitPanel {
fn revert_selected( fn revert_selected(
&mut self, &mut self,
_: &editor::actions::RevertFile, _: &git::RestoreFile,
window: &mut Window, window: &mut Window,
cx: &mut Context<Self>, cx: &mut Context<Self>,
) { ) {
@ -763,7 +763,7 @@ impl GitPanel {
fn discard_tracked_changes( fn discard_tracked_changes(
&mut self, &mut self,
_: &DiscardTrackedChanges, _: &RestoreTrackedFiles,
window: &mut Window, window: &mut Window,
cx: &mut Context<Self>, cx: &mut Context<Self>,
) { ) {
@ -2019,7 +2019,7 @@ impl GitPanel {
let context_menu = ContextMenu::build(window, cx, |context_menu, _, _| { let context_menu = ContextMenu::build(window, cx, |context_menu, _, _| {
context_menu context_menu
.action("Stage File", ToggleStaged.boxed_clone()) .action("Stage File", ToggleStaged.boxed_clone())
.action(revert_title, editor::actions::RevertFile.boxed_clone()) .action(revert_title, git::RestoreFile.boxed_clone())
.separator() .separator()
.action("Open Diff", Confirm.boxed_clone()) .action("Open Diff", Confirm.boxed_clone())
.action("Open File", SecondaryConfirm.boxed_clone()) .action("Open File", SecondaryConfirm.boxed_clone())
@ -2040,10 +2040,7 @@ impl GitPanel {
.action("Unstage All", UnstageAll.boxed_clone()) .action("Unstage All", UnstageAll.boxed_clone())
.action("Open Diff", project_diff::Diff.boxed_clone()) .action("Open Diff", project_diff::Diff.boxed_clone())
.separator() .separator()
.action( .action("Discard Tracked Changes", RestoreTrackedFiles.boxed_clone())
"Discard Tracked Changes",
DiscardTrackedChanges.boxed_clone(),
)
.action("Trash Untracked Files", TrashUntrackedFiles.boxed_clone()) .action("Trash Untracked Files", TrashUntrackedFiles.boxed_clone())
}); });
self.set_context_menu(context_menu, position, window, cx); self.set_context_menu(context_menu, position, window, cx);

View file

@ -841,7 +841,7 @@ fn generate_commands(_: &App) -> Vec<VimCommand> {
.range(act_on_range), .range(act_on_range),
VimCommand::new(("dif", "fupdate"), editor::actions::ToggleSelectedDiffHunks) VimCommand::new(("dif", "fupdate"), editor::actions::ToggleSelectedDiffHunks)
.range(act_on_range), .range(act_on_range),
VimCommand::new(("rev", "ert"), editor::actions::RevertSelectedHunks).range(act_on_range), VimCommand::str(("rev", "ert"), "git::Restore").range(act_on_range),
VimCommand::new(("d", "elete"), VisualDeleteLine).range(select_range), VimCommand::new(("d", "elete"), VisualDeleteLine).range(select_range),
VimCommand::new(("y", "ank"), gpui::NoAction).range(|_, range| { VimCommand::new(("y", "ank"), gpui::NoAction).range(|_, range| {
Some( Some(