From: Paul Mackerras Date: Wed, 12 Dec 2007 07:13:51 +0000 (+1100) Subject: gitk: Fix more bugs resulting in Tcl "no such element in array" errors X-Git-Tag: v1.5.6-rc0~20^2~40 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=e5b37ac1ec6f1500a47a320a261933bccbdeb4f7;p=git.git gitk: Fix more bugs resulting in Tcl "no such element in array" errors First, update_arcrows was being overly aggressive in trimming displayorder, resulting in calls to rowofcommit sometimes trimming off commits that layoutrows had asked for in make_disporder and was relying on having present. This adds a vrowmod($view) variable that lets update_arcrows be more precise in trimming off the invalid bits of displayorder (and it also simplifies the check in make_disporder). This modifies modify_arc and its callers so that vrowmod($view) is updated appropriately. Secondly, we were sometimes calling idcol with $i==-1, which resulted in a call to ordertoken with the null string. This fixes it by forcing $i to 0 if it is less than zero. This also fixes a possible infinite recursion with rowofcommit and update_arcrows calling each other ad infinitum. Signed-off-by: Paul Mackerras --- diff --git a/gitk b/gitk index 9d1dd77d6..9c5de3f45 100755 --- a/gitk +++ b/gitk @@ -268,7 +268,7 @@ proc strrep {n} { proc varcinit {view} { global vseeds varcstart vupptr vdownptr vleftptr varctok varcrow - global vtokmod varcmod varcix uat + global vtokmod varcmod vrowmod varcix uat set vseeds($view) {} set varcstart($view) {{}} @@ -279,6 +279,7 @@ proc varcinit {view} { set varcrow($view) {{}} set vtokmod($view) {} set varcmod($view) 0 + set vrowmod($view) 0 set varcix($view) {{}} set uat 0 } @@ -307,7 +308,7 @@ proc resetvarcs {view} { proc newvarc {view id} { global varcid varctok parents children vseeds global vupptr vdownptr vleftptr varcrow varcix varcstart - global commitdata commitinfo vseedcount + global commitdata commitinfo vseedcount varccommits set a [llength $varctok($view)] set vid $view,$id @@ -377,6 +378,7 @@ proc newvarc {view id} { lappend vdownptr($view) 0 lappend varcrow($view) {} lappend varcix($view) {} + set varccommits($view,$a) {} return $a } @@ -547,7 +549,7 @@ proc insertrow {id p v} { # note we deliberately don't update varcstart($v) even if $i == 0 set varccommits($v,$a) [linsert $varccommits($v,$a) $i $id] if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} { - modify_arc $v $a + modify_arc $v $a $i } drawvisible } @@ -579,7 +581,7 @@ proc removerow {id v} { } set tok [lindex $varctok($v) $a] if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} { - modify_arc $v $a + modify_arc $v $a $i } drawvisible } @@ -591,22 +593,30 @@ proc vtokcmp {v a b} { [lindex $varctok($v) $varcid($v,$b)]] } -proc modify_arc {v a} { - global varctok vtokmod varcmod varcrow vupptr curview +proc modify_arc {v a {lim {}}} { + global varctok vtokmod varcmod varcrow vupptr curview vrowmod varccommits set vtokmod($v) [lindex $varctok($v) $a] set varcmod($v) $a if {$v == $curview} { while {$a != 0 && [lindex $varcrow($v) $a] eq {}} { set a [lindex $vupptr($v) $a] + set lim {} } - set r [expr {$a == 0? 0: [lindex $varcrow($v) $a]}] + set r 0 + if {$a != 0} { + if {$lim eq {}} { + set lim [llength $varccommits($v,$a)] + } + set r [expr {[lindex $varcrow($v) $a] + $lim}] + } + set vrowmod($v) $r undolayout $r } } proc update_arcrows {v} { - global vtokmod varcmod varcrow commitidx currentid selectedline + global vtokmod varcmod vrowmod varcrow commitidx currentid selectedline global varcid vseeds vrownum varcorder varcix varccommits global vupptr vdownptr vleftptr varctok global uat displayorder parentlist curview cached_commitrow @@ -640,11 +650,11 @@ proc update_arcrows {v} { } set row [lindex $varcrow($v) $a] } - if {[llength $displayorder] > $row} { - set displayorder [lrange $displayorder 0 [expr {$row - 1}]] - set parentlist [lrange $parentlist 0 [expr {$row - 1}]] - } if {$v == $curview} { + if {[llength $displayorder] > $vrowmod($v)} { + set displayorder [lrange $displayorder 0 [expr {$vrowmod($v) - 1}]] + set parentlist [lrange $parentlist 0 [expr {$vrowmod($v) - 1}]] + } catch {unset cached_commitrow} } while {1} { @@ -668,11 +678,12 @@ proc update_arcrows {v} { lset varcix($v) $a $arcn lset varcrow($v) $a $row } + set vtokmod($v) [lindex $varctok($v) $p] + set varcmod($v) $p + set vrowmod($v) $row if {[info exists currentid]} { set selectedline [rowofcommit $currentid] } - set vtokmod($v) [lindex $varctok($v) $p] - set varcmod($v) $p set t2 [clock clicks -milliseconds] incr uat [expr {$t2-$t1}] } @@ -734,13 +745,10 @@ proc bsearch {l elt} { # Make sure rows $start..$end-1 are valid in displayorder and parentlist proc make_disporder {start end} { global vrownum curview commitidx displayorder parentlist - global varccommits varcorder parents varcmod varcrow + global varccommits varcorder parents vrowmod varcrow global d_valid_start d_valid_end - set la $varcmod($curview) - set lrow [lindex $varcrow($curview) $la] - if {$la == 0 || $lrow eq {} || \ - $end > $lrow + [llength $varccommits($curview,$la)]} { + if {$end > $vrowmod($curview)} { update_arcrows $curview } set ai [bsearch $vrownum($curview) $start] @@ -808,10 +816,10 @@ proc closevarcs {v} { set b [newvarc $v $p] } set varcid($v,$p) $b - lappend varccommits($v,$b) $p if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} { modify_arc $v $b } + lappend varccommits($v,$b) $p incr commitidx($v) if {[info exists commitinterest($p)]} { foreach script $commitinterest($p) { @@ -958,8 +966,11 @@ proc getcommitlines {fd inst view} { set a [newvarc $view $id] } set varcid($vid) $a + if {[string compare [lindex $varctok($view) $a] $vtokmod($view)] < 0} { + modify_arc $view $a + } lappend varccommits($view,$a) $id - set tok [lindex $varctok($view) $a] + set i 0 foreach p $olds { if {$i == 0 || [lsearch -exact $olds $p] >= $i} { @@ -976,9 +987,6 @@ proc getcommitlines {fd inst view} { } incr i } - if {[string compare $tok $vtokmod($view)] < 0} { - modify_arc $view $a - } incr commitidx($view) if {[info exists commitinterest($id)]} { @@ -3345,6 +3353,9 @@ proc ordertoken {id} { # values increase from left to right proc idcol {idlist id {i 0}} { set t [ordertoken $id] + if {$i < 0} { + set i 0 + } if {$i >= [llength $idlist] || $t < [ordertoken [lindex $idlist $i]]} { if {$i > [llength $idlist]} { set i [llength $idlist]