1 # git-gui remote branch deleting support
2 # Copyright (C) 2007 Shawn Pearce
4 class remote_branch_delete {
13 field checktype {head}
25 constructor dialog {} {
26 global all_remotes M1B
29 wm title $top "[appname] ([reponame]): Delete Remote Branch"
31 wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
34 label $w.header -text {Delete Remote Branch} -font font_uibold
35 pack $w.header -side top -fill x
38 button $w.buttons.delete -text Delete \
41 pack $w.buttons.delete -side right
42 button $w.buttons.cancel -text {Cancel} \
43 -command [list destroy $w]
44 pack $w.buttons.cancel -side right -padx 5
45 pack $w.buttons -side bottom -fill x -pady 10 -padx 10
47 labelframe $w.dest -text {From Repository}
48 if {$all_remotes ne {}} {
49 radiobutton $w.dest.remote_r \
53 eval tk_optionMenu $w.dest.remote_m @remote $all_remotes
54 grid $w.dest.remote_r $w.dest.remote_m -sticky w
55 if {[lsearch -sorted -exact $all_remotes origin] != -1} {
58 set remote [lindex $all_remotes 0]
61 trace add variable @remote write [cb _write_remote]
65 radiobutton $w.dest.url_r \
66 -text {Arbitrary URL:} \
76 if {%d == 1 && [regexp {\s} %S]} {return 0}
79 trace add variable @url write [cb _write_url]
80 grid $w.dest.url_r $w.dest.url_t -sticky we -padx {0 5}
81 grid columnconfigure $w.dest 1 -weight 1
82 pack $w.dest -anchor nw -fill x -pady 5 -padx 5
84 labelframe $w.heads -text {Branches}
88 -listvariable @head_list \
89 -selectmode extended \
90 -yscrollcommand [list $w.heads.sby set]
91 scrollbar $w.heads.sby -command [list $w.heads.l yview]
94 label $w.heads.footer.status \
95 -textvariable @status \
98 button $w.heads.footer.rescan \
100 -command [cb _rescan]
101 pack $w.heads.footer.status -side left -fill x -expand 1
102 pack $w.heads.footer.rescan -side right
104 pack $w.heads.footer -side bottom -fill x -expand 1
105 pack $w.heads.sby -side right -fill y
106 pack $w.heads.l -side left -fill both -expand 1
107 pack $w.heads -fill both -expand 1 -pady 5 -padx 5
109 labelframe $w.validate -text {Delete Only If}
110 radiobutton $w.validate.head_r \
111 -text {Merged Into:} \
114 set head_m [tk_optionMenu $w.validate.head_m @check_head {}]
115 trace add variable @head_list write [cb _write_head_list]
116 trace add variable @check_head write [cb _write_check_head]
117 grid $w.validate.head_r $w.validate.head_m -sticky w
118 radiobutton $w.validate.always_r \
119 -text {Always (Do not perform merge checks)} \
122 grid $w.validate.always_r -columnspan 2 -sticky w
123 grid columnconfigure $w.validate 1 -weight 1
124 pack $w.validate -anchor nw -fill x -pady 5 -padx 5
126 trace add variable @urltype write [cb _write_urltype]
129 bind $w <Key-F5> [cb _rescan]
130 bind $w <$M1B-Key-r> [cb _rescan]
131 bind $w <$M1B-Key-R> [cb _rescan]
132 bind $w <Key-Return> [cb _delete]
133 bind $w <Key-Escape> [list destroy $w]
134 bind $w.header <Destroy> [list delete_this $this]
140 remote {set uri $remote}
144 set cache $urltype:$uri
146 if {$checktype eq {head}} {
147 if {$check_head eq {}} {
151 -title [wm title $w] \
153 -message "A branch is required for 'Merged Into'."
156 set crev $full_cache("$cache\nrefs/heads/$check_head")
159 set not_merged [list]
162 set push_cmd [list git push]
164 lappend push_cmd $uri
166 foreach i [$w.heads.l curselection] {
167 set ref [lindex $full_list $i]
169 set obj $full_cache("$cache\n$ref")
170 if {[catch {set m [git merge-base $obj $crev]}]} {
175 lappend not_merged [lindex $head_list $i]
180 lappend push_cmd :$ref
184 if {$not_merged ne {}} {
185 set msg "The following branches are not completely merged into $check_head:
187 - [join $not_merged "\n - "]"
192 One or more of the merge tests failed because you have not fetched the necessary commits. Try fetching from $uri first."
198 -title [wm title $w] \
201 if {!$have_selection} return
204 if {!$have_selection} {
208 -title [wm title $w] \
210 -message "Please select one or more branches to delete."
217 -title [wm title $w] \
219 -message {Recovering deleted branches is difficult.
221 Delete the selected branches?}] ne yes} {
227 set cons [console::new \
229 "Deleting branches from $uri"]
230 console::exec $cons $push_cmd
233 method _rescan {{force 1}} {
235 remote {set uri $remote}
240 unset -nocomplain cached($urltype:$uri)
243 if {$idle_id ne {}} {
244 after cancel $idle_id
248 _load $this $urltype:$uri $uri
251 method _write_remote {args} { set urltype remote }
252 method _write_url {args} { set urltype url }
253 method _write_check_head {args} { set checktype head }
255 method _write_head_list {args} {
257 foreach abr $head_list {
258 $head_m insert end radiobutton \
261 -variable @check_head
263 if {[lsearch -exact -sorted $head_list $check_head] < 0} {
268 method _write_urltype {args} {
269 if {$urltype eq {url}} {
270 if {$idle_id ne {}} {
271 after cancel $idle_id
274 set idle_id [after 1000 [cb _rescan 0]]
280 method _load {cache uri} {
281 if {$active_ls ne {}} {
282 catch {close $active_ls}
286 $w.heads.l conf -state disabled
289 set status {No repository selected.}
293 if {[catch {set x $cached($cache)}]} {
294 set status "Scanning $uri..."
295 $w.heads.l conf -state disabled
298 set head_cache($cache) [list]
299 set full_cache($cache) [list]
300 set active_ls [open "| [list git ls-remote $uri]" r]
301 fconfigure $active_ls \
305 fileevent $active_ls readable [cb _read $cache $active_ls]
308 set full_list $full_cache($cache)
309 set head_list $head_cache($cache)
310 $w.heads.l conf -state normal
314 method _read {cache fd} {
315 if {$fd ne $active_ls} {
320 while {[gets $fd line] >= 0} {
321 if {[string match {*^{}} $line]} continue
322 if {[regexp {^([0-9a-f]{40}) (.*)$} $line _junk obj ref]} {
323 if {[regsub ^refs/heads/ $ref {} abr]} {
324 lappend head_list $abr
325 lappend head_cache($cache) $abr
326 lappend full_list $ref
327 lappend full_cache($cache) $ref
328 set full_cache("$cache\n$ref") $obj
334 if {[catch {close $fd} err]} {
341 $w.heads.l conf -state normal