gitk: Implement batch lookup and caching of encoding attrs

When the diff contains thousands of files, calling git-check-attr once
per file is very slow.  With this patch gitk does attribute lookup in
batches of 30 files while reading the diff file list, which leads to a
very noticeable speedup.

It may be possible to reimplement this even more efficiently, if
git-check-attr is modified to support a --stdin-paths option.
Additionally, it should quote the ':' character in file paths, or
provide a more robust way of column separation.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
Tested-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Alexander Gavrilov 2008-10-13 12:12:33 +04:00 коммит произвёл Paul Mackerras
Родитель 09c7029dfa
Коммит 4db09304f9
1 изменённых файлов: 34 добавлений и 1 удалений

35
gitk
Просмотреть файл

@ -6531,6 +6531,7 @@ proc gettreediffline {gdtf ids} {
global cmitmode vfilelimit curview limitdiffs
set nr 0
set sublist {}
while {[incr nr] <= 1000 && [gets $gdtf line] >= 0} {
set i [string first "\t" $line]
if {$i >= 0} {
@ -6540,8 +6541,10 @@ proc gettreediffline {gdtf ids} {
}
set file [encoding convertfrom $file]
lappend treediff $file
lappend sublist $file
}
}
cache_gitattr encoding $sublist
if {![eof $gdtf]} {
return [expr {$nr >= 1000? 2: 1}]
}
@ -9816,18 +9819,48 @@ proc tcl_encoding {enc} {
}
proc gitattr {path attr default} {
if {[catch {set r [exec git check-attr $attr -- $path]}]} {
global path_attr_cache
if {[info exists path_attr_cache($attr,$path)]} {
set r $path_attr_cache($attr,$path)
} elseif {[catch {set r [exec git check-attr $attr -- $path]}]} {
set r unspecified
} else {
set r [join [lrange [split $r :] 2 end] :]
regsub {^ } $r {} r
}
set path_attr_cache($attr,$path) $r
if {$r eq {unspecified}} {
return $default
}
return $r
}
proc cache_gitattr {attr pathlist} {
global path_attr_cache
set newlist {}
foreach path $pathlist {
if {[info exists path_attr_cache($attr,$path)]} continue
lappend newlist $path
}
while {$newlist ne {}} {
set head [lrange $newlist 0 29]
set newlist [lrange $newlist 30 end]
if {![catch {set rlist [eval exec git check-attr $attr -- $head]}]} {
foreach row [split $rlist "\n"] {
set cols [split $row :]
set path [lindex $cols 0]
set value [join [lrange $cols 2 end] :]
if {[string index $path 0] eq "\""} {
set path [encoding convertfrom [lindex $path 0]]
}
regsub {^ } $value {} value
set path_attr_cache($attr,$path) $value
}
}
update
}
}
proc get_path_encoding {path} {
global gui_encoding
set tcl_enc [tcl_encoding $gui_encoding]