field c_tag {}; # selected tag
field c_expr {}; # current revision expression
+field trck_spec ; # array of specifications
+
constructor new {path {title {}}} {
global all_heads current_branch
trace add variable @c_head write [cb _select head]
}
- set all_trackings [all_tracking_branches]
- if {$all_trackings ne {}} {
- set c_trck [lindex $all_trackings 0]
+ set trck_list [all_tracking_branches]
+ if {$trck_list ne {}} {
+ set nam [list]
+ foreach spec $trck_list {
+ set txt [lindex $spec 0]
+ regsub ^refs/(heads/|remotes/)? $txt {} txt
+ set trck_spec($txt) $spec
+ lappend nam $txt
+ }
+ set nam [lsort -unique $nam]
+
radiobutton $w.trck_r \
-text {Tracking Branch:} \
-value trck \
-variable @revtype
- eval tk_optionMenu $w.trck_m @c_trck $all_trackings
+ eval tk_optionMenu $w.trck_m @c_trck $nam
grid $w.trck_r $w.trck_m -sticky w
+
+ set c_trck [lindex $nam 0]
if {$revtype eq {}} {
set revtype trck
}
trace add variable @c_trck write [cb _select trck]
+ unset nam spec txt
}
set all_tags [load_all_tags]
}
}
+method get_expr {} {
+ switch -- $revtype {
+ head { return refs/heads/$c_head }
+ trck { return [lindex $trck_spec($c_trck) 0] }
+ tag { return refs/tags/$c_tag }
+ expr { return $c_expr }
+ none { return {} }
+ default { error "unknown type of revision" }
+ }
+}
+
method get_commit {} {
if {$revtype eq {none}} {
return {}
}
- set rev [get $this]
- return [git rev-parse --verify "${rev}^0"]
+ return [git rev-parse --verify "[get_expr $this]^0"]
}
method _validate {d S} {
proc all_tracking_branches {} {
global tracking_branches
- set all_trackings {}
- set cmd {}
+ set all [list]
+ set pat [list]
+ set cmd [list]
+
foreach spec $tracking_branches {
- set name [lindex $spec 0]
- if {[string range $name end-1 end] eq {/*}} {
- lappend cmd [string range $name 0 end-2]
+ set dst [lindex $spec 0]
+ if {[string range $dst end-1 end] eq {/*}} {
+ lappend pat $spec
+ lappend cmd [string range $dst 0 end-2]
} else {
- regsub ^refs/(heads|remotes)/ $name {} name
- lappend all_trackings $name
+ lappend all $spec
}
}
- if {$cmd ne {}} {
+ if {$pat ne {}} {
set fd [open "| git for-each-ref --format=%(refname) $cmd" r]
- while {[gets $fd name] > 0} {
- regsub ^refs/(heads|remotes)/ $name {} name
- lappend all_trackings $name
+ while {[gets $fd n] > 0} {
+ foreach spec $pat {
+ set dst [string range [lindex $spec 0] 0 end-2]
+ set len [string length $dst]
+ if {[string equal -length $len $dst $n]} {
+ set src [string range [lindex $spec 2] 0 end-2]
+ set spec [list \
+ $n \
+ [lindex $spec 1] \
+ $src[string range $n $len end] \
+ ]
+ lappend all $spec
+ }
+ }
}
close $fd
}
- return [lsort -unique $all_trackings]
+ return [lsort -index 0 -unique $all]
}
proc load_all_remotes {} {
while {[gets $fd line] >= 0} {
if {![regexp {^Pull:[ ]*([^:]+):(.+)$} \
$line line src dst]} continue
+ if {[string index $src 0] eq {+}} {
+ set src [string range $src 1 end]
+ }
if {![string equal -length 5 refs/ $src]} {
set src $rh_str$src
}
}
foreach line $fl {
if {![regexp {^([^:]+):(.+)$} $line line src dst]} continue
+ if {[string index $src 0] eq {+}} {
+ set src [string range $src 1 end]
+ }
if {![string equal -length 5 refs/ $src]} {
set src $rh_str$src
}