git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[RFC PATCH] Make gitk use --early-output

From
Paul Mackerras <paulus@samba.org>
Date
Nov 3, 2007, 23:49 UTC
Message-ID
<18221.2285.259487.655684@cargo.ozlabs.ibm.com>
This makes gitk use the --early-output flag on the git log command.

When gitk sees the "Final output:" line from git log, it goes into a mode where it basically just checks that it is getting the commits again in the same order as before. If they are, well and good; if not, it truncates its internal list at the point of difference and proceeds to read in the commits in the new order from there on, and re-does the graph layout if necessary.

This gives a much more immediate feel to the startup; gitk shows its window with the first screenful of commits displayed very quickly this way.

Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/gitk b/gitk
index 1da0b0a..7d9a2f2 100755
--- a/gitk
+++ b/gitk
@@ -84,25 +84,27 @@ proc start_rev_list {view} {
     global commfd leftover tclencoding datemode
     global viewargs viewfiles commitidx viewcomplete vnextroot
     global showlocalchanges commitinterest mainheadid
-    global progressdirn progresscoords proglastnc curview
+    global progressdirn progresscoords proglastnc curview rereading
 
     set startmsecs [clock clicks -milliseconds]
     set commitidx($view) 0
     set viewcomplete($view) 0
     set vnextroot($view) 0
-    set order "--topo-order"
+    set order "--early-output=50"
     if {$datemode} {
-	set order "--date-order"
+	lappend order "--date-order"
     }
     if {[catch {
-	set fd [open [concat | git log --no-color -z --pretty=raw $order --parents \
-			 --boundary $viewargs($view) "--" $viewfiles($view)] r]
+	set fd [open [concat | git log --no-color -z --pretty=raw \
+			  $order --parents --boundary \
+			  $viewargs($view) "--" $viewfiles($view)] r]
     } err]} {
 	error_popup "Error executing git rev-list: $err"
 	exit 1
     }
     set commfd($view) $fd
     set leftover($view) {}
+    set rereading($view) -1
     if {$showlocalchanges} {
 	lappend commitinterest($mainheadid) {dodiffindex}
     }
@@ -161,6 +163,7 @@ proc getcommitlines {fd view}  {
     global parentlist children curview hlview
     global vparentlist vdisporder vcmitlisted
     global ordertok vnextroot idpending
+    global rereading nullid nullid2
 
     set stuff [read $fd 500000]
     # git log doesn't terminate the last commit with a null...
@@ -236,6 +239,15 @@ proc getcommitlines {fd view}  {
 	}
 	set start [expr {$i + 1}]
 	set j [string first "\n" $cmit]
+	if {$j >= 0 && [string match "Final output:*" $cmit]} {
+	    set rereading($view) 0
+	    set cmit [string range $cmit [expr {$j + 1}] end]
+	    set j [string first "\n" $cmit]
+	    if {$view == $curview} {
+		layoutmore
+		update
+	    }
+	}
 	set ok 0
 	set listed 1
 	if {$j >= 0 && [string match "commit *" $cmit]} {
@@ -255,6 +267,7 @@ proc getcommitlines {fd view}  {
 		    break
 		}
 	    }
+	    set cmit [string range $cmit [expr {$j + 1}] end]
 	}
 	if {!$ok} {
 	    set shortcmit $cmit
@@ -265,13 +278,31 @@ proc getcommitlines {fd view}  {
 	    exit 1
 	}
 	set id [lindex $ids 0]
+	if {$rereading($view) >= 0} {
+	    set r $rereading($view)
+	    set oldid [lindex $displayorder $r]
+	    while {$oldid eq $nullid || $oldid eq $nullid2} {
+		set oldid [lindex $displayorder [incr r]]
+	    }
+	    if {$oldid eq $id} {
+		# commits are still in the same order; just skip to the next
+		set rereading($view) [expr {$r + 1}]
+		continue
+	    }
+	    if {$r < $commitidx($view)} {
+		# commits are in a different order now;
+		# truncate the list and redisplay
+		truncate_view $view $r
+	    }
+	    set rereading($view) -1
+	}
 	if {![info exists ordertok($view,$id)]} {
 	    set otok "o[strrep $vnextroot($view)]"
 	    incr vnextroot($view)
 	    set ordertok($view,$id) $otok
 	} else {
 	    set otok $ordertok($view,$id)
-	    unset idpending($view,$id)
+	    catch {unset idpending($view,$id)}
 	}
 	if {$listed} {
 	    set olds [lrange $ids 1 end]
@@ -301,7 +332,7 @@ proc getcommitlines {fd view}  {
 	if {![info exists children($view,$id)]} {
 	    set children($view,$id) {}
 	}
-	set commitdata($id) [string range $cmit [expr {$j + 1}] end]
+	set commitdata($id) $cmit
 	set commitrow($view,$id) $commitidx($view)
 	incr commitidx($view)
 	if {$view == $curview} {
@@ -323,7 +354,7 @@ proc getcommitlines {fd view}  {
     }
     if {$gotsome} {
 	run chewcommits $view
-	if {$view == $curview} {
+	if {0 && $view == $curview} {
 	    # update progress bar
 	    global progressdirn progresscoords proglastnc
 	    set inc [expr {($commitidx($view) - $proglastnc) * 0.0002}]
@@ -354,6 +385,43 @@ proc getcommitlines {fd view}  {
     return 2
 }
 
+proc truncate_view {view row} {
+    global curview commitidx displayorder parentlist commitlisted
+    global vdisporder vparentlist vcmitlisted commitrow children
+    global numcommits localfrow localirow
+
+    set rm1 [expr {$row - 1}]
+    if {$view == $curview} {
+	set disporder $displayorder
+	set displayorder [lrange $disporder 0 $rm1]
+	set parents $parentlist
+	set parentlist [lrange $parents 0 $rm1]
+	set commitlisted [lrange $commitlisted 0 $rm1]
+    } else {
+	set disporder $vdisporder($view)
+	set vdisporder($view) [lrange $disporder 0 $rm1]
+	set parents $vparentlist($view)
+	set vparentlist($view) [lrange $parents 0 $rm1]
+	set vcmitlisted($view) [lrange $vcmitlisted($view) 0 $rm1]
+    }
+    for {set r $commitidx($view)} {[incr r -1] >= $row} {} {
+	set id [lindex $disporder $r]
+	foreach p [lindex $parents $r] {
+	    if {[lindex $children($view,$p) end] eq $id} {
+		set children($view,$p) [lrange $children($view,$p) 0 end-1]
+	    }
+	}
+	unset commitrow($view,$id)
+    }
+    set commitidx($view) $row
+    if {$view == $curview} {
+	truncate_localchanges $row
+	if {$row < $numcommits} {
+	    undolayout $row
+	}
+    }
+}
+
 proc chewcommits {view} {
     global curview hlview viewcomplete
     global selectedline pending_select
@@ -2843,6 +2911,20 @@ proc dohidelocalchanges {} {
     incr lserial
 }
 
+proc truncate_localchanges {row} {
+    global localfrow localirow
+
+    if {$localfrow >= $row} {
+	set localfrow -1
+    }
+    if {$localirow >= $row} {
+	set localirow -1
+    }
+    if {$localfrow == $row - 1 || $localirow == $row - 1} {
+	dohidelocalchanges
+    }
+}
+
 # spawn off a process to do git diff-index --cached HEAD
 proc dodiffindex {} {
     global localirow localfrow lserial showlocalchanges
@@ -3840,6 +3922,23 @@ proc drawcommits {row {endrow {}}} {
     }
 }
 
+proc undolayout {row} {
+    global uparrowlen mingaplen downarrowlen
+    global rowidlist rowisopt rowfinal need_redisplay
+
+    set r [expr {$row - ($uparrowlen + $mingaplen + $downarrowlen)}]
+    if {$r < 0} {
+	set r 0
+    }
+    if {[llength $rowidlist] > $r} {
+	set rowidlist [lrange $rowidlist 0 $r]
+	set rowfinal [lrange $rowfinal 0 $r]
+	set rowisopt [lrange $rowisopt 0 $r]
+	set need_redisplay 1
+	run drawvisible
+    }
+}
+
 proc drawfrac {f0 f1} {
     global canv linespc
 
Next: Michael J. Cohen
Message 1 of 8 in “Make gitk use --early-output”
  1. Make gitk use --early-outputPaul Mackerras, Nov 3, 2007
  2. Michael J. CohenNov 4, 2007
  3. Linus TorvaldsNov 4, 2007
  4. Marco CostalbaNov 4, 2007
  5. Paul MackerrasNov 4, 2007
  6. Marco CostalbaNov 4, 2007
  7. Linus TorvaldsNov 4, 2007
  8. David KastrupNov 4, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.