Code

gitk: Fix potential bug with fake commit IDs in renumbervarc
[git.git] / gitk
diff --git a/gitk b/gitk
index aadc18db92e8a5f02d65bf0b332a73c5755decea..fda06186b4dcf7d42560cd1ac6cf25d06e295925 100755 (executable)
--- a/gitk
+++ b/gitk
@@ -234,7 +234,7 @@ proc updatecommits {} {
 proc reloadcommits {} {
     global curview viewcomplete selectedline currentid thickerline
     global showneartags treediffs commitinterest cached_commitrow
-    global progresscoords
+    global progresscoords targetid
 
     if {!$viewcomplete($curview)} {
        stop_rev_list $curview
@@ -254,6 +254,7 @@ proc reloadcommits {} {
     clear_display
     catch {unset commitinterest}
     catch {unset cached_commitrow}
+    catch {unset targetid}
     setcanvscroll
     getcommits
 }
@@ -461,8 +462,8 @@ proc renumbervarc {a v} {
            set tok $oldtok
        }
        set ka 0
-       if {[llength $children($v,$id)] > 0} {
-           set kid [lindex $children($v,$id) end]
+       set kid [last_real_child $v,$id]
+       if {$kid ne {}} {
            set k $varcid($v,$kid)
            if {[string compare [lindex $varctok($v) $k] $tok] > 0} {
                set ki $kid
@@ -561,7 +562,7 @@ proc fix_reversal {p a v} {
 
 proc insertrow {id p v} {
     global varcid varccommits parents children cmitlisted
-    global commitidx varctok vtokmod
+    global commitidx varctok vtokmod targetid targetrow
 
     set a $varcid($v,$p)
     set i [lsearch -exact $varccommits($v,$a) $p]
@@ -580,12 +581,18 @@ proc insertrow {id p v} {
     if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} {
        modify_arc $v $a $i
     }
+    if {[info exists targetid]} {
+       if {![comes_before $targetid $p]} {
+           incr targetrow
+       }
+    }
     drawvisible
 }
 
 proc removerow {id v} {
     global varcid varccommits parents children commitidx
     global varctok vtokmod cmitlisted currentid selectedline
+    global targetid
 
     if {[llength $parents($v,$id)] != 1} {
        puts "oops: removerow [shortids $id] has [llength $parents($v,$id)] parents"
@@ -615,9 +622,36 @@ proc removerow {id v} {
        unset currentid
        unset selectedline
     }
+    if {[info exists targetid] && $targetid eq $id} {
+       set targetid $p
+    }
     drawvisible
 }
 
+proc first_real_child {vp} {
+    global children nullid nullid2
+
+    foreach id $children($vp) {
+       if {$id ne $nullid && $id ne $nullid2} {
+           return $id
+       }
+    }
+    return {}
+}
+
+proc last_real_child {vp} {
+    global children nullid nullid2
+
+    set kids $children($vp)
+    for {set i [llength $kids]} {[incr i -1] >= 0} {} {
+       set id [lindex $kids $i]
+       if {$id ne $nullid && $id ne $nullid2} {
+           return $id
+       }
+    }
+    return {}
+}
+
 proc vtokcmp {v a b} {
     global varctok varcid
 
@@ -756,6 +790,22 @@ proc rowofcommit {id} {
     return $i
 }
 
+# Returns 1 if a is on an earlier row than b, otherwise 0
+proc comes_before {a b} {
+    global varcid varctok curview
+
+    set v $curview
+    if {$a eq $b || ![info exists varcid($v,$a)] || \
+           ![info exists varcid($v,$b)]} {
+       return 0
+    }
+    if {$varcid($v,$a) != $varcid($v,$b)} {
+       return [expr {[string compare [lindex $varctok($v) $varcid($v,$a)] \
+                          [lindex $varctok($v) $varcid($v,$b)]] < 0}]
+    }
+    return [expr {[rowofcommit $a] < [rowofcommit $b]}]
+}
+
 proc bsearch {l elt} {
     if {[llength $l] == 0 || $elt <= [lindex $l 0]} {
        return 0
@@ -3350,17 +3400,12 @@ proc ordertoken {id} {
            set tok $ordertok($p)
            break
        }
-       if {[llength $children($curview,$p)] == 0} {
+       set id [first_real_child $curview,$p]
+       if {$id eq {}} {
            # it's a root
            set tok [lindex $varctok($curview) $a]
            break
        }
-       set id [lindex $children($curview,$p) 0]
-       if {$id eq $nullid || $id eq $nullid2} {
-           # XXX treat it as a root
-           set tok [lindex $varctok($curview) $a]
-           break
-       }
        if {[llength $parents($curview,$id)] == 1} {
            lappend todo [list $p {}]
        } else {
@@ -4540,7 +4585,7 @@ proc undolayout {row} {
 
 proc drawvisible {} {
     global canv linespc curview vrowmod selectedline targetrow targetid
-    global need_redisplay cscroll
+    global need_redisplay cscroll numcommits
 
     set fs [$canv yview]
     set ymax [lindex [$canv cget -scrollregion] 3]
@@ -4551,21 +4596,25 @@ proc drawvisible {} {
     set y1 [expr {int($f1 * $ymax)}]
 
     if {[info exists targetid]} {
-       set r [rowofcommit $targetid]
-       if {$r != $targetrow} {
-           # Fix up the scrollregion and change the scrolling position
-           # now that our target row has moved.
-           set diff [expr {($r - $targetrow) * $linespc}]
-           set targetrow $r
-           setcanvscroll
-           set ymax [lindex [$canv cget -scrollregion] 3]
-           incr y0 $diff
-           incr y1 $diff
-           set f0 [expr {$y0 / $ymax}]
-           set f1 [expr {$y1 / $ymax}]
-           allcanvs yview moveto $f0
-           $cscroll set $f0 $f1
-           set need_redisplay 1
+       if {[commitinview $targetid $curview]} {
+           set r [rowofcommit $targetid]
+           if {$r != $targetrow} {
+               # Fix up the scrollregion and change the scrolling position
+               # now that our target row has moved.
+               set diff [expr {($r - $targetrow) * $linespc}]
+               set targetrow $r
+               setcanvscroll
+               set ymax [lindex [$canv cget -scrollregion] 3]
+               incr y0 $diff
+               incr y1 $diff
+               set f0 [expr {$y0 / $ymax}]
+               set f1 [expr {$y1 / $ymax}]
+               allcanvs yview moveto $f0
+               $cscroll set $f0 $f1
+               set need_redisplay 1
+           }
+       } else {
+           unset targetid
        }
     }
 
@@ -4580,6 +4629,9 @@ proc drawvisible {} {
     } else {
        set targetrow [expr {int(($row + $endrow) / 2)}]
     }
+    if {$targetrow >= $numcommits} {
+       set targetrow [expr {$numcommits - 1}]
+    }
     set targetid [commitonrow $targetrow]
     drawcommits $row $endrow
 }
@@ -4917,7 +4969,7 @@ proc findmore {} {
     global commitdata commitinfo numcommits findpattern findloc
     global findstartline findcurline findallowwrap
     global find_dirn gdttype fhighlights fprogcoord
-    global curview varcorder vrownum varccommits
+    global curview varcorder vrownum varccommits vrowmod
 
     if {![info exists find_dirn]} {
        return 0
@@ -4953,6 +5005,9 @@ proc findmore {} {
        set n 500
        set moretodo 1
     }
+    if {$l + ($find_dirn > 0? $n: 1) > $vrowmod($curview)} {
+       update_arcrows $curview
+    }
     set found 0
     set domore 1
     set ai [bsearch $vrownum($curview) $l]
@@ -4999,14 +5054,18 @@ proc findmore {} {
            }
            set id [lindex $ids [expr {$l - $arow}]]
            if {![info exists fhighlights($l)]} {
+               # this sets fhighlights($l) to -1
                askfilehighlight $l $id
+           }
+           if {$fhighlights($l) > 0} {
+               set found $domore
+               break
+           }
+           if {$fhighlights($l) < 0} {
                if {$domore} {
                    set domore 0
                    set findcurline [expr {$l - $find_dirn}]
                }
-           } elseif {$fhighlights($l)} {
-               set found $domore
-               break
            }
        }
     }