@@ -8,14 +8,17 @@ use crate::{
8
8
branchloc:: BranchLocator ,
9
9
ext:: RepositoryExtended ,
10
10
stack:: { InitializationPolicy , Stack , StackStateAccess } ,
11
+ stupid:: Stupid ,
11
12
} ;
12
13
14
+ use super :: get_stgit_parent;
15
+
13
16
pub ( super ) fn command ( ) -> clap:: Command {
14
17
clap:: Command :: new ( "--delete" )
15
18
. short_flag ( 'D' )
16
19
. override_usage ( super :: super :: make_usage (
17
20
"stg branch --delete" ,
18
- & [ "[--force] <branch>" ] ,
21
+ & [ "[--force] [ <branch>] " ] ,
19
22
) )
20
23
. about ( "Delete a branch" )
21
24
. long_about (
@@ -24,13 +27,16 @@ pub(super) fn command() -> clap::Command {
24
27
The branch will not be deleted if there are any patches remaining unless \
25
28
the '--force' option is provided.\n \
26
29
\n \
30
+ If the current branch is selected for deletion, its parent branch must be \
31
+ configured and the worktree must be clean. The parent branch will be \
32
+ checked-out after the current branch is deleted.\n \
33
+ \n \
27
34
A protected branch may not be deleted; it must be unprotected first.",
28
35
)
29
36
. arg (
30
37
clap:: Arg :: new ( "branch-any" )
31
38
. help ( "Branch to delete" )
32
39
. value_name ( "branch" )
33
- . required ( true )
34
40
. value_parser ( clap:: value_parser!( BranchLocator ) ) ,
35
41
)
36
42
. arg (
@@ -42,25 +48,49 @@ pub(super) fn command() -> clap::Command {
42
48
}
43
49
44
50
pub ( super ) fn dispatch ( repo : & gix:: Repository , matches : & clap:: ArgMatches ) -> Result < ( ) > {
45
- let target_branch = matches
46
- . get_one :: < BranchLocator > ( "branch-any" )
47
- . expect ( "required argument" )
48
- . resolve ( repo) ?;
49
- let target_branchname = target_branch. get_branch_partial_name ( ) ?;
51
+ let ( target_branch, target_branchname) = if let Some ( branch_loc) = matches. get_one :: < BranchLocator > ( "branch-any" ) {
52
+ let branch = branch_loc. resolve ( repo) ?;
53
+ let branchname = branch. get_branch_partial_name ( ) ?;
54
+ ( branch, branchname)
55
+ } else if let Ok ( branch) = repo. get_current_branch ( ) {
56
+ let branchname = branch. get_branch_partial_name ( ) ?;
57
+ ( branch, branchname)
58
+ } else {
59
+ return Err ( anyhow ! ( "no target branch specified and no current branch" ) ) ;
60
+ } ;
61
+
50
62
let current_branch = repo. get_current_branch ( ) . ok ( ) ;
51
63
let current_branchname = current_branch
52
64
. as_ref ( )
53
65
. and_then ( |branch| branch. get_branch_partial_name ( ) . ok ( ) ) ;
54
- if Some ( & target_branchname) == current_branchname. as_ref ( ) {
55
- return Err ( anyhow ! ( "cannot delete the current branch" ) ) ;
56
- }
66
+ let config_snapshot = repo. config_snapshot ( ) ;
67
+ let stupid = repo. stupid ( ) ;
68
+
69
+ let switch_to_branch = if Some ( & target_branchname) == current_branchname. as_ref ( ) {
70
+ if let Some ( parent_branch) = get_stgit_parent ( & config_snapshot, & target_branchname) {
71
+ let statuses = stupid. statuses ( None ) ?;
72
+ if let Err ( e) = statuses
73
+ . check_worktree_clean ( )
74
+ . and_then ( |_| statuses. check_conflicts ( ) )
75
+ {
76
+ return Err ( anyhow ! ( "cannot delete the current branch: {e}" ) ) ;
77
+ }
78
+ Some ( parent_branch)
79
+ } else {
80
+ return Err ( anyhow ! (
81
+ "cannot delete the current branch without a known parent branch"
82
+ ) ) ;
83
+ }
84
+ } else {
85
+ None
86
+ } ;
57
87
58
88
if let Ok ( stack) = Stack :: from_branch (
59
89
repo,
60
90
target_branch. clone ( ) ,
61
91
InitializationPolicy :: RequireInitialized ,
62
92
) {
63
- if stack. is_protected ( & repo . config_snapshot ( ) ) {
93
+ if stack. is_protected ( & config_snapshot) {
64
94
return Err ( anyhow ! ( "delete not permitted: this branch is protected" ) ) ;
65
95
} else if !matches. get_flag ( "force" ) && stack. all_patches ( ) . count ( ) > 0 {
66
96
return Err ( anyhow ! (
@@ -70,11 +100,18 @@ pub(super) fn dispatch(repo: &gix::Repository, matches: &clap::ArgMatches) -> Re
70
100
stack. deinitialize ( ) ?;
71
101
}
72
102
103
+ if let Some ( branch_name) = switch_to_branch {
104
+ stupid
105
+ . checkout ( & branch_name)
106
+ . context ( "switching to parent branch" ) ?;
107
+ }
108
+
73
109
target_branch. delete ( ) ?;
74
110
75
111
let mut local_config_file = repo. local_config_file ( ) ?;
76
112
local_config_file. remove_section ( "branch" , Some ( target_branchname. as_ref ( ) . into ( ) ) ) ;
77
- repo. write_local_config ( local_config_file) . context ( "writing local config file" ) ?;
113
+ repo. write_local_config ( local_config_file)
114
+ . context ( "writing local config file" ) ?;
78
115
79
116
Ok ( ( ) )
80
117
}
0 commit comments