Add branch rename action to Git panel (#38273)
Reopening #35136, cc @launay12u Release Notes: - git: added `git: rename branch` action to rename a branch (`git branch -m`) --------- Co-authored-by: Guillaume Launay <guillaume.launay@paylead.fr> Co-authored-by: Peter Tripp <petertripp@gmail.com>
This commit is contained in:
co-authored by
Guillaume Launay
Peter Tripp
parent
df50b5c14a
commit
439d31e2d4
+130
-3
@@ -4,20 +4,28 @@ use ::settings::Settings;
|
||||
use command_palette_hooks::CommandPaletteFilter;
|
||||
use commit_modal::CommitModal;
|
||||
use editor::{Editor, actions::DiffClipboardWithSelectionData};
|
||||
use ui::{
|
||||
Headline, HeadlineSize, Icon, IconName, IconSize, IntoElement, ParentElement, Render, Styled,
|
||||
StyledExt, div, h_flex, rems, v_flex,
|
||||
};
|
||||
|
||||
mod blame_ui;
|
||||
|
||||
use git::{
|
||||
repository::{Branch, Upstream, UpstreamTracking, UpstreamTrackingStatus},
|
||||
status::{FileStatus, StatusCode, UnmergedStatus, UnmergedStatusCode},
|
||||
};
|
||||
use git_panel_settings::GitPanelSettings;
|
||||
use gpui::{
|
||||
Action, App, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Window,
|
||||
actions,
|
||||
Action, App, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, SharedString,
|
||||
Window, actions,
|
||||
};
|
||||
use menu::{Cancel, Confirm};
|
||||
use onboarding::GitOnboardingModal;
|
||||
use project::git_store::Repository;
|
||||
use project_diff::ProjectDiff;
|
||||
use ui::prelude::*;
|
||||
use workspace::{ModalView, Workspace};
|
||||
use workspace::{ModalView, Workspace, notifications::DetachAndPromptErr};
|
||||
use zed_actions;
|
||||
|
||||
use crate::{git_panel::GitPanel, text_diff_view::TextDiffView};
|
||||
@@ -202,6 +210,9 @@ pub fn init(cx: &mut App) {
|
||||
workspace.register_action(|workspace, _: &git::OpenModifiedFiles, window, cx| {
|
||||
open_modified_files(workspace, window, cx);
|
||||
});
|
||||
workspace.register_action(|workspace, _: &git::RenameBranch, window, cx| {
|
||||
rename_current_branch(workspace, window, cx);
|
||||
});
|
||||
workspace.register_action(
|
||||
|workspace, action: &DiffClipboardWithSelectionData, window, cx| {
|
||||
if let Some(task) = TextDiffView::open(action, workspace, window, cx) {
|
||||
@@ -245,6 +256,122 @@ pub fn git_status_icon(status: FileStatus) -> impl IntoElement {
|
||||
GitStatusIcon::new(status)
|
||||
}
|
||||
|
||||
struct RenameBranchModal {
|
||||
current_branch: SharedString,
|
||||
editor: Entity<Editor>,
|
||||
repo: Entity<Repository>,
|
||||
}
|
||||
|
||||
impl RenameBranchModal {
|
||||
fn new(
|
||||
current_branch: String,
|
||||
repo: Entity<Repository>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let editor = cx.new(|cx| {
|
||||
let mut editor = Editor::single_line(window, cx);
|
||||
editor.set_text(current_branch.clone(), window, cx);
|
||||
editor
|
||||
});
|
||||
Self {
|
||||
current_branch: current_branch.into(),
|
||||
editor,
|
||||
repo,
|
||||
}
|
||||
}
|
||||
|
||||
fn cancel(&mut self, _: &Cancel, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
cx.emit(DismissEvent);
|
||||
}
|
||||
|
||||
fn confirm(&mut self, _: &Confirm, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let new_name = self.editor.read(cx).text(cx);
|
||||
if new_name.is_empty() || new_name == self.current_branch.as_ref() {
|
||||
cx.emit(DismissEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
let repo = self.repo.clone();
|
||||
let current_branch = self.current_branch.to_string();
|
||||
cx.spawn(async move |_, cx| {
|
||||
match repo
|
||||
.update(cx, |repo, _| {
|
||||
repo.rename_branch(current_branch, new_name.clone())
|
||||
})?
|
||||
.await
|
||||
{
|
||||
Ok(Ok(_)) => Ok(()),
|
||||
Ok(Err(error)) => Err(error),
|
||||
Err(_) => Err(anyhow::anyhow!("Operation was canceled")),
|
||||
}
|
||||
})
|
||||
.detach_and_prompt_err("Failed to rename branch", window, cx, |_, _, _| None);
|
||||
cx.emit(DismissEvent);
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<DismissEvent> for RenameBranchModal {}
|
||||
impl ModalView for RenameBranchModal {}
|
||||
impl Focusable for RenameBranchModal {
|
||||
fn focus_handle(&self, cx: &App) -> FocusHandle {
|
||||
self.editor.focus_handle(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for RenameBranchModal {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.key_context("RenameBranchModal")
|
||||
.on_action(cx.listener(Self::cancel))
|
||||
.on_action(cx.listener(Self::confirm))
|
||||
.elevation_2(cx)
|
||||
.w(rems(34.))
|
||||
.child(
|
||||
h_flex()
|
||||
.px_3()
|
||||
.pt_2()
|
||||
.pb_1()
|
||||
.w_full()
|
||||
.gap_1p5()
|
||||
.child(Icon::new(IconName::GitBranch).size(IconSize::XSmall))
|
||||
.child(
|
||||
Headline::new(format!("Rename Branch ({})", self.current_branch))
|
||||
.size(HeadlineSize::XSmall),
|
||||
),
|
||||
)
|
||||
.child(div().px_3().pb_3().w_full().child(self.editor.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
fn rename_current_branch(
|
||||
workspace: &mut Workspace,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Workspace>,
|
||||
) {
|
||||
let Some(panel) = workspace.panel::<git_panel::GitPanel>(cx) else {
|
||||
return;
|
||||
};
|
||||
let current_branch: Option<String> = panel.update(cx, |panel, cx| {
|
||||
let repo = panel.active_repository.as_ref()?;
|
||||
let repo = repo.read(cx);
|
||||
repo.branch.as_ref().map(|branch| branch.name().to_string())
|
||||
});
|
||||
|
||||
let Some(current_branch_name) = current_branch else {
|
||||
return;
|
||||
};
|
||||
|
||||
let repo = panel.read(cx).active_repository.clone();
|
||||
let Some(repo) = repo else {
|
||||
return;
|
||||
};
|
||||
|
||||
workspace.toggle_modal(window, cx, |window, cx| {
|
||||
RenameBranchModal::new(current_branch_name, repo, window, cx)
|
||||
});
|
||||
}
|
||||
|
||||
fn render_remote_button(
|
||||
id: impl Into<SharedString>,
|
||||
branch: &Branch,
|
||||
|
||||
Reference in New Issue
Block a user