Skip to content

Commit 1218701

Browse files
committed
interactive rm local branch
1 parent 47b226e commit 1218701

File tree

5 files changed

+384
-80
lines changed

5 files changed

+384
-80
lines changed

src/cli/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ pub fn run() -> color_eyre::Result<()> {
128128
}
129129
Commands::Rm(args) => {
130130
let command = RemoveCommand::new(args.name, args.force);
131-
command.execute(&repo)?;
131+
let _ = command.execute(&repo)?;
132132
}
133133
Commands::PrGithub(args) => {
134134
let worktree_name = resolve_worktree_name(args.name, &repo, "pr-github")?;

src/commands/interactive/command.rs

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use super::{
2121
},
2222
view::{DetailData, DialogView, Snapshot},
2323
};
24+
use crate::commands::rm::{LocalBranchStatus, RemoveOutcome};
2425

2526
pub struct InteractiveCommand<B, E>
2627
where
@@ -77,7 +78,7 @@ where
7778

7879
pub fn run<F, G>(mut self, mut on_remove: F, mut on_create: G) -> Result<Option<Selection>>
7980
where
80-
F: FnMut(&str, bool) -> Result<()>,
81+
F: FnMut(&str, bool) -> Result<RemoveOutcome>,
8182
G: FnMut(&str, Option<&str>) -> Result<()>,
8283
{
8384
self.terminal
@@ -86,6 +87,9 @@ where
8687

8788
let result = self.event_loop(&mut on_remove, &mut on_create);
8889

90+
self.terminal
91+
.clear()
92+
.wrap_err("failed to clear terminal before exit")?;
8993
self.terminal
9094
.show_cursor()
9195
.wrap_err("failed to show cursor")?;
@@ -99,7 +103,7 @@ where
99103
on_create: &mut G,
100104
) -> Result<Option<Selection>>
101105
where
102-
F: FnMut(&str, bool) -> Result<()>,
106+
F: FnMut(&str, bool) -> Result<RemoveOutcome>,
103107
G: FnMut(&str, Option<&str>) -> Result<()>,
104108
{
105109
let mut state = ListState::default();
@@ -126,15 +130,15 @@ where
126130
on_create: &mut G,
127131
) -> Result<LoopControl>
128132
where
129-
F: FnMut(&str, bool) -> Result<()>,
133+
F: FnMut(&str, bool) -> Result<RemoveOutcome>,
130134
G: FnMut(&str, Option<&str>) -> Result<()>,
131135
{
132136
if let Some(dialog) = self.dialog.clone() {
133137
match dialog {
134138
Dialog::Remove(_) => {
135139
if let Event::Key(key) = event {
136140
if key.kind == KeyEventKind::Press {
137-
self.handle_remove_dialog_key(key, state, on_remove)?;
141+
return self.handle_remove_dialog_key(key, state, on_remove);
138142
}
139143
}
140144
return Ok(LoopControl::Continue);
@@ -327,17 +331,18 @@ where
327331
key: KeyEvent,
328332
state: &mut ListState,
329333
on_remove: &mut F,
330-
) -> Result<()>
334+
) -> Result<LoopControl>
331335
where
332-
F: FnMut(&str, bool) -> Result<()>,
336+
F: FnMut(&str, bool) -> Result<RemoveOutcome>,
333337
{
334338
let dialog_state = self.dialog.take();
335339
let Some(Dialog::Remove(mut dialog)) = dialog_state else {
336340
self.dialog = dialog_state;
337-
return Ok(());
341+
return Ok(LoopControl::Continue);
338342
};
339343

340344
let mut reinstate = true;
345+
let mut control = LoopControl::Continue;
341346

342347
match key.code {
343348
KeyCode::Esc | KeyCode::Char('n') | KeyCode::Char('N') => {
@@ -346,7 +351,14 @@ where
346351
}
347352
KeyCode::Char('y') | KeyCode::Char('Y') => {
348353
reinstate = false;
349-
self.perform_remove(dialog.index, dialog.remove_local_branch(), state, on_remove)?;
354+
if let Some(selection) = self.perform_remove(
355+
dialog.index,
356+
dialog.remove_local_branch(),
357+
state,
358+
on_remove,
359+
)? {
360+
control = LoopControl::Exit(Some(selection));
361+
}
350362
}
351363
KeyCode::Tab => dialog.focus_next(),
352364
KeyCode::BackTab => dialog.focus_prev(),
@@ -381,12 +393,14 @@ where
381393
self.status = Some(StatusMessage::info("Removal cancelled."));
382394
} else {
383395
reinstate = false;
384-
self.perform_remove(
396+
if let Some(selection) = self.perform_remove(
385397
dialog.index,
386398
dialog.remove_local_branch(),
387399
state,
388400
on_remove,
389-
)?;
401+
)? {
402+
control = LoopControl::Exit(Some(selection));
403+
}
390404
}
391405
}
392406
},
@@ -397,7 +411,7 @@ where
397411
self.dialog = Some(Dialog::Remove(dialog));
398412
}
399413

