From 8ed164841564802cc0b063a6b365fb19e9a513d1 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 2 Mar 2006 22:56:44 +1100 Subject: gitk: Further speedups Now we don't parse the commits as we are reading them, we just put commit data on a list as a blob, and instead parse the commit when we need the various parts of it, such as when a commit is drawn on the canvas. This makes searching a bit more interesting: now we scan through the commit blobs doing a string or regexp match to find commits that might match, then for those that might match, we parse the commit info (if it isn't already parsed) and do the matching for the various fields as before. Signed-off-by: Paul Mackerras diff --git a/gitk b/gitk index cca9d35..8d7b258 100755 --- a/gitk +++ b/gitk @@ -35,6 +35,7 @@ proc parse_args {rargs} { proc start_rev_list {rlargs} { global startmsecs nextupdate ncmupdate global commfd leftover tclencoding datemode + global commitdata set startmsecs [clock clicks -milliseconds] set nextupdate [expr {$startmsecs + 100}] @@ -52,6 +53,7 @@ proc start_rev_list {rlargs} { exit 1 } set leftover {} + set commitdata {} fconfigure $commfd -blocking 0 -translation lf if {$tclencoding != {}} { fconfigure $commfd -encoding $tclencoding @@ -72,11 +74,9 @@ proc getcommits {rargs} { } proc getcommitlines {commfd} { - global parents cdate children nchildren - global commitlisted commitinfo phase nextupdate - global stopped leftover - global canv - global displayorder commitidx commitrow + global commitlisted nextupdate + global leftover + global displayorder commitidx commitrow commitdata set stuff [read $commfd] if {$stuff == {}} { @@ -136,12 +136,9 @@ proc getcommitlines {commfd} { } set id [lindex $ids 0] set olds [lrange $ids 1 end] - set cmit [string range $cmit [expr {$j + 1}] end] set commitlisted($id) 1 updatechildren $id [lrange $ids 1 end] - if {![info exists commitinfo($id)]} { - parsecommit $id $cmit 1 - } + lappend commitdata [string range $cmit [expr {$j + 1}] end] set commitrow($id) $commitidx incr commitidx lappend displayorder $id @@ -269,6 +266,25 @@ proc parsecommit {id contents listed} { $comname $comdate $comment] } +proc getcommit {id {row {}}} { + global commitdata commitrow commitinfo nparents + + if {$row eq {}} { + if {![info exists commitrow($id)]} {return 0} + set row $commitrow($id) + } + if {$row < [llength $commitdata]} { + parsecommit $id [lindex $commitdata $row] 1 + } else { + readcommit $id + if {![info exists commitinfo($id)]} { + set commitinfo($id) {"No commit information available"} + set nparents($id) 0 + } + } + return 1 +} + proc readrefs {} { global tagids idtags headids idheads tagcontents global otherrefids idotherrefs @@ -1317,6 +1333,7 @@ proc drawcmitrow {row} { global displayorder rowidlist global idrowranges idrangedrawn iddrawn global commitinfo commitlisted parents numcommits + global commitdata if {$row >= $numcommits} return foreach id [lindex $rowidlist $row] { @@ -1344,11 +1361,7 @@ proc drawcmitrow {row} { return } if {![info exists commitinfo($id)]} { - readcommit $id - if {![info exists commitinfo($id)]} { - set commitinfo($id) {"No commit information available"} - set nparents($id) 0 - } + getcommit $id $row } assigncolor $id if {[info exists commitlisted($id)] && [info exists parents($id)] @@ -1604,19 +1617,19 @@ proc xcoord {i level ln} { } proc finishcommits {} { - global phase + global commitidx phase global canv mainfont ctext maincursor textcursor - if {$phase == "incrdraw"} { + if {$commitidx > 0} { drawrest } else { $canv delete all $canv create text 3 3 -anchor nw -text "No commits selected" \ -font $mainfont -tags textitems - set phase {} } . config -cursor $maincursor settextcursor $textcursor + set phase {} } # Don't change the text pane cursor if it is currently the hand cursor, @@ -1672,7 +1685,8 @@ proc dofind {} { global findtype findloc findstring markedmatches commitinfo global numcommits displayorder linehtag linentag linedtag global mainfont namefont canv canv2 canv3 selectedline - global matchinglines foundstring foundstrlen + global matchinglines foundstring foundstrlen matchstring + global commitdata stopfindproc unmarkmatches @@ -1689,6 +1703,8 @@ proc dofind {} { } set foundstrlen [string length $findstring] if {$foundstrlen == 0} return + regsub -all {[*?\[\\]} $foundstring {\\&} matchstring + set matchstring "*$matchstring*" if {$findloc == "Files"} { findfiles return @@ -1700,8 +1716,21 @@ proc dofind {} { } set didsel 0 set fldtypes {Headline Author Date Committer CDate Comment} - for {set l 0} {$l < $numcommits} {incr l} { + set l -1 + foreach d $commitdata { + incr l + if {$findtype == "Regexp"} { + set doesmatch [regexp $foundstring $d] + } elseif {$findtype == "IgnCase"} { + set doesmatch [string match -nocase $matchstring $d] + } else { + set doesmatch [string match $matchstring $d] + } + if {!$doesmatch} continue set id [lindex $displayorder $l] + if {![info exists commitinfo($id)]} { + getcommit $id $l + } set info $commitinfo($id) set doesmatch 0 foreach f $info ty $fldtypes { @@ -2069,7 +2098,7 @@ proc findcont {id} { # mark a commit as matching by putting a yellow background # behind the headline proc markheadline {l id} { - global canv mainfont linehtag commitinfo + global canv mainfont linehtag drawcmitrow $l set bbox [$canv bbox $linehtag($l)] @@ -2725,9 +2754,9 @@ proc gotocommit {} { set id [string tolower $sha1string] if {[regexp {^[0-9a-f]{4,39}$} $id]} { set matches {} - for {set l 0} {$l < $numcommits} {incr l} { - if {[string match $id* [lindex $displayorder $l]]} { - lappend matches [lindex $displayorder $l] + foreach i $displayorder { + if {[string match $id* $i]} { + lappend matches $i } } if {$matches ne {}} { @@ -2755,7 +2784,7 @@ proc lineenter {x y id} { global hoverx hovery hoverid hovertimer global commitinfo canv - if {![info exists commitinfo($id)]} return + if {![info exists commitinfo($id)] && ![getcommit $id]} return set hoverx $x set hovery $y set hoverid $id @@ -2849,6 +2878,7 @@ proc arrowjump {id n y} { proc lineclick {x y id isnew} { global ctext commitinfo children cflist canv thickerline + if {![info exists commitinfo($id)] && ![getcommit $id]} return unmarkmatches unselectline normalline @@ -2890,6 +2920,7 @@ proc lineclick {x y id isnew} { set i 0 foreach child $children($id) { incr i + if {![info exists commitinfo($child)] && ![getcommit $child]} continue set info $commitinfo($child) $ctext insert end "\n\t" $ctext insert end $child [list link link$i] -- cgit v0.10.2-6-g49f6