@ -12,30 +12,31 @@ exec wish "$0" -- "${1+$@}"
proc getcommits {rargs} {
proc getcommits {rargs} {
global commits commfd phase canv mainfont
global commits commfd phase canv mainfont
global startmsecs nextupdate
global startmsecs nextupdate
global ctext maincursor textcursor nlines
global ctext maincursor textcursor leftover
set commits {}
set commits {}
set phase getcommits
set phase getcommits
set startmsecs [clock clicks -milliseconds]
set startmsecs [clock clicks -milliseconds]
set nextupdate [expr $startmsecs + 100]
set nextupdate [expr $startmsecs + 100]
if [catch {
if [catch {
set parse_args [concat --default HEAD --merge-order $rargs]
set parse_args [concat --default HEAD $rargs]
set parsed_args [split [eval exec git-rev-parse $parse_args] "\n"]
set parsed_args [split [eval exec git-rev-parse $parse_args] "\n"]
}] {
}] {
# if git-rev-parse failed for some reason...
if {$rargs == {}} {
if {$rargs == {}} {
set rargs HEAD
set rargs HEAD
}
}
set parsed_args [concat --merge-order $rargs]
set parsed_args $rargs
}
}
if [catch {
if [catch {
set commfd [open "|git-rev-list $parsed_args" r]
set commfd [open "|git-rev-list --header --merge-order $parsed_args" r]
} err] {
} err] {
puts stderr "Error executing git-rev-list: $err"
puts stderr "Error executing git-rev-list: $err"
exit 1
exit 1
}
}
set nlines 0
set leftover {}
fconfigure $commfd -blocking 0
fconfigure $commfd -blocking 0 -translation binary
fileevent $commfd readable "getcommitline $commfd"
fileevent $commfd readable "getcommitlines $commfd"
$canv delete all
$canv delete all
$canv create text 3 3 -anchor nw -text "Reading commits..." \
$canv create text 3 3 -anchor nw -text "Reading commits..." \
-font $mainfont -tags textitems
-font $mainfont -tags textitems
@ -43,13 +44,13 @@ proc getcommits {rargs} {
$ctext config -cursor watch
$ctext config -cursor watch
}
}
proc getcommitline {commfd} {
proc getcommitlines {commfd} {
global commits parents cdate children nchildren
global commits parents cdate children nchildren
global commitlisted phase commitinfo nextupdate
global commitlisted phase commitinfo nextupdate
global stopped redisplaying nlines
global stopped redisplaying leftover
set n [gets $commfd line]
set stuff [read $commfd]
if {$n < 0} {
if {$stuff == {}} {
if {![eof $commfd]} return
if {![eof $commfd]} return
# this works around what is apparently a bug in Tcl...
# this works around what is apparently a bug in Tcl...
fconfigure $commfd -blocking 1
fconfigure $commfd -blocking 1
@ -68,35 +69,41 @@ to allow selection of commits to be displayed.)}
error_popup $err
error_popup $err
exit 1
exit 1
}
}
incr nlines
set start 0
if {![regexp {^[0-9a-f]{40}$} $line id]} {
while 1 {
error_popup "Can't parse git-rev-list output: {$line}"
set i [string first "\0" $stuff $start]
exit 1
if {$i < 0} {
}
set leftover [string range $stuff $start end]
lappend commits $id
return
set commitlisted($id) 1
if {![info exists commitinfo($id)]} {
readcommit $id
}
foreach p $parents($id) {
if {[info exists commitlisted($p)]} {
puts "oops, parent $p before child $id"
}
}
}
set cmit [string range $stuff $start [expr {$i - 1}]]
drawcommit $id
if {$start == 0} {
if {[clock clicks -milliseconds] >= $nextupdate} {
set cmit "$leftover$cmit"
doupdate
}
}
set start [expr {$i + 1}]
while {$redisplaying} {
if {![regexp {^([0-9a-f]{40})\n} $cmit match id]} {
set redisplaying 0
error_popup "Can't parse git-rev-list output: {$cmit}"
if {$stopped == 1} {
exit 1
set stopped 0
}
set phase "getcommits"
set cmit [string range $cmit 41 end]
foreach id $commits {
lappend commits $id
drawcommit $id
set commitlisted($id) 1
if {$stopped} break
parsecommit $id $cmit 1
if {[clock clicks -milliseconds] >= $nextupdate} {
drawcommit $id
doupdate
if {[clock clicks -milliseconds] >= $nextupdate} {
doupdate
}
while {$redisplaying} {
set redisplaying 0
if {$stopped == 1} {
set stopped 0
set phase "getcommits"
foreach id $commits {
drawcommit $id
if {$stopped} break
if {[clock clicks -milliseconds] >= $nextupdate} {
doupdate
}
}
}
}
}
}
}
@ -109,12 +116,16 @@ proc doupdate {} {
incr nextupdate 100
incr nextupdate 100
fileevent $commfd readable {}
fileevent $commfd readable {}
update
update
fileevent $commfd readable "getcommitline $commfd"
fileevent $commfd readable "getcommitlines $commfd"
}
}
proc readcommit {id} {
proc readcommit {id} {
if [catch {set contents [exec git-cat-file commit $id]}] return
parsecommit $id $contents 0
}
proc parsecommit {id contents listed} {
global commitinfo children nchildren parents nparents cdate ncleft
global commitinfo children nchildren parents nparents cdate ncleft
global noreadobj
set inhdr 1
set inhdr 1
set comment {}
set comment {}
@ -130,13 +141,6 @@ proc readcommit {id} {
}
}
set parents($id) {}
set parents($id) {}
set nparents($id) 0
set nparents($id) 0
if {$noreadobj} {
if [catch {set contents [exec git-cat-file commit $id]}] return
} else {
if [catch {set x [readobj $id]}] return
if {[lindex $x 0] != "commit"} return
set contents [lindex $x 1]
}
foreach line [split $contents "\n"] {
foreach line [split $contents "\n"] {
if {$inhdr} {
if {$inhdr} {
if {$line == {}} {
if {$line == {}} {
@ -153,7 +157,7 @@ proc readcommit {id} {
lappend parents($id) $p
lappend parents($id) $p
incr nparents($id)
incr nparents($id)
# sometimes we get a commit that lists a parent twice...
# sometimes we get a commit that lists a parent twice...
if {[lsearch -exact $children($p) $id] < 0} {
if {$listed && [lsearch -exact $children($p) $id] < 0} {
lappend children($p) $id
lappend children($p) $id
incr nchildren($p)
incr nchildren($p)
incr ncleft($p)
incr ncleft($p)
@ -545,7 +549,7 @@ proc assigncolor {id} {
global parents nparents children nchildren
global parents nparents children nchildren
if [info exists colormap($id)] return
if [info exists colormap($id)] return
set ncolors [llength $colors]
set ncolors [llength $colors]
if {$nparents($id) == 1 && $nchildren($id) == 1} {
if {$nparents($id) <= 1 && $nchildren($id) == 1} {
set child [lindex $children($id) 0]
set child [lindex $children($id) 0]
if {[info exists colormap($child)]
if {[info exists colormap($child)]
&& $nparents($child) == 1} {
&& $nparents($child) == 1} {
@ -583,7 +587,7 @@ proc assigncolor {id} {
proc initgraph {} {
proc initgraph {} {
global canvy canvy0 lineno numcommits lthickness nextcolor linespc
global canvy canvy0 lineno numcommits lthickness nextcolor linespc
global glines
global mainline sidelines
global nchildren ncleft
global nchildren ncleft
allcanvs delete all
allcanvs delete all
@ -592,7 +596,8 @@ proc initgraph {} {
set lineno -1
set lineno -1
set numcommits 0
set numcommits 0
set lthickness [expr {int($linespc / 9) + 1}]
set lthickness [expr {int($linespc / 9) + 1}]
catch {unset glines}
catch {unset mainline}
catch {unset sidelines}
foreach id [array names nchildren] {
foreach id [array names nchildren] {
set ncleft($id) $nchildren($id)
set ncleft($id) $nchildren($id)
}
}
@ -610,12 +615,11 @@ proc bindline {t id} {
proc drawcommitline {level} {
proc drawcommitline {level} {
global parents children nparents nchildren todo
global parents children nparents nchildren todo
global canv canv2 canv3 mainfont namefont canvx0 canvy linespc
global canv canv2 canv3 mainfont namefont canvx0 canvy linespc
global datemode cdate
global lineid linehtag linentag linedtag commitinfo
global lineid linehtag linentag linedtag commitinfo
global colormap numcommits currentparents dupparents
global colormap numcommits currentparents dupparents
global oldlevel oldnlines oldtodo
global oldlevel oldnlines oldtodo
global idtags idline idheads
global idtags idline idheads
global lineno lthickness glines
global lineno lthickness mainline sidelines
global commitlisted
global commitlisted
incr numcommits
incr numcommits
@ -631,6 +635,7 @@ proc drawcommitline {level} {
set nparents($id) 0
set nparents($id) 0
}
}
}
}
assigncolor $id
set currentparents {}
set currentparents {}
set dupparents {}
set dupparents {}
if {[info exists commitlisted($id)] && [info exists parents($id)]} {
if {[info exists commitlisted($id)] && [info exists parents($id)]} {
@ -648,21 +653,31 @@ proc drawcommitline {level} {
set canvy [expr $canvy + $linespc]
set canvy [expr $canvy + $linespc]
allcanvs conf -scrollregion \
allcanvs conf -scrollregion \
[list 0 0 0 [expr $y1 + 0.5 * $linespc + 2]]
[list 0 0 0 [expr $y1 + 0.5 * $linespc + 2]]
if {[info exists glines($id)]} {
if {[info exists mainline($id)]} {
lappend glines($id) $x $y1
lappend mainline($id) $x $y1
set t [$canv create line $glines($id) \
set t [$canv create line $mainline($id) \
-width $lthickness -fill $colormap($id)]
-width $lthickness -fill $colormap($id)]
$canv lower $t
$canv lower $t
bindline $t $id
bindline $t $id
}
}
if {[info exists sidelines($id)]} {
foreach ls $sidelines($id) {
set coords [lindex $ls 0]
set thick [lindex $ls 1]
set t [$canv create line $coords -fill $colormap($id) \
-width [expr {$thick * $lthickness}]]
$canv lower $t
bindline $t $id
}
}
set orad [expr {$linespc / 3}]
set orad [expr {$linespc / 3}]
set t [$canv create oval [expr $x - $orad] [expr $y1 - $orad] \
set t [$canv create oval [expr $x - $orad] [expr $y1 - $orad] \
[expr $x + $orad - 1] [expr $y1 + $orad - 1] \
[expr $x + $orad - 1] [expr $y1 + $orad - 1] \
-fill $ofill -outline black -width 1]
-fill $ofill -outline black -width 1]
$canv raise $t
$canv raise $t
set xt [expr $canvx0 + [llength $todo] * $linespc]
set xt [expr $canvx0 + [llength $todo] * $linespc]
if {$nparents($id) > 2} {
if {[llength $currentparents] > 2} {
set xt [expr {$xt + ($nparents($id) - 2) * $linespc}]
set xt [expr {$xt + ([llength $currentparents] - 2) * $linespc}]
}
}
set marks {}
set marks {}
set ntags 0
set ntags 0
@ -718,38 +733,32 @@ proc drawcommitline {level} {
}
}
proc updatetodo {level noshortcut} {
proc updatetodo {level noshortcut} {
global datemode currentparents ncleft todo
global currentparents ncleft todo
global glines oldlevel oldtodo oldnlines
global mainline oldlevel oldtodo oldnlines
global canvx0 canvy linespc glines
global canvx0 canvy linespc mainline
global commitinfo
global commitinfo
foreach p $currentparents {
set oldlevel $level
if {![info exists commitinfo($p)]} {
set oldtodo $todo
readcommit $p
set oldnlines [llength $todo]
}
}
set x [expr $canvx0 + $level * $linespc]
set y [expr $canvy - $linespc]
if {!$noshortcut && [llength $currentparents] == 1} {
if {!$noshortcut && [llength $currentparents] == 1} {
set p [lindex $currentparents 0]
set p [lindex $currentparents 0]
if {$ncleft($p) == 0 && [lsearch -exact $todo $p] < 0} {
if {$ncleft($p) == 1 && [lsearch -exact $todo $p] < 0} {
assigncolor $p
set ncleft($p) 0
set glines($p) [list $x $y]
set x [expr $canvx0 + $level * $linespc]
set y [expr $canvy - $linespc]
set mainline($p) [list $x $y]
set todo [lreplace $todo $level $level $p]
set todo [lreplace $todo $level $level $p]
return 0
return 0
}
}
}
}
set oldlevel $level
set oldtodo $todo
set oldnlines [llength $todo]
set todo [lreplace $todo $level $level]
set todo [lreplace $todo $level $level]
set i $level
set i $level
foreach p $currentparents {
foreach p $currentparents {
incr ncleft($p) -1
incr ncleft($p) -1
set k [lsearch -exact $todo $p]
set k [lsearch -exact $todo $p]
if {$k < 0} {
if {$k < 0} {
assigncolor $p
set todo [linsert $todo $i $p]
set todo [linsert $todo $i $p]
incr i
incr i
}
}
@ -758,7 +767,7 @@ proc updatetodo {level noshortcut} {
}
}
proc drawslants {} {
proc drawslants {} {
global canv glines canvx0 canvy linespc
global canv mainline sidelines canvx0 canvy linespc
global oldlevel oldtodo todo currentparents dupparents
global oldlevel oldtodo todo currentparents dupparents
global lthickness linespc canvy colormap
global lthickness linespc canvy colormap
@ -782,33 +791,27 @@ proc drawslants {} {
if {[lsearch -exact $dupparents $p] >= 0} {
if {[lsearch -exact $dupparents $p] >= 0} {
# draw a double-width line to indicate the doubled parent
# draw a double-width line to indicate the doubled parent
lappend coords $xj $y2
lappend coords $xj $y2
set t [$canv create line $coords \
lappend sidelines($p) [list $coords 2]
-width [expr 2*$lthickness] -fill $colormap($p)]
if {![info exists mainline($p)]} {
$canv lower $t
set mainline($p) [list $xj $y2]
bindline $t $p
if {![info exists glines($p)]} {
set glines($p) [list $xj $y2]
}
}
} else {
} else {
# normal case, no parent duplicated
# normal case, no parent duplicated
if {![info exists glines($p)]} {
if {![info exists mainline($p)]} {
if {$i != $j} {
if {$i != $j} {
lappend coords $xj $y2
lappend coords $xj $y2
}
}
set glines($p) $coords
set mainline($p) $coords
} else {
} else {
lappend coords $xj $y2
lappend coords $xj $y2
set t [$canv create line $coords \
lappend sidelines($p) [list $coords 1]
-width $lthickness -fill $colormap($p)]
$canv lower $t
bindline $t $p
}
}
}
}
}
}
} elseif {[lindex $todo $i] != $id} {
} elseif {[lindex $todo $i] != $id} {
set j [lsearch -exact $todo $id]
set j [lsearch -exact $todo $id]
set xj [expr {$canvx0 + $j * $linespc}]
set xj [expr {$canvx0 + $j * $linespc}]
lappend glines($id) $xi $y1 $xj $y2
lappend mainline($id) $xi $y1 $xj $y2
}
}
}
}
}
}
@ -849,7 +852,7 @@ proc decidenext {} {
if {$todo != {}} {
if {$todo != {}} {
puts "ERROR: none of the pending commits can be done yet:"
puts "ERROR: none of the pending commits can be done yet:"
foreach p $todo {
foreach p $todo {
puts " $p"
puts " $p ($ncleft($p))"
}
}
}
}
return -1
return -1
@ -888,14 +891,12 @@ proc drawcommit {id} {
set todo $id
set todo $id
set startcommits $id
set startcommits $id
initgraph
initgraph
assigncolor $id
drawcommitline 0
drawcommitline 0
updatetodo 0 $datemode
updatetodo 0 $datemode
} else {
} else {
if {$nchildren($id) == 0} {
if {$nchildren($id) == 0} {
lappend todo $id
lappend todo $id
lappend startcommits $id
lappend startcommits $id
assigncolor $id
}
}
set level [decidenext]
set level [decidenext]
if {$id != [lindex $todo $level]} {
if {$id != [lindex $todo $level]} {
@ -1636,7 +1637,6 @@ foreach arg $argv {
}
}
}
}
set noreadobj [catch {load libreadobj.so.0.0}]
set stopped 0
set stopped 0
set redisplaying 0
set redisplaying 0
set stuffsaved 0
set stuffsaved 0