400-
Ok(())
414+
Ok(control)
401415
}
402416

403417
fn perform_remove<F>(
@@ -406,26 +420,40 @@ where
406420
remove_local_branch: bool,
407421
state: &mut ListState,
408422
on_remove: &mut F,
409-
) -> Result<()>
423+
) -> Result<Option<Selection>>
410424
where
411-
F: FnMut(&str, bool) -> Result<()>,
425+
F: FnMut(&str, bool) -> Result<RemoveOutcome>,
412426
{
413427
if let Some(entry) = self.worktrees.get(index).cloned() {
414428
match on_remove(&entry.name, remove_local_branch) {
415-
Ok(()) => {
429+
Ok(outcome) => {
416430
self.worktrees.remove(index);
417431
let removal_dir = entry
418432
.path
419433
.parent()
420434
.map(|parent| parent.display().to_string())
421435
.unwrap_or_else(|| entry.path.display().to_string());
422-
let message =
436+
let mut message =
423437
format!("Removed worktree `{}` from `{}`.", entry.name, removal_dir);
438+
match outcome.local_branch {
439+
Some(LocalBranchStatus::Deleted) => {
440+
message.push_str(&format!(" Deleted local branch `{}`.", entry.name));
441+
}
442+
Some(LocalBranchStatus::NotFound) => {
443+
message.push_str(&format!(" Local branch `{}` not found.", entry.name));
444+
}
445+
None => {}
446+
}
424447
self.selected = None;
425448
self.focus = Focus::Worktrees;
426449
self.sync_selection(state);
427450
self.status = None;
428-
self.dialog = Some(Dialog::Info { message });
451+
if outcome.repositioned {
452+
self.dialog = None;
453+
return Ok(Some(Selection::RepoRoot));
454+
} else {
455+
self.dialog = Some(Dialog::Info { message });
456+
}
429457
}
430458
Err(err) => {
431459
self.status = Some(StatusMessage::error(format!(
@@ -439,7 +467,7 @@ where
439467
self.dialog = None;
440468
}
441469

442-
Ok(())
470+
Ok(None)
443471
}
444472

445473
fn handle_create_key<G>(

src/commands/interactive/runtime.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ pub fn run(repo: &Repo) -> Result<()> {
6868
|name, remove_local_branch| {
6969
let command = RemoveCommand::new(name.to_owned(), false)
7070
.with_quiet(true)
71-
.with_remove_local_branch(remove_local_branch);
71+
.with_remove_local_branch(remove_local_branch)
72+
.with_spawn_shell(false);
7273
command.execute(repo)
7374
},
7475
|name, base| {
@@ -135,7 +136,7 @@ pub fn run(repo: &Repo) -> Result<()> {
135136

136137
if remove_worktree {
137138
let remove_command = RemoveCommand::new(name, false);
138-
remove_command.execute(repo)?;
139+
let _ = remove_command.execute(repo)?;
139140
}
140141
}
141142
}

0 commit comments

Comments
 (0)