Subject: [PATCH] gitk: Prevent garbage text at the end of the tag description

From: Björn Gustavsson <[email-masked]>
Date: Tue, 13 Oct 2009 09:34:28 +0200

When first clicking on a commit with a huge diff (in 1000 files
or more), and then clicking on a tag, garbage text could appear
after the tag description.

The problem is that commits are shown incrementally using a
run queue (implemented by the runq() and filerun() procedures).
When the user requests a tag to be shown, there may still be
jobs in the run queue updating the previous commit.

Solve this problem by implementing a new procedure
empty_run_queue() that will empty the run queue and cancel all
outstanding file events. Call it from showtag().

Signed-off-by: Björn Gustavsson <[email-masked]>
---

This is more an annoyance than a real bug, but I was quite
surprised the first time I saw it happen and at first searched
for a bug in my own scripts that had created the tags.

This patch is a suggested correction.

Here is an example of a repository where the problem can be
reproduced quite easily:

git://github.com/mfoemmel/erlang-otp.git

 gitk-git/gitk |   34 ++++++++++++++++++++++++++++++++--
 1 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/gitk-git/gitk b/gitk-git/gitk
index a0214b7..ee0d0c3 100644
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -34,12 +34,16 @@ proc run args {
 }
 
 proc filerun {fd script} {
+    global pending_file_events
+
+    set pending_file_events($fd) $fd
     fileevent $fd readable [list filereadable $fd $script]
 }
 
 proc filereadable {fd script} {
-    global runq currunq
+    global runq currunq pending_file_events
 
+    unset pending_file_events($fd)
     fileevent $fd readable {}
     if {$runq eq {} && ![info exists currunq]} {
 	after idle dorunq
@@ -60,7 +64,7 @@ proc nukefile {fd} {
 }
 
 proc dorunq {} {
-    global isonrunq runq currunq
+    global isonrunq runq currunq pending_file_events
 
     set tstart [clock clicks -milliseconds]
     set t0 $tstart
@@ -79,6 +83,7 @@ proc dorunq {} {
 		# file readers return 2 if they could do more straight away
 		lappend runq [list $fd $script]
 	    } else {
+		set pending_file_events($fd) $fd
 		fileevent $fd readable [list filereadable $fd $script]
 	    }
 	} elseif {$fd eq {}} {
@@ -92,6 +97,29 @@ proc dorunq {} {
     }
 }
 
+# Empty the run queue, cancel all outstanding file events,
+# and close all files associated with file events.
+proc empty_run_queue {} {
+    global isonrunq runq pending_file_events
+
+    foreach entry $runq {
+	set fd [lindex $entry 0]
+	set script [lindex $entry 1]
+	if {$fd eq {}} {
+	    unset isonrunq($script)
+	} else {
+	    catch {close $fd}
+	}
+    }
+    set runq {}
+
+    foreach fd [array names pending_file_events] {
+	fileevent $fd readable {}
+	unset pending_file_events($fd)
+	catch {close $fd}
+    }
+}
+
 proc reg_instance {fd} {
     global commfd leftover loginstance
 
@@ -10261,6 +10289,8 @@ proc listrefs {id} {
 proc showtag {tag isnew} {
     global ctext tagcontents tagids linknum tagobjid
 
+    empty_run_queue
+
     if {$isnew} {
 	addtohistory [list showtag $tag 0]
     }
-- 
1.6.5.2.gd6127