Fix git branches in non-active repository (#26148)
Release Notes: - Git Beta: Fixed a bug where the branch selector would only show for the first repository opened. --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com> Co-authored-by: Richard Feldman <oss@rtfeldman.com>
This commit is contained in:
parent
2a919ad1d0
commit
9d54e63a11
12 changed files with 316 additions and 299 deletions
|
@ -1,4 +1,4 @@
|
|||
use anyhow::Context as _;
|
||||
use anyhow::{anyhow, Context as _};
|
||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||
|
||||
use git::repository::Branch;
|
||||
|
@ -8,7 +8,7 @@ use gpui::{
|
|||
Task, Window,
|
||||
};
|
||||
use picker::{Picker, PickerDelegate};
|
||||
use project::{Project, ProjectPath};
|
||||
use project::git::Repository;
|
||||
use std::sync::Arc;
|
||||
use ui::{prelude::*, HighlightedLabel, ListItem, ListItemSpacing, PopoverMenuHandle};
|
||||
use util::ResultExt;
|
||||
|
@ -28,16 +28,20 @@ pub fn open(
|
|||
window: &mut Window,
|
||||
cx: &mut Context<Workspace>,
|
||||
) {
|
||||
let project = workspace.project().clone();
|
||||
let repository = workspace.project().read(cx).active_repository(cx).clone();
|
||||
let style = BranchListStyle::Modal;
|
||||
workspace.toggle_modal(window, cx, |window, cx| {
|
||||
BranchList::new(project, style, 34., window, cx)
|
||||
BranchList::new(repository, style, 34., window, cx)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn popover(project: Entity<Project>, window: &mut Window, cx: &mut App) -> Entity<BranchList> {
|
||||
pub fn popover(
|
||||
repository: Option<Entity<Repository>>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Entity<BranchList> {
|
||||
cx.new(|cx| {
|
||||
let list = BranchList::new(project, BranchListStyle::Popover, 15., window, cx);
|
||||
let list = BranchList::new(repository, BranchListStyle::Popover, 15., window, cx);
|
||||
list.focus_handle(cx).focus(window);
|
||||
list
|
||||
})
|
||||
|
@ -58,22 +62,21 @@ pub struct BranchList {
|
|||
|
||||
impl BranchList {
|
||||
fn new(
|
||||
project_handle: Entity<Project>,
|
||||
repository: Option<Entity<Repository>>,
|
||||
style: BranchListStyle,
|
||||
rem_width: f32,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let popover_handle = PopoverMenuHandle::default();
|
||||
let project = project_handle.read(cx);
|
||||
let all_branches_request = project
|
||||
.visible_worktrees(cx)
|
||||
.next()
|
||||
.map(|worktree| project.branches(ProjectPath::root_path(worktree.read(cx).id()), cx))
|
||||
.context("No worktrees found");
|
||||
let all_branches_request = repository
|
||||
.clone()
|
||||
.map(|repository| repository.read(cx).branches());
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
let all_branches = all_branches_request?.await?;
|
||||
let all_branches = all_branches_request
|
||||
.context("No active repository")?
|
||||
.await??;
|
||||
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.picker.update(cx, |picker, cx| {
|
||||
|
@ -86,7 +89,7 @@ impl BranchList {
|
|||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
||||
let delegate = BranchListDelegate::new(project_handle.clone(), style, 20);
|
||||
let delegate = BranchListDelegate::new(repository.clone(), style, 20);
|
||||
let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
|
||||
|
||||
let _subscription = cx.subscribe(&picker, |_, _, _, cx| {
|
||||
|
@ -145,7 +148,7 @@ impl BranchEntry {
|
|||
pub struct BranchListDelegate {
|
||||
matches: Vec<BranchEntry>,
|
||||
all_branches: Option<Vec<Branch>>,
|
||||
project: Entity<Project>,
|
||||
repo: Option<Entity<Repository>>,
|
||||
style: BranchListStyle,
|
||||
selected_index: usize,
|
||||
last_query: String,
|
||||
|
@ -155,13 +158,13 @@ pub struct BranchListDelegate {
|
|||
|
||||
impl BranchListDelegate {
|
||||
fn new(
|
||||
project: Entity<Project>,
|
||||
repo: Option<Entity<Repository>>,
|
||||
style: BranchListStyle,
|
||||
branch_name_trailoff_after: usize,
|
||||
) -> Self {
|
||||
Self {
|
||||
matches: vec![],
|
||||
project,
|
||||
repo,
|
||||
style,
|
||||
all_branches: None,
|
||||
selected_index: 0,
|
||||
|
@ -280,14 +283,16 @@ impl PickerDelegate for BranchListDelegate {
|
|||
return;
|
||||
};
|
||||
|
||||
let current_branch = self.project.update(cx, |project, cx| {
|
||||
project
|
||||
.active_repository(cx)
|
||||
.and_then(|repo| repo.read(cx).current_branch())
|
||||
.map(|branch| branch.name.to_string())
|
||||
let current_branch = self.repo.as_ref().map(|repo| {
|
||||
repo.update(cx, |repo, _| {
|
||||
repo.current_branch().map(|branch| branch.name.clone())
|
||||
})
|
||||
});
|
||||
|
||||
if current_branch == Some(branch.name().to_string()) {
|
||||
if current_branch
|
||||
.flatten()
|
||||
.is_some_and(|current_branch| current_branch == branch.name())
|
||||
{
|
||||
cx.emit(DismissEvent);
|
||||
return;
|
||||
}
|
||||
|
@ -296,19 +301,33 @@ impl PickerDelegate for BranchListDelegate {
|
|||
let branch = branch.clone();
|
||||
|picker, mut cx| async move {
|
||||
let branch_change_task = picker.update(&mut cx, |this, cx| {
|
||||
let project = this.delegate.project.read(cx);
|
||||
let branch_to_checkout = match branch {
|
||||
BranchEntry::Branch(branch) => branch.string,
|
||||
BranchEntry::History(string) => string,
|
||||
BranchEntry::NewBranch { name: branch_name } => branch_name,
|
||||
};
|
||||
let worktree = project
|
||||
.visible_worktrees(cx)
|
||||
.next()
|
||||
.context("worktree disappeared")?;
|
||||
let repository = ProjectPath::root_path(worktree.read(cx).id());
|
||||
let repo = this
|
||||
.delegate
|
||||
.repo
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("No active repository"))?
|
||||
.clone();
|
||||
|
||||
anyhow::Ok(project.update_or_create_branch(repository, branch_to_checkout, cx))
|
||||
let cx = cx.to_async();
|
||||
|
||||
anyhow::Ok(async move {
|
||||
match branch {
|
||||
BranchEntry::Branch(StringMatch {
|
||||
string: branch_name,
|
||||
..
|
||||
})
|
||||
| BranchEntry::History(branch_name) => {
|
||||
cx.update(|cx| repo.read(cx).change_branch(branch_name))?
|
||||
.await?
|
||||
}
|
||||
BranchEntry::NewBranch { name: branch_name } => {
|
||||
cx.update(|cx| repo.read(cx).create_branch(branch_name.clone()))?
|
||||
.await??;
|
||||
cx.update(|cx| repo.read(cx).change_branch(branch_name))?
|
||||
.await?
|
||||
}
|
||||
}
|
||||
})
|
||||
})??;
|
||||
|
||||
branch_change_task.await?;
|
||||
|
@ -316,7 +335,7 @@ impl PickerDelegate for BranchListDelegate {
|
|||
picker.update(&mut cx, |_, cx| {
|
||||
cx.emit(DismissEvent);
|
||||
|
||||
Ok::<(), anyhow::Error>(())
|
||||
anyhow::Ok(())
|
||||
})
|
||||
}
|
||||
})
|
||||
|
|
|
@ -4,7 +4,6 @@ use crate::branch_picker::{self, BranchList};
|
|||
use crate::git_panel::{commit_message_editor, GitPanel};
|
||||
use git::{Commit, ShowCommitEditor};
|
||||
use panel::{panel_button, panel_editor_style, panel_filled_button};
|
||||
use project::Project;
|
||||
use ui::{prelude::*, KeybindingHint, PopoverMenu, Tooltip};
|
||||
|
||||
use editor::{Editor, EditorElement};
|
||||
|
@ -129,10 +128,9 @@ impl CommitModal {
|
|||
active_index,
|
||||
};
|
||||
|
||||
let project = workspace.project().clone();
|
||||
workspace.open_panel::<GitPanel>(window, cx);
|
||||
workspace.toggle_modal(window, cx, move |window, cx| {
|
||||
CommitModal::new(git_panel, restore_dock_position, project, window, cx)
|
||||
CommitModal::new(git_panel, restore_dock_position, window, cx)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
@ -140,11 +138,11 @@ impl CommitModal {
|
|||
fn new(
|
||||
git_panel: Entity<GitPanel>,
|
||||
restore_dock: RestoreDock,
|
||||
project: Entity<Project>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let panel = git_panel.read(cx);
|
||||
let active_repository = panel.active_repository.clone();
|
||||
let suggested_commit_message = panel.suggest_commit_message();
|
||||
|
||||
let commit_editor = git_panel.update(cx, |git_panel, cx| {
|
||||
|
@ -188,7 +186,7 @@ impl CommitModal {
|
|||
let properties = ModalContainerProperties::new(window, 50);
|
||||
|
||||
Self {
|
||||
branch_list: branch_picker::popover(project.clone(), window, cx),
|
||||
branch_list: branch_picker::popover(active_repository.clone(), window, cx),
|
||||
git_panel,
|
||||
commit_editor,
|
||||
restore_dock,
|
||||
|
|
|
@ -3327,6 +3327,11 @@ impl RenderOnce for PanelRepoFooter {
|
|||
.as_ref()
|
||||
.map(|panel| panel.read(cx).project.clone());
|
||||
|
||||
let repo = self
|
||||
.git_panel
|
||||
.as_ref()
|
||||
.and_then(|panel| panel.read(cx).active_repository.clone());
|
||||
|
||||
let single_repo = project
|
||||
.as_ref()
|
||||
.map(|project| project.read(cx).all_repositories(cx).len() == 1)
|
||||
|
@ -3366,7 +3371,7 @@ impl RenderOnce for PanelRepoFooter {
|
|||
});
|
||||
|
||||
let branch_selector = PopoverMenu::new("popover-button")
|
||||
.menu(move |window, cx| Some(branch_picker::popover(project.clone()?, window, cx)))
|
||||
.menu(move |window, cx| Some(branch_picker::popover(repo.clone(), window, cx)))
|
||||
.trigger_with_tooltip(
|
||||
branch_selector_button,
|
||||
Tooltip::for_action_title("Switch Branch", &zed_actions::git::Branch),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue