Skip to content

Commit 52b8ea9

Browse files
committed
gitk: Fix possible infinite loop and display corruption
This fixes an issue reported by Johannes Sixt on the git mailing list: > This recipe sends gitk into an endless loop. In git.git do: > > cd t > # remove chmod a+x A near the end of the file > sed -i 's/chmod/: chmod/' t3400-rebase.sh > sh t3400-rebase.sh --debug > cd trash\ directory.t3400-rebase/ > gitk master modechange modechange@{1} > > > I briefly see the history chart, but the dot that should be modechange@{1} > is missing. One automatically selected commit is shown in the diff section > below. But then the commit list is cleared and gitk goes into an infinite > loop. > > Things work alright if either modechange@{1} is dropped, or the 'chmod' > line is left unchanged, which is a bit strange. > > This is with git version 1.6.1.2.390.gba743 There were actually two problems. This recipe created a situation where git log would output a child commit after its parent. This meant that we called fix_reversal which called splitvarc, which should call modify_arc to note the fact that it has modified the arc that it has just split. It wasn't, which meant that displayorder and other variables got into an inconsistent state (a commit appearing twice in displayorder). This then meant that the targetrow/targetid logic in drawvisible thought it need to redraw each time. That, together with the fact that drawvisible called drawcommits which called drawvisible if a redraw was needed, led to the infinite loop. In fact drawvisible is now the only caller of drawcommits. Thus, the start and end row arguments to drawcommits always encompass the whole visible area, so drawcommits doesn't need to call drawvisible to redraw; it just needs to clear the screen and draw what it's been asked to. This fixes these two problems by adding a call to modify_arc in splitvarc and by taking out the call to drawvisible in drawcommits. It also removes an unrelated left-over debugging puts in external_blame. Signed-off-by: Paul Mackerras <paulus@samba.org>
1 parent e4df519 commit 52b8ea9

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

gitk

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -701,16 +701,17 @@ proc newvarc {view id} {
701701
}
702702

703703
proc splitvarc {p v} {
704-
global varcid varcstart varccommits varctok
704+
global varcid varcstart varccommits varctok vtokmod
705705
global vupptr vdownptr vleftptr vbackptr varcix varcrow vlastins
706706

707707
set oa $varcid($v,$p)
708+
set otok [lindex $varctok($v) $oa]
708709
set ac $varccommits($v,$oa)
709710
set i [lsearch -exact $varccommits($v,$oa) $p]
710711
if {$i <= 0} return
711712
set na [llength $varctok($v)]
712713
# "%" sorts before "0"...
713-
set tok "[lindex $varctok($v) $oa]%[strrep $i]"
714+
set tok "$otok%[strrep $i]"
714715
lappend varctok($v) $tok
715716
lappend varcrow($v) {}
716717
lappend varcix($v) {}
@@ -730,6 +731,9 @@ proc splitvarc {p v} {
730731
for {set b [lindex $vdownptr($v) $na]} {$b != 0} {set b [lindex $vleftptr($v) $b]} {
731732
lset vupptr($v) $b $na
732733
}
734+
if {[string compare $otok $vtokmod($v)] <= 0} {
735+
modify_arc $v $oa
736+
}
733737
}
734738

735739
proc renumbervarc {a v} {
@@ -3363,7 +3367,6 @@ proc external_blame {parent_idx {line {}}} {
33633367
# being given an absolute path...
33643368
set f [make_relative $f]
33653369
lappend cmdline $base_commit $f
3366-
puts "cmdline={$cmdline}"
33673370
if {[catch {eval exec $cmdline &} err]} {
33683371
error_popup "[mc "git gui blame: command failed:"] $err"
33693372
}
@@ -5731,7 +5734,6 @@ proc drawcommits {row {endrow {}}} {
57315734
optimize_rows $ro1 0 $r2
57325735
if {$need_redisplay || $nrows_drawn > 2000} {
57335736
clear_display
5734-
drawvisible
57355737
}
57365738

57375739
# make the lines join to already-drawn rows either side

0 commit comments

Comments
 (0)