1 # git-gui revision chooser
2 # Copyright (C) 2006, 2007 Shawn Pearce
6 image create photo ::choose_rev::img_find -data {R0lGODlhEAAQAIYAAPwCBCQmJDw+PBQSFAQCBMza3NTm5MTW1HyChOT29Ozq7MTq7Kze5Kzm7Oz6/NTy9Iza5GzGzKzS1Nzy9Nz29Kzq9HTGzHTK1Lza3AwKDLzu9JTi7HTW5GTCzITO1Mzq7Hza5FTK1ESyvHzKzKzW3DQyNDyqtDw6PIzW5HzGzAT+/Dw+RKyurNTOzMTGxMS+tJSGdATCxHRydLSqpLymnLSijBweHERCRNze3Pz69PTy9Oze1OTSxOTGrMSqlLy+vPTu5OzSvMymjNTGvNS+tMy2pMyunMSefAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAe4gACCAAECA4OIiAIEBQYHBAKJgwIICQoLDA0IkZIECQ4PCxARCwSSAxITFA8VEBYXGBmJAQYLGhUbHB0eH7KIGRIMEBAgISIjJKaIJQQLFxERIialkieUGigpKRoIBCqJKyyLBwvJAioEyoICLS4v6QQwMQQyLuqLli8zNDU2BCf1lN3AkUPHDh49fAQAAEnGD1MCCALZEaSHkIUMBQS8wWMIkSJGhBzBmFEGgRsBUqpMiSgdAD+BAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7}
8 field w ; # our megawidget path
9 field w_list ; # list of currently filtered specs
10 field w_filter ; # filter entry for $w_list
12 field c_expr {}; # current revision expression
13 field filter ; # current filter string
14 field revtype head; # type of revision chosen
15 field cur_specs [list]; # list of specs for $revtype
16 field spec_head ; # list of all head specs
17 field spec_trck ; # list of all tracking branch specs
18 field spec_tag ; # list of all tag specs
20 constructor new {path {title {}}} {
21 global current_branch is_detached
26 labelframe $w -text $title
30 bind $w <Destroy> [cb _delete %W]
33 radiobutton $w.detachedhead_r \
35 -text {This Detached Checkout} \
38 grid $w.detachedhead_r -sticky we -padx {0 5} -columnspan 2
41 radiobutton $w.expr_r \
42 -text {Revision Expression:} \
49 -textvariable @c_expr \
51 -validatecommand [cb _validate %d %S]
52 grid $w.expr_r $w.expr_t -sticky we -padx {0 5}
55 radiobutton $w.types.head_r \
56 -text {Local Branch} \
59 pack $w.types.head_r -side left
60 radiobutton $w.types.trck_r \
61 -text {Tracking Branch} \
64 pack $w.types.trck_r -side left
65 radiobutton $w.types.tag_r \
69 pack $w.types.tag_r -side left
70 set w_filter $w.types.filter
75 -textvariable @filter \
77 -validatecommand [cb _filter %P]
78 pack $w_filter -side right
79 pack [label $w.types.filter_icon \
80 -image ::choose_rev::img_find \
82 grid $w.types -sticky we -padx {0 5} -columnspan 2
91 -exportselection false \
92 -xscrollcommand [cb _sb_set $w.list.sbx h] \
93 -yscrollcommand [cb _sb_set $w.list.sby v]
94 pack $w_list -fill both -expand 1
95 grid $w.list -sticky nswe -padx {20 5} -columnspan 2
97 grid columnconfigure $w 1 -weight 1
99 grid rowconfigure $w 3 -weight 1
101 grid rowconfigure $w 2 -weight 1
104 trace add variable @revtype write [cb _select]
105 bind $w_filter <Key-Return> [list focus $w_list]\;break
106 bind $w_filter <Key-Down> [list focus $w_list]
109 foreach name [load_all_heads] {
110 lappend spec_head [list $name refs/heads/$name]
114 foreach spec [all_tracking_branches] {
115 set name [lindex $spec 0]
116 regsub ^refs/(heads|remotes)/ $name {} name
117 lappend spec_trck [concat $name $spec]
121 foreach name [load_all_tags] {
122 lappend spec_tag [list $name refs/tags/$name]
125 if {$is_detached} { set revtype HEAD
126 } elseif {[llength $spec_head] > 0} { set revtype head
127 } elseif {[llength $spec_trck] > 0} { set revtype trck
128 } elseif {[llength $spec_tag ] > 0} { set revtype tag
129 } else { set revtype expr
132 if {$revtype eq {head} && $current_branch ne {}} {
134 foreach spec $spec_head {
135 if {[lindex $spec 0] eq $current_branch} {
136 $w_list selection clear 0 end
137 $w_list selection set $i
148 if {![winfo exists $w.none_r]} {
149 radiobutton $w.none_r \
153 grid $w.none_r -sticky we -padx {0 5} -columnspan 2
155 $w.none_r configure -text $text
163 set i [$w_list curselection]
165 return [lindex $cur_specs $i 0]
172 expr { return $c_expr }
174 default { error "unknown type of revision" }
178 method pick_tracking_branch {} {
182 method focus_filter {} {
183 if {[$w_filter cget -state] eq {normal}} {
188 method get_local_branch {} {
189 if {$revtype eq {head}} {
196 method get_tracking_branch {} {
197 set i [$w_list curselection]
198 if {$i eq {} || $revtype ne {trck}} {
201 return [lrange [lindex $cur_specs $i] 1 end]
204 method get_commit {} {
209 return [git rev-parse --verify "$e^0"]
212 method commit_or_die {} {
213 if {[catch {set new [get_commit $this]} err]} {
215 # Cleanup the not-so-friendly error from rev-parse.
217 regsub {^fatal:\s*} $err {} err
218 if {$err eq {Needed a single revision}} {
222 set top [winfo toplevel $w]
223 set msg "Invalid revision: [get $this]\n\n$err"
227 -title [wm title $top] \
240 set i [$w_list curselection]
242 return [lindex $cur_specs $i 1]
244 error "No revision selected."
252 error "Revision expression is empty."
257 default { error "unknown type of revision" }
261 method _validate {d S} {
263 if {[regexp {\s} $S]} {
266 if {[string length $S] > 0} {
274 if {[regexp {\s} $P]} {
281 method _select {args} {
282 _rebuild $this $filter
286 method _rebuild {pat} {
289 head { set new $spec_head }
290 trck { set new $spec_trck }
291 tag { set new $spec_tag }
300 if {[$w_list cget -state] eq {disabled}} {
301 $w_list configure -state normal
310 set txt [lindex $spec 0]
311 if {$pat eq {} || [string match $pat $txt]} {
312 lappend cur_specs $spec
313 $w_list insert end $txt
316 if {$cur_specs ne {}} {
317 $w_list selection clear 0 end
318 $w_list selection set 0
321 if {[$w_filter cget -state] ne $ste} {
322 $w_list configure -state $ste
323 $w_filter configure -state $ste
327 method _delete {current} {
328 if {$current eq $w} {
333 method _sb_set {sb orient first last} {
334 set old_focus [focus -lastfor $w]
336 if {$first == 0 && $last == 1} {
337 if {[winfo exists $sb]} {
339 if {$old_focus ne {}} {
347 if {![winfo exists $sb]} {
348 if {$orient eq {h}} {
349 scrollbar $sb -orient h -command [list $w_list xview]
350 pack $sb -fill x -side bottom -before $w_list
352 scrollbar $sb -orient v -command [list $w_list yview]
353 pack $sb -fill y -side right -before $w_list
355 if {$old_focus ne {}} {