Subject: Re: [PATCH (GIT-GUI,GITK) 6/8] gitk: Port new encoding logic from git-gui.

From: Alexander Gavrilov <[email-masked]>
Date: Mon, 22 Sep 2008 12:01:35 +0400

On Monday 22 September 2008 11:25:43 Johannes Sixt wrote:
> Alexander Gavrilov schrieb:
> > Subject: [PATCH] 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.
> 
> This one does not work for me: The correct is not picked up anymore,
> neither in Patch mode nor Tree mode. (It works as expected without this
> patch.)
> 

OOPS, I forgot to copy the line that removes leading whitespace:

@@ -9876,6 +9876,7 @@ proc cache_gitattr {attr pathlist} {
                                if {[string index $path 0] eq "\""} {
                                        set path [encoding convertfrom [lindex $path 0]]
                                }
+                               regsub {^ } $value {} value
                                set path_attr_cache($attr,$path) $value
                        }
                }

> > +				set cols [split $row :]
> > +				set path [lindex $cols 0]
> 
> This colon made me nervous (because of the drive-colon combination on
> Windows), but as long as you feed relative paths into 'git check-attr',
> this should not matter (in my case).

I'm afraid there is nothing to be done about it without changing git-check-attr.
For example, it could quote ':' in the path in octal -- current interface allows it.
But since the path is relative, it is not a big deal.

--- >8 ---
From: Alexander Gavrilov <[email-masked]>
Subject: [PATCH v2] 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.

Signed-off-by: Alexander Gavrilov <[email-masked]>
---
 gitk |   35 ++++++++++++++++++++++++++++++++++-
 1 files changed, 34 insertions(+), 1 deletions(-)

diff --git a/gitk b/gitk
index 1355aa2..cf557c3 100755
--- a/gitk
+++ b/gitk
@@ -6530,6 +6530,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} {
@@ -6539,8 +6540,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}]
     }
@@ -9839,18 +9842,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]
-- 
1.6.0.20.g6148bc