Add graft support.
[git.git] / gitk
diff --git a/gitk b/gitk
index 1bc0d88..c443d95 100755 (executable)
--- a/gitk
+++ b/gitk
@@ -18,7 +18,7 @@ proc gitdir {} {
 
 proc getcommits {rargs} {
     global commits commfd phase canv mainfont env
-    global startmsecs nextupdate
+    global startmsecs nextupdate ncmupdate
     global ctext maincursor textcursor leftover
 
     # check that we can find a .git directory somewhere...
@@ -31,6 +31,7 @@ proc getcommits {rargs} {
     set phase getcommits
     set startmsecs [clock clicks -milliseconds]
     set nextupdate [expr $startmsecs + 100]
+    set ncmupdate 1
     if [catch {
        set parse_args [concat --default HEAD $rargs]
        set parsed_args [split [eval exec git-rev-parse $parse_args] "\n"]
@@ -49,7 +50,7 @@ proc getcommits {rargs} {
     }
     set leftover {}
     fconfigure $commfd -blocking 0 -translation lf
-    fileevent $commfd readable "getcommitlines $commfd"
+    fileevent $commfd readable [list getcommitlines $commfd]
     $canv delete all
     $canv create text 3 3 -anchor nw -text "Reading commits..." \
        -font $mainfont -tags textitems
@@ -109,7 +110,7 @@ to allow selection of commits to be displayed.)}
        parsecommit $id $cmit 1
        drawcommit $id
        if {[clock clicks -milliseconds] >= $nextupdate} {
-           doupdate
+           doupdate 1
        }
        while {$redisplaying} {
            set redisplaying 0
@@ -120,7 +121,7 @@ to allow selection of commits to be displayed.)}
                    drawcommit $id
                    if {$stopped} break
                    if {[clock clicks -milliseconds] >= $nextupdate} {
-                       doupdate
+                       doupdate 1
                    }
                }
            }
@@ -128,13 +129,24 @@ to allow selection of commits to be displayed.)}
     }
 }
 
-proc doupdate {} {
-    global commfd nextupdate
+proc doupdate {reading} {
+    global commfd nextupdate numcommits ncmupdate
 
-    incr nextupdate 100
-    fileevent $commfd readable {}
+    if {$reading} {
+       fileevent $commfd readable {}
+    }
     update
-    fileevent $commfd readable "getcommitlines $commfd"
+    set nextupdate [expr {[clock clicks -milliseconds] + 100}]
+    if {$numcommits < 100} {
+       set ncmupdate [expr {$numcommits + 1}]
+    } elseif {$numcommits < 10000} {
+       set ncmupdate [expr {$numcommits + 10}]
+    } else {
+       set ncmupdate [expr {$numcommits + 100}]
+    }
+    if {$reading} {
+       fileevent $commfd readable [list getcommitlines $commfd]
+    }
 }
 
 proc readcommit {id} {
@@ -144,6 +156,7 @@ proc readcommit {id} {
 
 proc parsecommit {id contents listed} {
     global commitinfo children nchildren parents nparents cdate ncleft
+    global grafts
 
     set inhdr 1
     set comment {}
@@ -159,13 +172,32 @@ proc parsecommit {id contents listed} {
     }
     set parents($id) {}
     set nparents($id) 0
+    set grafted 0
+    if {[info exists grafts($id)]} {
+       set grafted 1
+       set parents($id) $grafts($id)
+       set nparents($id) [llength $grafts($id)]
+       if {$listed} {
+           foreach p $grafts($id) {
+               if {![info exists nchildren($p)]} {
+                   set children($p) [list $id]
+                   set nchildren($p) 1
+                   set ncleft($p) 1
+               } elseif {[lsearch -exact $children($p) $id] < 0} {
+                   lappend children($p) $id
+                   incr nchildren($p)
+                   incr ncleft($p)
+               }
+           }
+       }
+    }
     foreach line [split $contents "\n"] {
        if {$inhdr} {
            if {$line == {}} {
                set inhdr 0
            } else {
                set tag [lindex $line 0]
-               if {$tag == "parent"} {
+               if {$tag == "parent" && !$grafted} {
                    set p [lindex $line 1]
                    if {![info exists nchildren($p)]} {
                        set children($p) {}
@@ -261,6 +293,32 @@ proc readrefs {} {
     }
 }
 
+proc readgrafts {} {
+    global grafts env
+    catch {
+       set graftfile info/grafts
+       if {[info exists env(GIT_GRAFT_FILE)]} {
+           set graftfile $env(GIT_GRAFT_FILE)
+       }
+       set fd [open [gitdir]/$graftfile r]
+       while {[gets $fd line] >= 0} {
+           if {[string match "#*" $line]} continue
+           set ok 1
+           foreach x $line {
+               if {![regexp {^[0-9a-f]{40}$} $x]} {
+                   set ok 0
+                   break
+               }
+           }
+           if {$ok} {
+               set id [lindex $line 0]
+               set grafts($id) [lrange $line 1 end]
+           }
+       }
+       close $fd
+    }
+}
+
 proc error_popup msg {
     set w .error
     toplevel $w
@@ -1090,7 +1148,7 @@ proc decidenext {{noread 0}} {
 
 proc drawcommit {id} {
     global phase todo nchildren datemode nextupdate
-    global startcommits
+    global startcommits numcommits ncmupdate
 
     if {$phase != "incrdraw"} {
        set phase incrdraw
@@ -1119,8 +1177,9 @@ proc drawcommit {id} {
            if {![info exists commitlisted($id)]} {
                break
            }
-           if {[clock clicks -milliseconds] >= $nextupdate} {
-               doupdate
+           if {[clock clicks -milliseconds] >= $nextupdate
+               && $numcommits >= $ncmupdate} {
+               doupdate 1
                if {$stopped} break
            }
        }
@@ -1158,11 +1217,12 @@ proc settextcursor {c} {
 }
 
 proc drawgraph {} {
-    global nextupdate startmsecs startcommits todo
+    global nextupdate startmsecs startcommits todo ncmupdate
 
     if {$startcommits == {}} return
     set startmsecs [clock clicks -milliseconds]
     set nextupdate [expr $startmsecs + 100]
+    set ncmupdate 1
     initgraph
     set todo [lindex $startcommits 0]
     drawrest 0 1
@@ -1171,7 +1231,7 @@ proc drawgraph {} {
 proc drawrest {level startix} {
     global phase stopped redisplaying selectedline
     global datemode currentparents todo
-    global numcommits
+    global numcommits ncmupdate
     global nextupdate startmsecs startcommits idline
 
     if {$level >= 0} {
@@ -1200,9 +1260,9 @@ proc drawrest {level startix} {
                if {$level < 0} break
                drawslants $level
            }
-           if {[clock clicks -milliseconds] >= $nextupdate} {
-               update
-               incr nextupdate 100
+           if {[clock clicks -milliseconds] >= $nextupdate
+               && $numcommits >= $ncmupdate} {
+               doupdate 0
            }
        }
     }
@@ -3188,4 +3248,5 @@ set patchnum 0
 setcoords
 makewindow
 readrefs
+readgrafts
 getcommits $revtreeargs