diff --git a/crates/collab_ui/src/branch_list.rs b/crates/collab_ui/src/branch_list.rs index 2d014cc1b9..038180b671 100644 --- a/crates/collab_ui/src/branch_list.rs +++ b/crates/collab_ui/src/branch_list.rs @@ -1,3 +1,4 @@ +use anyhow::{anyhow, bail}; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{elements::*, AppContext, MouseState, Task, ViewContext, ViewHandle}; use picker::{Picker, PickerDelegate, PickerEvent}; @@ -53,7 +54,7 @@ impl PickerDelegate for BranchListDelegate { fn update_matches(&mut self, query: String, cx: &mut ViewContext>) -> Task<()> { cx.spawn(move |picker, mut cx| async move { - let candidates = picker + let Some(candidates) = picker .read_with(&mut cx, |view, cx| { let delegate = view.delegate(); let project = delegate.workspace.read(cx).project().read(&cx); @@ -67,13 +68,10 @@ impl PickerDelegate for BranchListDelegate { .path .to_path_buf(); cwd.push(".git"); - let mut branches = project - .fs() - .open_repo(&cwd) - .unwrap() + let Some(repo) = project.fs().open_repo(&cwd) else {bail!("Project does not have associated git repository.")}; + let mut branches = repo .lock() - .branches() - .unwrap(); + .branches()?; if query.is_empty() { const RECENT_BRANCHES_COUNT: usize = 10; // Do a partial sort to show recent-ish branches first. @@ -83,7 +81,7 @@ impl PickerDelegate for BranchListDelegate { branches.truncate(RECENT_BRANCHES_COUNT); branches.sort_unstable_by(|lhs, rhs| lhs.name.cmp(&rhs.name)); } - branches + Ok(branches .iter() .cloned() .enumerate() @@ -92,9 +90,10 @@ impl PickerDelegate for BranchListDelegate { char_bag: command.name.chars().collect(), string: command.name.into(), }) - .collect::>() + .collect::>()) }) - .unwrap(); + .log_err() else { return; }; + let Some(candidates) = candidates.log_err() else {return;}; let matches = if query.is_empty() { candidates .into_iter() @@ -136,37 +135,43 @@ impl PickerDelegate for BranchListDelegate { fn confirm(&mut self, cx: &mut ViewContext>) { let current_pick = self.selected_index(); let current_pick = self.matches[current_pick].string.clone(); - let project = self.workspace.read(cx).project().read(cx); - let mut cwd = project - .visible_worktrees(cx) - .next() - .unwrap() - .read(cx) - .root_entry() - .unwrap() - .path - .to_path_buf(); - cwd.push(".git"); - let status = project - .fs() - .open_repo(&cwd) - .unwrap() - .lock() - .change_branch(¤t_pick); - if status.is_err() { - const GIT_CHECKOUT_FAILURE_ID: usize = 2048; - self.workspace.update(cx, |model, ctx| { - model.show_toast( - Toast::new( - GIT_CHECKOUT_FAILURE_ID, - format!("Failed to checkout branch '{current_pick}', check for conflicts or unstashed files"), - ), - ctx, - ) - }); - } - status.log_err(); - cx.emit(PickerEvent::Dismiss); + cx.spawn(|picker, mut cx| async move { + picker.update(&mut cx, |this, cx| { + let project = this.delegate().workspace.read(cx).project().read(cx); + let mut cwd = project + .visible_worktrees(cx) + .next() + .ok_or_else(|| anyhow!("There are no visisible worktrees."))? + .read(cx) + .root_entry() + .ok_or_else(|| anyhow!("Worktree has no root entry."))? + .path + .to_path_buf(); + cwd.push(".git"); + let status = project + .fs() + .open_repo(&cwd) + .ok_or_else(|| anyhow!("Could not open repository at path `{}`", cwd.as_os_str().to_string_lossy()))? + .lock() + .change_branch(¤t_pick); + if status.is_err() { + const GIT_CHECKOUT_FAILURE_ID: usize = 2048; + this.delegate().workspace.update(cx, |model, ctx| { + model.show_toast( + Toast::new( + GIT_CHECKOUT_FAILURE_ID, + format!("Failed to checkout branch '{current_pick}', check for conflicts or unstashed files"), + ), + ctx, + ) + }); + status?; + } + cx.emit(PickerEvent::Dismiss); + + Ok::<(), anyhow::Error>(()) + }).log_err(); + }).detach(); } fn dismissed(&mut self, cx: &mut ViewContext>) {