2 # Tcl ignores the next line -*- tcl -*- \
3 exec wish "$0" -- "${1+$@}"
5 # Copyright (C) 2005 Paul Mackerras. All rights reserved.
6 # This program is free software; it may be used, copied, modified
7 # and distributed under the terms of the GNU General Public Licence,
8 # either version 2, or (at your option) any later version.
10 proc getcommits {rargs} {
11 global commits commfd phase canv mainfont env
12 global startmsecs nextupdate
13 global ctext maincursor textcursor leftover
15 # check that we can find a .git directory somewhere...
16 if {[info exists env(GIT_DIR)]} {
17 set gitdir $env(GIT_DIR)
21 if {![file isdirectory $gitdir]} {
22 error_popup "Cannot find the git directory \"$gitdir\"."
27 set startmsecs [clock clicks -milliseconds]
28 set nextupdate [expr $startmsecs + 100]
30 set parse_args [concat --default HEAD $rargs]
31 set parsed_args [split [eval exec git-rev-parse $parse_args] "\n"]
33 # if git-rev-parse failed for some reason...
37 set parsed_args $rargs
40 set commfd [open "|git-rev-list --header --merge-order $parsed_args" r]
42 puts stderr "Error executing git-rev-list: $err"
46 fconfigure $commfd -blocking 0 -translation binary
47 fileevent $commfd readable "getcommitlines $commfd"
49 $canv create text 3 3 -anchor nw -text "Reading commits..." \
50 -font $mainfont -tags textitems
51 . config -cursor watch
52 $ctext config -cursor watch
55 proc getcommitlines {commfd} {
56 global commits parents cdate children nchildren
57 global commitlisted phase commitinfo nextupdate
58 global stopped redisplaying leftover
60 set stuff [read $commfd]
62 if {![eof $commfd]} return
63 # this works around what is apparently a bug in Tcl...
64 fconfigure $commfd -blocking 1
65 if {![catch {close $commfd} err]} {
66 after idle finishcommits
69 if {[string range $err 0 4] == "usage"} {
71 {Gitk: error reading commits: bad arguments to git-rev-list.
72 (Note: arguments to gitk are passed to git-rev-list
73 to allow selection of commits to be displayed.)}
75 set err "Error reading commits: $err"
82 set i [string first "\0" $stuff $start]
84 set leftover [string range $stuff $start end]
87 set cmit [string range $stuff $start [expr {$i - 1}]]
89 set cmit "$leftover$cmit"
91 set start [expr {$i + 1}]
92 if {![regexp {^([0-9a-f]{40})\n} $cmit match id]} {
93 error_popup "Can't parse git-rev-list output: {$cmit}"
96 set cmit [string range $cmit 41 end]
98 set commitlisted($id) 1
99 parsecommit $id $cmit 1
101 if {[clock clicks -milliseconds] >= $nextupdate} {
104 while {$redisplaying} {
108 set phase "getcommits"
109 foreach id $commits {
112 if {[clock clicks -milliseconds] >= $nextupdate} {
122 global commfd nextupdate
125 fileevent $commfd readable {}
127 fileevent $commfd readable "getcommitlines $commfd"
130 proc readcommit {id} {
131 if [catch {set contents [exec git-cat-file commit $id]}] return
132 parsecommit $id $contents 0
135 proc parsecommit {id contents listed} {
136 global commitinfo children nchildren parents nparents cdate ncleft
145 if {![info exists nchildren($id)]} {
152 foreach line [split $contents "\n"] {
157 set tag [lindex $line 0]
158 if {$tag == "parent"} {
159 set p [lindex $line 1]
160 if {![info exists nchildren($p)]} {
165 lappend parents($id) $p
167 # sometimes we get a commit that lists a parent twice...
168 if {$listed && [lsearch -exact $children($p) $id] < 0} {
169 lappend children($p) $id
173 } elseif {$tag == "author"} {
174 set x [expr {[llength $line] - 2}]
175 set audate [lindex $line $x]
176 set auname [lrange $line 1 [expr {$x - 1}]]
177 } elseif {$tag == "committer"} {
178 set x [expr {[llength $line] - 2}]
179 set comdate [lindex $line $x]
180 set comname [lrange $line 1 [expr {$x - 1}]]
184 if {$comment == {}} {
185 set headline [string trim $line]
190 # git-rev-list indents the comment by 4 spaces;
191 # if we got this via git-cat-file, add the indentation
198 set audate [clock format $audate -format "%Y-%m-%d %H:%M:%S"]
200 if {$comdate != {}} {
201 set cdate($id) $comdate
202 set comdate [clock format $comdate -format "%Y-%m-%d %H:%M:%S"]
204 set commitinfo($id) [list $headline $auname $audate \
205 $comname $comdate $comment]
209 global tagids idtags headids idheads
210 set tags [glob -nocomplain -types f .git/refs/tags/*]
215 if {[regexp {^[0-9a-f]{40}} $line id]} {
216 set direct [file tail $f]
217 set tagids($direct) $id
218 lappend idtags($id) $direct
219 set contents [split [exec git-cat-file tag $id] "\n"]
223 foreach l $contents {
225 switch -- [lindex $l 0] {
226 "object" {set obj [lindex $l 1]}
227 "type" {set type [lindex $l 1]}
228 "tag" {set tag [string range $l 4 end]}
231 if {$obj != {} && $type == "commit" && $tag != {}} {
232 set tagids($tag) $obj
233 lappend idtags($obj) $tag
239 set heads [glob -nocomplain -types f .git/refs/heads/*]
243 set line [read $fd 40]
244 if {[regexp {^[0-9a-f]{40}} $line id]} {
245 set head [file tail $f]
246 set headids($head) $line
247 lappend idheads($line) $head
254 proc error_popup msg {
258 message $w.m -text $msg -justify center -aspect 400
259 pack $w.m -side top -fill x -padx 20 -pady 20
260 button $w.ok -text OK -command "destroy $w"
261 pack $w.ok -side bottom -fill x
262 bind $w <Visibility> "grab $w; focus $w"
267 global canv canv2 canv3 linespc charspc ctext cflist textfont
268 global findtype findloc findstring fstring geometry
269 global entries sha1entry sha1string sha1but
270 global maincursor textcursor
274 .bar add cascade -label "File" -menu .bar.file
276 .bar.file add command -label "Quit" -command doquit
278 .bar add cascade -label "Help" -menu .bar.help
279 .bar.help add command -label "About gitk" -command about
280 . configure -menu .bar
282 if {![info exists geometry(canv1)]} {
283 set geometry(canv1) [expr 45 * $charspc]
284 set geometry(canv2) [expr 30 * $charspc]
285 set geometry(canv3) [expr 15 * $charspc]
286 set geometry(canvh) [expr 25 * $linespc + 4]
287 set geometry(ctextw) 80
288 set geometry(ctexth) 30
289 set geometry(cflistw) 30
291 panedwindow .ctop -orient vertical
292 if {[info exists geometry(width)]} {
293 .ctop conf -width $geometry(width) -height $geometry(height)
294 set texth [expr {$geometry(height) - $geometry(canvh) - 56}]
295 set geometry(ctexth) [expr {($texth - 8) /
296 [font metrics $textfont -linespace]}]
300 pack .ctop.top.bar -side bottom -fill x
301 set cscroll .ctop.top.csb
302 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
303 pack $cscroll -side right -fill y
304 panedwindow .ctop.top.clist -orient horizontal -sashpad 0 -handlesize 4
305 pack .ctop.top.clist -side top -fill both -expand 1
307 set canv .ctop.top.clist.canv
308 canvas $canv -height $geometry(canvh) -width $geometry(canv1) \
310 -yscrollincr $linespc -yscrollcommand "$cscroll set"
311 .ctop.top.clist add $canv
312 set canv2 .ctop.top.clist.canv2
313 canvas $canv2 -height $geometry(canvh) -width $geometry(canv2) \
314 -bg white -bd 0 -yscrollincr $linespc
315 .ctop.top.clist add $canv2
316 set canv3 .ctop.top.clist.canv3
317 canvas $canv3 -height $geometry(canvh) -width $geometry(canv3) \
318 -bg white -bd 0 -yscrollincr $linespc
319 .ctop.top.clist add $canv3
320 bind .ctop.top.clist <Configure> {resizeclistpanes %W %w}
322 set sha1entry .ctop.top.bar.sha1
323 set entries $sha1entry
324 set sha1but .ctop.top.bar.sha1label
325 button $sha1but -text "SHA1 ID: " -state disabled -relief flat \
326 -command gotocommit -width 8
327 $sha1but conf -disabledforeground [$sha1but cget -foreground]
328 pack .ctop.top.bar.sha1label -side left
329 entry $sha1entry -width 40 -font $textfont -textvariable sha1string
330 trace add variable sha1string write sha1change
331 pack $sha1entry -side left -pady 2
332 button .ctop.top.bar.findbut -text "Find" -command dofind
333 pack .ctop.top.bar.findbut -side left
335 set fstring .ctop.top.bar.findstring
336 lappend entries $fstring
337 entry $fstring -width 30 -font $textfont -textvariable findstring
338 pack $fstring -side left -expand 1 -fill x
340 tk_optionMenu .ctop.top.bar.findtype findtype Exact IgnCase Regexp
341 set findloc "All fields"
342 tk_optionMenu .ctop.top.bar.findloc findloc "All fields" Headline \
343 Comments Author Committer
344 pack .ctop.top.bar.findloc -side right
345 pack .ctop.top.bar.findtype -side right
347 panedwindow .ctop.cdet -orient horizontal
349 frame .ctop.cdet.left
350 set ctext .ctop.cdet.left.ctext
351 text $ctext -bg white -state disabled -font $textfont \
352 -width $geometry(ctextw) -height $geometry(ctexth) \
353 -yscrollcommand ".ctop.cdet.left.sb set"
354 scrollbar .ctop.cdet.left.sb -command "$ctext yview"
355 pack .ctop.cdet.left.sb -side right -fill y
356 pack $ctext -side left -fill both -expand 1
357 .ctop.cdet add .ctop.cdet.left
359 $ctext tag conf filesep -font [concat $textfont bold]
360 $ctext tag conf hunksep -back blue -fore white
361 $ctext tag conf d0 -back "#ff8080"
362 $ctext tag conf d1 -back green
363 $ctext tag conf found -back yellow
365 frame .ctop.cdet.right
366 set cflist .ctop.cdet.right.cfiles
367 listbox $cflist -bg white -selectmode extended -width $geometry(cflistw) \
368 -yscrollcommand ".ctop.cdet.right.sb set"
369 scrollbar .ctop.cdet.right.sb -command "$cflist yview"
370 pack .ctop.cdet.right.sb -side right -fill y
371 pack $cflist -side left -fill both -expand 1
372 .ctop.cdet add .ctop.cdet.right
373 bind .ctop.cdet <Configure> {resizecdetpanes %W %w}
375 pack .ctop -side top -fill both -expand 1
377 bindall <1> {selcanvline %W %x %y}
378 #bindall <B1-Motion> {selcanvline %W %x %y}
379 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
380 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
381 bindall <2> "allcanvs scan mark 0 %y"
382 bindall <B2-Motion> "allcanvs scan dragto 0 %y"
383 bind . <Key-Up> "selnextline -1"
384 bind . <Key-Down> "selnextline 1"
385 bind . <Key-Prior> "allcanvs yview scroll -1 pages"
386 bind . <Key-Next> "allcanvs yview scroll 1 pages"
387 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
388 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
389 bindkey <Key-space> "$ctext yview scroll 1 pages"
390 bindkey p "selnextline -1"
391 bindkey n "selnextline 1"
392 bindkey b "$ctext yview scroll -1 pages"
393 bindkey d "$ctext yview scroll 18 units"
394 bindkey u "$ctext yview scroll -18 units"
398 bind . <Control-q> doquit
399 bind . <Control-f> dofind
400 bind . <Control-g> findnext
401 bind . <Control-r> findprev
402 bind . <Control-equal> {incrfont 1}
403 bind . <Control-KP_Add> {incrfont 1}
404 bind . <Control-minus> {incrfont -1}
405 bind . <Control-KP_Subtract> {incrfont -1}
406 bind $cflist <<ListboxSelect>> listboxsel
407 bind . <Destroy> {savestuff %W}
408 bind . <Button-1> "click %W"
409 bind $fstring <Key-Return> dofind
410 bind $sha1entry <Key-Return> gotocommit
411 bind $sha1entry <<PasteSelection>> clearsha1
413 set maincursor [. cget -cursor]
414 set textcursor [$ctext cget -cursor]
416 set rowctxmenu .rowctxmenu
417 menu $rowctxmenu -tearoff 0
418 $rowctxmenu add command -label "Diff this -> selected" \
419 -command {diffvssel 0}
420 $rowctxmenu add command -label "Diff selected -> this" \
421 -command {diffvssel 1}
424 # when we make a key binding for the toplevel, make sure
425 # it doesn't get triggered when that key is pressed in the
426 # find string entry widget.
427 proc bindkey {ev script} {
430 set escript [bind Entry $ev]
431 if {$escript == {}} {
432 set escript [bind Entry <Key>]
435 bind $e $ev "$escript; break"
439 # set the focus back to the toplevel for any click outside
450 global canv canv2 canv3 ctext cflist mainfont textfont
452 if {$stuffsaved} return
453 if {![winfo viewable .]} return
455 set f [open "~/.gitk-new" w]
456 puts $f "set mainfont {$mainfont}"
457 puts $f "set textfont {$textfont}"
458 puts $f "set geometry(width) [winfo width .ctop]"
459 puts $f "set geometry(height) [winfo height .ctop]"
460 puts $f "set geometry(canv1) [expr [winfo width $canv]-2]"
461 puts $f "set geometry(canv2) [expr [winfo width $canv2]-2]"
462 puts $f "set geometry(canv3) [expr [winfo width $canv3]-2]"
463 puts $f "set geometry(canvh) [expr [winfo height $canv]-2]"
464 set wid [expr {([winfo width $ctext] - 8) \
465 / [font measure $textfont "0"]}]
466 puts $f "set geometry(ctextw) $wid"
467 set wid [expr {([winfo width $cflist] - 11) \
468 / [font measure [$cflist cget -font] "0"]}]
469 puts $f "set geometry(cflistw) $wid"
471 file rename -force "~/.gitk-new" "~/.gitk"
476 proc resizeclistpanes {win w} {
478 if [info exists oldwidth($win)] {
479 set s0 [$win sash coord 0]
480 set s1 [$win sash coord 1]
482 set sash0 [expr {int($w/2 - 2)}]
483 set sash1 [expr {int($w*5/6 - 2)}]
485 set factor [expr {1.0 * $w / $oldwidth($win)}]
486 set sash0 [expr {int($factor * [lindex $s0 0])}]
487 set sash1 [expr {int($factor * [lindex $s1 0])}]
491 if {$sash1 < $sash0 + 20} {
492 set sash1 [expr $sash0 + 20]
494 if {$sash1 > $w - 10} {
495 set sash1 [expr $w - 10]
496 if {$sash0 > $sash1 - 20} {
497 set sash0 [expr $sash1 - 20]
501 $win sash place 0 $sash0 [lindex $s0 1]
502 $win sash place 1 $sash1 [lindex $s1 1]
504 set oldwidth($win) $w
507 proc resizecdetpanes {win w} {
509 if [info exists oldwidth($win)] {
510 set s0 [$win sash coord 0]
512 set sash0 [expr {int($w*3/4 - 2)}]
514 set factor [expr {1.0 * $w / $oldwidth($win)}]
515 set sash0 [expr {int($factor * [lindex $s0 0])}]
519 if {$sash0 > $w - 15} {
520 set sash0 [expr $w - 15]
523 $win sash place 0 $sash0 [lindex $s0 1]
525 set oldwidth($win) $w
529 global canv canv2 canv3
535 proc bindall {event action} {
536 global canv canv2 canv3
537 bind $canv $event $action
538 bind $canv2 $event $action
539 bind $canv3 $event $action
544 if {[winfo exists $w]} {
549 wm title $w "About gitk"
553 Copyright © 2005 Paul Mackerras
555 Use and redistribute under the terms of the GNU General Public License} \
556 -justify center -aspect 400
557 pack $w.m -side top -fill x -padx 20 -pady 20
558 button $w.ok -text Close -command "destroy $w"
559 pack $w.ok -side bottom
562 proc assigncolor {id} {
563 global commitinfo colormap commcolors colors nextcolor
564 global parents nparents children nchildren
565 global cornercrossings crossings
567 if [info exists colormap($id)] return
568 set ncolors [llength $colors]
569 if {$nparents($id) <= 1 && $nchildren($id) == 1} {
570 set child [lindex $children($id) 0]
571 if {[info exists colormap($child)]
572 && $nparents($child) == 1} {
573 set colormap($id) $colormap($child)
578 if {[info exists cornercrossings($id)]} {
579 foreach x $cornercrossings($id) {
580 if {[info exists colormap($x)]
581 && [lsearch -exact $badcolors $colormap($x)] < 0} {
582 lappend badcolors $colormap($x)
585 if {[llength $badcolors] >= $ncolors} {
589 set origbad $badcolors
590 if {[llength $badcolors] < $ncolors - 1} {
591 if {[info exists crossings($id)]} {
592 foreach x $crossings($id) {
593 if {[info exists colormap($x)]
594 && [lsearch -exact $badcolors $colormap($x)] < 0} {
595 lappend badcolors $colormap($x)
598 if {[llength $badcolors] >= $ncolors} {
599 set badcolors $origbad
602 set origbad $badcolors
604 if {[llength $badcolors] < $ncolors - 1} {
605 foreach child $children($id) {
606 if {[info exists colormap($child)]
607 && [lsearch -exact $badcolors $colormap($child)] < 0} {
608 lappend badcolors $colormap($child)
610 if {[info exists parents($child)]} {
611 foreach p $parents($child) {
612 if {[info exists colormap($p)]
613 && [lsearch -exact $badcolors $colormap($p)] < 0} {
614 lappend badcolors $colormap($p)
619 if {[llength $badcolors] >= $ncolors} {
620 set badcolors $origbad
623 for {set i 0} {$i <= $ncolors} {incr i} {
624 set c [lindex $colors $nextcolor]
625 if {[incr nextcolor] >= $ncolors} {
628 if {[lsearch -exact $badcolors $c]} break
634 global canvy canvy0 lineno numcommits lthickness nextcolor linespc
635 global mainline sidelines
636 global nchildren ncleft
643 set lthickness [expr {int($linespc / 9) + 1}]
644 catch {unset mainline}
645 catch {unset sidelines}
646 foreach id [array names nchildren] {
647 set ncleft($id) $nchildren($id)
651 proc bindline {t id} {
654 $canv bind $t <Enter> "lineenter %x %y $id"
655 $canv bind $t <Motion> "linemotion %x %y $id"
656 $canv bind $t <Leave> "lineleave $id"
657 $canv bind $t <Button-1> "lineclick %x %y $id"
660 proc drawcommitline {level} {
661 global parents children nparents nchildren todo
662 global canv canv2 canv3 mainfont namefont canvx0 canvy linespc
663 global lineid linehtag linentag linedtag commitinfo
664 global colormap numcommits currentparents dupparents
665 global oldlevel oldnlines oldtodo
666 global idtags idline idheads
667 global lineno lthickness mainline sidelines
668 global commitlisted rowtextx
672 set id [lindex $todo $level]
673 set lineid($lineno) $id
674 set idline($id) $lineno
675 set ofill [expr {[info exists commitlisted($id)]? "blue": "white"}]
676 if {![info exists commitinfo($id)]} {
678 if {![info exists commitinfo($id)]} {
679 set commitinfo($id) {"No commit information available"}
684 set currentparents {}
686 if {[info exists commitlisted($id)] && [info exists parents($id)]} {
687 foreach p $parents($id) {
688 if {[lsearch -exact $currentparents $p] < 0} {
689 lappend currentparents $p
691 # remember that this parent was listed twice
692 lappend dupparents $p
696 set x [expr $canvx0 + $level * $linespc]
698 set canvy [expr $canvy + $linespc]
699 allcanvs conf -scrollregion \
700 [list 0 0 0 [expr $y1 + 0.5 * $linespc + 2]]
701 if {[info exists mainline($id)]} {
702 lappend mainline($id) $x $y1
703 set t [$canv create line $mainline($id) \
704 -width $lthickness -fill $colormap($id)]
708 if {[info exists sidelines($id)]} {
709 foreach ls $sidelines($id) {
710 set coords [lindex $ls 0]
711 set thick [lindex $ls 1]
712 set t [$canv create line $coords -fill $colormap($id) \
713 -width [expr {$thick * $lthickness}]]
718 set orad [expr {$linespc / 3}]
719 set t [$canv create oval [expr $x - $orad] [expr $y1 - $orad] \
720 [expr $x + $orad - 1] [expr $y1 + $orad - 1] \
721 -fill $ofill -outline black -width 1]
723 $canv bind $t <1> {selcanvline {} %x %y}
724 set xt [expr $canvx0 + [llength $todo] * $linespc]
725 if {[llength $currentparents] > 2} {
726 set xt [expr {$xt + ([llength $currentparents] - 2) * $linespc}]
728 set rowtextx($lineno) $xt
731 if {[info exists idtags($id)]} {
732 set marks $idtags($id)
733 set ntags [llength $marks]
735 if {[info exists idheads($id)]} {
736 set marks [concat $marks $idheads($id)]
739 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
740 set yt [expr $y1 - 0.5 * $linespc]
741 set yb [expr $yt + $linespc - 1]
745 set wid [font measure $mainfont $tag]
748 set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}]
750 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
751 -width $lthickness -fill black]
753 foreach tag $marks x $xvals wid $wvals {
754 set xl [expr $x + $delta]
755 set xr [expr $x + $delta + $wid + $lthickness]
756 if {[incr ntags -1] >= 0} {
758 $canv create polygon $x [expr $yt + $delta] $xl $yt\
759 $xr $yt $xr $yb $xl $yb $x [expr $yb - $delta] \
760 -width 1 -outline black -fill yellow
763 set xl [expr $xl - $delta/2]
764 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
765 -width 1 -outline black -fill green
767 $canv create text $xl $y1 -anchor w -text $tag \
771 set headline [lindex $commitinfo($id) 0]
772 set name [lindex $commitinfo($id) 1]
773 set date [lindex $commitinfo($id) 2]
774 set linehtag($lineno) [$canv create text $xt $y1 -anchor w \
775 -text $headline -font $mainfont ]
776 $canv bind $linehtag($lineno) <Button-3> "rowmenu %X %Y $id"
777 set linentag($lineno) [$canv2 create text 3 $y1 -anchor w \
778 -text $name -font $namefont]
779 set linedtag($lineno) [$canv3 create text 3 $y1 -anchor w \
780 -text $date -font $mainfont]
783 proc updatetodo {level noshortcut} {
784 global currentparents ncleft todo
785 global mainline oldlevel oldtodo oldnlines
786 global canvx0 canvy linespc mainline
791 set oldnlines [llength $todo]
792 if {!$noshortcut && [llength $currentparents] == 1} {
793 set p [lindex $currentparents 0]
794 if {$ncleft($p) == 1 && [lsearch -exact $todo $p] < 0} {
796 set x [expr $canvx0 + $level * $linespc]
797 set y [expr $canvy - $linespc]
798 set mainline($p) [list $x $y]
799 set todo [lreplace $todo $level $level $p]
804 set todo [lreplace $todo $level $level]
806 foreach p $currentparents {
808 set k [lsearch -exact $todo $p]
810 set todo [linsert $todo $i $p]
817 proc notecrossings {id lo hi corner} {
818 global oldtodo crossings cornercrossings
820 for {set i $lo} {[incr i] < $hi} {} {
821 set p [lindex $oldtodo $i]
822 if {$p == {}} continue
824 if {![info exists cornercrossings($id)]
825 || [lsearch -exact $cornercrossings($id) $p] < 0} {
826 lappend cornercrossings($id) $p
828 if {![info exists cornercrossings($p)]
829 || [lsearch -exact $cornercrossings($p) $id] < 0} {
830 lappend cornercrossings($p) $id
833 if {![info exists crossings($id)]
834 || [lsearch -exact $crossings($id) $p] < 0} {
835 lappend crossings($id) $p
837 if {![info exists crossings($p)]
838 || [lsearch -exact $crossings($p) $id] < 0} {
839 lappend crossings($p) $id
846 global canv mainline sidelines canvx0 canvy linespc
847 global oldlevel oldtodo todo currentparents dupparents
848 global lthickness linespc canvy colormap
850 set y1 [expr $canvy - $linespc]
853 foreach id $oldtodo {
855 if {$id == {}} continue
856 set xi [expr {$canvx0 + $i * $linespc}]
857 if {$i == $oldlevel} {
858 foreach p $currentparents {
859 set j [lsearch -exact $todo $p]
860 set coords [list $xi $y1]
861 set xj [expr {$canvx0 + $j * $linespc}]
863 lappend coords [expr $xj + $linespc] $y1
864 notecrossings $p $j $i [expr {$j + 1}]
865 } elseif {$j > $i + 1} {
866 lappend coords [expr $xj - $linespc] $y1
867 notecrossings $p $i $j [expr {$j - 1}]
869 if {[lsearch -exact $dupparents $p] >= 0} {
870 # draw a double-width line to indicate the doubled parent
871 lappend coords $xj $y2
872 lappend sidelines($p) [list $coords 2]
873 if {![info exists mainline($p)]} {
874 set mainline($p) [list $xj $y2]
877 # normal case, no parent duplicated
878 if {![info exists mainline($p)]} {
880 lappend coords $xj $y2
882 set mainline($p) $coords
884 lappend coords $xj $y2
885 lappend sidelines($p) [list $coords 1]
889 } elseif {[lindex $todo $i] != $id} {
890 set j [lsearch -exact $todo $id]
891 set xj [expr {$canvx0 + $j * $linespc}]
892 lappend mainline($id) $xi $y1 $xj $y2
898 global parents children nchildren ncleft todo
899 global canv canv2 canv3 mainfont namefont canvx0 canvy linespc
900 global datemode cdate
901 global lineid linehtag linentag linedtag commitinfo
902 global currentparents oldlevel oldnlines oldtodo
903 global lineno lthickness
905 # remove the null entry if present
906 set nullentry [lsearch -exact $todo {}]
907 if {$nullentry >= 0} {
908 set todo [lreplace $todo $nullentry $nullentry]
911 # choose which one to do next time around
912 set todol [llength $todo]
915 for {set k $todol} {[incr k -1] >= 0} {} {
916 set p [lindex $todo $k]
917 if {$ncleft($p) == 0} {
919 if {$latest == {} || $cdate($p) > $latest} {
921 set latest $cdate($p)
931 puts "ERROR: none of the pending commits can be done yet:"
933 puts " $p ($ncleft($p))"
939 # If we are reducing, put in a null entry
940 if {$todol < $oldnlines} {
941 if {$nullentry >= 0} {
944 && [lindex $oldtodo $i] == [lindex $todo $i]} {
954 set todo [linsert $todo $i {}]
963 proc drawcommit {id} {
964 global phase todo nchildren datemode nextupdate
967 if {$phase != "incrdraw"} {
973 updatetodo 0 $datemode
975 if {$nchildren($id) == 0} {
977 lappend startcommits $id
979 set level [decidenext]
980 if {$id != [lindex $todo $level]} {
985 drawcommitline $level
986 if {[updatetodo $level $datemode]} {
987 set level [decidenext]
989 set id [lindex $todo $level]
990 if {![info exists commitlisted($id)]} {
993 if {[clock clicks -milliseconds] >= $nextupdate} {
1001 proc finishcommits {} {
1004 global ctext maincursor textcursor
1006 if {$phase != "incrdraw"} {
1008 $canv create text 3 3 -anchor nw -text "No commits selected" \
1009 -font $mainfont -tags textitems
1014 set level [decidenext]
1015 drawrest $level [llength $startcommits]
1016 . config -cursor $maincursor
1017 $ctext config -cursor $textcursor
1021 global nextupdate startmsecs startcommits todo
1023 if {$startcommits == {}} return
1024 set startmsecs [clock clicks -milliseconds]
1025 set nextupdate [expr $startmsecs + 100]
1027 set todo [lindex $startcommits 0]
1031 proc drawrest {level startix} {
1032 global phase stopped redisplaying selectedline
1033 global datemode currentparents todo
1035 global nextupdate startmsecs startcommits idline
1039 set startid [lindex $startcommits $startix]
1041 if {$startid != {}} {
1042 set startline $idline($startid)
1046 drawcommitline $level
1047 set hard [updatetodo $level $datemode]
1048 if {$numcommits == $startline} {
1049 lappend todo $startid
1052 set startid [lindex $startcommits $startix]
1054 if {$startid != {}} {
1055 set startline $idline($startid)
1059 set level [decidenext]
1060 if {$level < 0} break
1063 if {[clock clicks -milliseconds] >= $nextupdate} {
1070 set drawmsecs [expr [clock clicks -milliseconds] - $startmsecs]
1071 #puts "overall $drawmsecs ms for $numcommits commits"
1072 if {$redisplaying} {
1073 if {$stopped == 0 && [info exists selectedline]} {
1074 selectline $selectedline
1076 if {$stopped == 1} {
1078 after idle drawgraph
1085 proc findmatches {f} {
1086 global findtype foundstring foundstrlen
1087 if {$findtype == "Regexp"} {
1088 set matches [regexp -indices -all -inline $foundstring $f]
1090 if {$findtype == "IgnCase"} {
1091 set str [string tolower $f]
1097 while {[set j [string first $foundstring $str $i]] >= 0} {
1098 lappend matches [list $j [expr $j+$foundstrlen-1]]
1099 set i [expr $j + $foundstrlen]
1106 global findtype findloc findstring markedmatches commitinfo
1107 global numcommits lineid linehtag linentag linedtag
1108 global mainfont namefont canv canv2 canv3 selectedline
1109 global matchinglines foundstring foundstrlen
1112 set matchinglines {}
1113 set fldtypes {Headline Author Date Committer CDate Comment}
1114 if {$findtype == "IgnCase"} {
1115 set foundstring [string tolower $findstring]
1117 set foundstring $findstring
1119 set foundstrlen [string length $findstring]
1120 if {$foundstrlen == 0} return
1121 if {![info exists selectedline]} {
1124 set oldsel $selectedline
1127 for {set l 0} {$l < $numcommits} {incr l} {
1129 set info $commitinfo($id)
1131 foreach f $info ty $fldtypes {
1132 if {$findloc != "All fields" && $findloc != $ty} {
1135 set matches [findmatches $f]
1136 if {$matches == {}} continue
1138 if {$ty == "Headline"} {
1139 markmatches $canv $l $f $linehtag($l) $matches $mainfont
1140 } elseif {$ty == "Author"} {
1141 markmatches $canv2 $l $f $linentag($l) $matches $namefont
1142 } elseif {$ty == "Date"} {
1143 markmatches $canv3 $l $f $linedtag($l) $matches $mainfont
1147 lappend matchinglines $l
1148 if {!$didsel && $l > $oldsel} {
1154 if {$matchinglines == {}} {
1156 } elseif {!$didsel} {
1157 findselectline [lindex $matchinglines 0]
1161 proc findselectline {l} {
1162 global findloc commentend ctext
1164 if {$findloc == "All fields" || $findloc == "Comments"} {
1165 # highlight the matches in the comments
1166 set f [$ctext get 1.0 $commentend]
1167 set matches [findmatches $f]
1168 foreach match $matches {
1169 set start [lindex $match 0]
1170 set end [expr [lindex $match 1] + 1]
1171 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
1177 global matchinglines selectedline
1178 if {![info exists matchinglines]} {
1182 if {![info exists selectedline]} return
1183 foreach l $matchinglines {
1184 if {$l > $selectedline} {
1193 global matchinglines selectedline
1194 if {![info exists matchinglines]} {
1198 if {![info exists selectedline]} return
1200 foreach l $matchinglines {
1201 if {$l >= $selectedline} break
1205 findselectline $prev
1211 proc markmatches {canv l str tag matches font} {
1212 set bbox [$canv bbox $tag]
1213 set x0 [lindex $bbox 0]
1214 set y0 [lindex $bbox 1]
1215 set y1 [lindex $bbox 3]
1216 foreach match $matches {
1217 set start [lindex $match 0]
1218 set end [lindex $match 1]
1219 if {$start > $end} continue
1220 set xoff [font measure $font [string range $str 0 [expr $start-1]]]
1221 set xlen [font measure $font [string range $str 0 [expr $end]]]
1222 set t [$canv create rect [expr $x0+$xoff] $y0 [expr $x0+$xlen+2] $y1 \
1223 -outline {} -tags matches -fill yellow]
1228 proc unmarkmatches {} {
1229 global matchinglines
1230 allcanvs delete matches
1231 catch {unset matchinglines}
1234 proc selcanvline {w x y} {
1235 global canv canvy0 ctext linespc selectedline
1236 global lineid linehtag linentag linedtag rowtextx
1237 set ymax [lindex [$canv cget -scrollregion] 3]
1238 if {$ymax == {}} return
1239 set yfrac [lindex [$canv yview] 0]
1240 set y [expr {$y + $yfrac * $ymax}]
1241 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
1246 if {![info exists rowtextx($l)] || $x < $rowtextx($l)} return
1252 proc selectline {l} {
1253 global canv canv2 canv3 ctext commitinfo selectedline
1254 global lineid linehtag linentag linedtag
1255 global canvy0 linespc parents nparents
1256 global cflist currentid sha1entry diffids
1257 global commentend seenfile idtags
1259 if {![info exists lineid($l)] || ![info exists linehtag($l)]} return
1261 set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \
1262 -tags secsel -fill [$canv cget -selectbackground]]
1264 $canv2 delete secsel
1265 set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \
1266 -tags secsel -fill [$canv2 cget -selectbackground]]
1268 $canv3 delete secsel
1269 set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \
1270 -tags secsel -fill [$canv3 cget -selectbackground]]
1272 set y [expr {$canvy0 + $l * $linespc}]
1273 set ymax [lindex [$canv cget -scrollregion] 3]
1274 set ytop [expr {$y - $linespc - 1}]
1275 set ybot [expr {$y + $linespc + 1}]
1276 set wnow [$canv yview]
1277 set wtop [expr [lindex $wnow 0] * $ymax]
1278 set wbot [expr [lindex $wnow 1] * $ymax]
1279 set wh [expr {$wbot - $wtop}]
1281 if {$ytop < $wtop} {
1282 if {$ybot < $wtop} {
1283 set newtop [expr {$y - $wh / 2.0}]
1286 if {$newtop > $wtop - $linespc} {
1287 set newtop [expr {$wtop - $linespc}]
1290 } elseif {$ybot > $wbot} {
1291 if {$ytop > $wbot} {
1292 set newtop [expr {$y - $wh / 2.0}]
1294 set newtop [expr {$ybot - $wh}]
1295 if {$newtop < $wtop + $linespc} {
1296 set newtop [expr {$wtop + $linespc}]
1300 if {$newtop != $wtop} {
1304 allcanvs yview moveto [expr $newtop * 1.0 / $ymax]
1310 set diffids [concat $id $parents($id)]
1311 $sha1entry delete 0 end
1312 $sha1entry insert 0 $id
1313 $sha1entry selection from 0
1314 $sha1entry selection to end
1316 $ctext conf -state normal
1317 $ctext delete 0.0 end
1318 $ctext mark set fmark.0 0.0
1319 $ctext mark gravity fmark.0 left
1320 set info $commitinfo($id)
1321 $ctext insert end "Author: [lindex $info 1] [lindex $info 2]\n"
1322 $ctext insert end "Committer: [lindex $info 3] [lindex $info 4]\n"
1323 if {[info exists idtags($id)]} {
1324 $ctext insert end "Tags:"
1325 foreach tag $idtags($id) {
1326 $ctext insert end " $tag"
1328 $ctext insert end "\n"
1330 $ctext insert end "\n"
1331 $ctext insert end [lindex $info 5]
1332 $ctext insert end "\n"
1333 $ctext tag delete Comments
1334 $ctext tag remove found 1.0 end
1335 $ctext conf -state disabled
1336 set commentend [$ctext index "end - 1c"]
1338 $cflist delete 0 end
1339 $cflist insert end "Comments"
1340 if {$nparents($id) == 1} {
1343 catch {unset seenfile}
1347 global treediffs diffids treepending
1349 if {![info exists treediffs($diffids)]} {
1350 if {![info exists treepending]} {
1351 gettreediffs $diffids
1354 addtocflist $diffids
1358 proc selnextline {dir} {
1360 if {![info exists selectedline]} return
1361 set l [expr $selectedline + $dir]
1366 proc addtocflist {ids} {
1367 global diffids treediffs cflist
1368 if {$ids != $diffids} {
1369 gettreediffs $diffids
1372 foreach f $treediffs($ids) {
1373 $cflist insert end $f
1378 proc gettreediffs {ids} {
1379 global treediffs parents treepending
1380 set treepending $ids
1381 set treediffs($ids) {}
1382 set id [lindex $ids 0]
1383 set p [lindex $ids 1]
1384 if [catch {set gdtf [open "|git-diff-tree -r $p $id" r]}] return
1385 fconfigure $gdtf -blocking 0
1386 fileevent $gdtf readable "gettreediffline $gdtf {$ids}"
1389 proc gettreediffline {gdtf ids} {
1390 global treediffs treepending
1391 set n [gets $gdtf line]
1393 if {![eof $gdtf]} return
1399 set file [lindex $line 5]
1400 lappend treediffs($ids) $file
1403 proc getblobdiffs {ids} {
1404 global diffopts blobdifffd env curdifftag curtagstart
1405 global diffindex difffilestart nextupdate
1407 set id [lindex $ids 0]
1408 set p [lindex $ids 1]
1409 set env(GIT_DIFF_OPTS) $diffopts
1410 if [catch {set bdf [open "|git-diff-tree -r -p $p $id" r]} err] {
1411 puts "error getting diffs: $err"
1414 fconfigure $bdf -blocking 0
1415 set blobdifffd($ids) $bdf
1416 set curdifftag Comments
1419 catch {unset difffilestart}
1420 fileevent $bdf readable "getblobdiffline $bdf {$ids}"
1421 set nextupdate [expr {[clock clicks -milliseconds] + 100}]
1424 proc getblobdiffline {bdf ids} {
1425 global diffids blobdifffd ctext curdifftag curtagstart seenfile
1426 global diffnexthead diffnextnote diffindex difffilestart
1429 set n [gets $bdf line]
1433 if {$ids == $diffids && $bdf == $blobdifffd($ids)} {
1434 $ctext tag add $curdifftag $curtagstart end
1435 set seenfile($curdifftag) 1
1440 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
1443 $ctext conf -state normal
1444 if {[regexp {^---[ \t]+([^/])*/(.*)} $line match s1 fname]} {
1445 # start of a new file
1446 $ctext insert end "\n"
1447 $ctext tag add $curdifftag $curtagstart end
1448 set seenfile($curdifftag) 1
1449 set curtagstart [$ctext index "end - 1c"]
1451 if {[info exists diffnexthead]} {
1452 set fname $diffnexthead
1453 set header "$diffnexthead ($diffnextnote)"
1456 set here [$ctext index "end - 1c"]
1457 set difffilestart($diffindex) $here
1459 # start mark names at fmark.1 for first file
1460 $ctext mark set fmark.$diffindex $here
1461 $ctext mark gravity fmark.$diffindex left
1462 set curdifftag "f:$fname"
1463 $ctext tag delete $curdifftag
1464 set l [expr {(78 - [string length $header]) / 2}]
1465 set pad [string range "----------------------------------------" 1 $l]
1466 $ctext insert end "$pad $header $pad\n" filesep
1467 } elseif {[string range $line 0 2] == "+++"} {
1468 # no need to do anything with this
1469 } elseif {[regexp {^Created: (.*) \((mode: *[0-7]*)\)} $line match fn m]} {
1470 set diffnexthead $fn
1471 set diffnextnote "created, mode $m"
1472 } elseif {[string range $line 0 8] == "Deleted: "} {
1473 set diffnexthead [string range $line 9 end]
1474 set diffnextnote "deleted"
1475 } elseif {[regexp {^diff --git a/(.*) b/} $line match fn]} {
1476 # save the filename in case the next thing is "new file mode ..."
1477 set diffnexthead $fn
1478 set diffnextnote "modified"
1479 } elseif {[regexp {^new file mode ([0-7]+)} $line match m]} {
1480 set diffnextnote "new file, mode $m"
1481 } elseif {[string range $line 0 11] == "deleted file"} {
1482 set diffnextnote "deleted"
1483 } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \
1484 $line match f1l f1c f2l f2c rest]} {
1485 $ctext insert end "\t" hunksep
1486 $ctext insert end " $f1l " d0 " $f2l " d1
1487 $ctext insert end " $rest \n" hunksep
1489 set x [string range $line 0 0]
1490 if {$x == "-" || $x == "+"} {
1491 set tag [expr {$x == "+"}]
1492 set line [string range $line 1 end]
1493 $ctext insert end "$line\n" d$tag
1494 } elseif {$x == " "} {
1495 set line [string range $line 1 end]
1496 $ctext insert end "$line\n"
1497 } elseif {$x == "\\"} {
1498 # e.g. "\ No newline at end of file"
1499 $ctext insert end "$line\n" filesep
1501 # Something else we don't recognize
1502 if {$curdifftag != "Comments"} {
1503 $ctext insert end "\n"
1504 $ctext tag add $curdifftag $curtagstart end
1505 set seenfile($curdifftag) 1
1506 set curtagstart [$ctext index "end - 1c"]
1507 set curdifftag Comments
1509 $ctext insert end "$line\n" filesep
1512 $ctext conf -state disabled
1513 if {[clock clicks -milliseconds] >= $nextupdate} {
1515 fileevent $bdf readable {}
1517 fileevent $bdf readable "getblobdiffline $bdf {$ids}"
1522 global difffilestart ctext
1523 set here [$ctext index @0,0]
1524 for {set i 0} {[info exists difffilestart($i)]} {incr i} {
1525 if {[$ctext compare $difffilestart($i) > $here]} {
1526 $ctext yview $difffilestart($i)
1532 proc listboxsel {} {
1533 global ctext cflist currentid treediffs seenfile
1534 if {![info exists currentid]} return
1535 set sel [lsort [$cflist curselection]]
1536 if {$sel eq {}} return
1537 set first [lindex $sel 0]
1538 catch {$ctext yview fmark.$first}
1542 global linespc charspc canvx0 canvy0 mainfont
1543 set linespc [font metrics $mainfont -linespace]
1544 set charspc [font measure $mainfont "m"]
1545 set canvy0 [expr 3 + 0.5 * $linespc]
1546 set canvx0 [expr 3 + 0.5 * $linespc]
1550 global selectedline stopped redisplaying phase
1551 if {$stopped > 1} return
1552 if {$phase == "getcommits"} return
1554 if {$phase == "drawgraph" || $phase == "incrdraw"} {
1561 proc incrfont {inc} {
1562 global mainfont namefont textfont selectedline ctext canv phase
1563 global stopped entries
1565 set mainfont [lreplace $mainfont 1 1 [expr {[lindex $mainfont 1] + $inc}]]
1566 set namefont [lreplace $namefont 1 1 [expr {[lindex $namefont 1] + $inc}]]
1567 set textfont [lreplace $textfont 1 1 [expr {[lindex $textfont 1] + $inc}]]
1569 $ctext conf -font $textfont
1570 $ctext tag conf filesep -font [concat $textfont bold]
1571 foreach e $entries {
1572 $e conf -font $mainfont
1574 if {$phase == "getcommits"} {
1575 $canv itemconf textitems -font $mainfont
1581 global sha1entry sha1string
1582 if {[string length $sha1string] == 40} {
1583 $sha1entry delete 0 end
1587 proc sha1change {n1 n2 op} {
1588 global sha1string currentid sha1but
1589 if {$sha1string == {}
1590 || ([info exists currentid] && $sha1string == $currentid)} {
1595 if {[$sha1but cget -state] == $state} return
1596 if {$state == "normal"} {
1597 $sha1but conf -state normal -relief raised -text "Goto: "
1599 $sha1but conf -state disabled -relief flat -text "SHA1 ID: "
1603 proc gotocommit {} {
1604 global sha1string currentid idline tagids
1605 if {$sha1string == {}
1606 || ([info exists currentid] && $sha1string == $currentid)} return
1607 if {[info exists tagids($sha1string)]} {
1608 set id $tagids($sha1string)
1610 set id [string tolower $sha1string]
1612 if {[info exists idline($id)]} {
1613 selectline $idline($id)
1616 if {[regexp {^[0-9a-fA-F]{40}$} $sha1string]} {
1621 error_popup "$type $sha1string is not known"
1624 proc lineenter {x y id} {
1625 global hoverx hovery hoverid hovertimer
1626 global commitinfo canv
1628 if {![info exists commitinfo($id)]} return
1632 if {[info exists hovertimer]} {
1633 after cancel $hovertimer
1635 set hovertimer [after 500 linehover]
1639 proc linemotion {x y id} {
1640 global hoverx hovery hoverid hovertimer
1642 if {[info exists hoverid] && $id == $hoverid} {
1645 if {[info exists hovertimer]} {
1646 after cancel $hovertimer
1648 set hovertimer [after 500 linehover]
1652 proc lineleave {id} {
1653 global hoverid hovertimer canv
1655 if {[info exists hoverid] && $id == $hoverid} {
1657 if {[info exists hovertimer]} {
1658 after cancel $hovertimer
1666 global hoverx hovery hoverid hovertimer
1667 global canv linespc lthickness
1668 global commitinfo mainfont
1670 set text [lindex $commitinfo($hoverid) 0]
1671 set ymax [lindex [$canv cget -scrollregion] 3]
1672 if {$ymax == {}} return
1673 set yfrac [lindex [$canv yview] 0]
1674 set x [expr {$hoverx + 2 * $linespc}]
1675 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
1676 set x0 [expr {$x - 2 * $lthickness}]
1677 set y0 [expr {$y - 2 * $lthickness}]
1678 set x1 [expr {$x + [font measure $mainfont $text] + 2 * $lthickness}]
1679 set y1 [expr {$y + $linespc + 2 * $lthickness}]
1680 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
1681 -fill \#ffff80 -outline black -width 1 -tags hover]
1683 set t [$canv create text $x $y -anchor nw -text $text -tags hover]
1687 proc lineclick {x y id} {
1688 global ctext commitinfo children cflist canv
1692 # fill the details pane with info about this line
1693 $ctext conf -state normal
1694 $ctext delete 0.0 end
1695 $ctext insert end "Parent:\n "
1696 catch {destroy $ctext.$id}
1697 button $ctext.$id -text "Go:" -command "selbyid $id" \
1699 $ctext window create end -window $ctext.$id -align center
1700 set info $commitinfo($id)
1701 $ctext insert end "\t[lindex $info 0]\n"
1702 $ctext insert end "\tAuthor:\t[lindex $info 1]\n"
1703 $ctext insert end "\tDate:\t[lindex $info 2]\n"
1704 $ctext insert end "\tID:\t$id\n"
1705 if {[info exists children($id)]} {
1706 $ctext insert end "\nChildren:"
1707 foreach child $children($id) {
1708 $ctext insert end "\n "
1709 catch {destroy $ctext.$child}
1710 button $ctext.$child -text "Go:" -command "selbyid $child" \
1712 $ctext window create end -window $ctext.$child -align center
1713 set info $commitinfo($child)
1714 $ctext insert end "\t[lindex $info 0]"
1717 $ctext conf -state disabled
1719 $cflist delete 0 end
1724 if {[info exists idline($id)]} {
1725 selectline $idline($id)
1731 if {![info exists startmstime]} {
1732 set startmstime [clock clicks -milliseconds]
1734 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
1737 proc rowmenu {x y id} {
1738 global rowctxmenu idline selectedline rowmenuid
1740 if {![info exists selectedline] || $idline($id) eq $selectedline} {
1745 $rowctxmenu entryconfigure 0 -state $state
1746 $rowctxmenu entryconfigure 1 -state $state
1748 tk_popup $rowctxmenu $x $y
1751 proc diffvssel {dirn} {
1752 global rowmenuid selectedline lineid
1754 global diffids commitinfo
1756 if {![info exists selectedline]} return
1758 set oldid $lineid($selectedline)
1759 set newid $rowmenuid
1761 set oldid $rowmenuid
1762 set newid $lineid($selectedline)
1764 $ctext conf -state normal
1765 $ctext delete 0.0 end
1766 $ctext mark set fmark.0 0.0
1767 $ctext mark gravity fmark.0 left
1768 $cflist delete 0 end
1769 $cflist insert end "Top"
1770 $ctext insert end "From $oldid\n "
1771 $ctext insert end [lindex $commitinfo($oldid) 0]
1772 $ctext insert end "\n\nTo $newid\n "
1773 $ctext insert end [lindex $commitinfo($newid) 0]
1774 $ctext insert end "\n"
1775 $ctext conf -state disabled
1776 $ctext tag delete Comments
1777 $ctext tag remove found 1.0 end
1778 set diffids [list $newid $oldid]
1791 set diffopts "-U 5 -p"
1793 set mainfont {Helvetica 9}
1794 set textfont {Courier 9}
1796 set colors {green red blue magenta darkgrey brown orange}
1798 catch {source ~/.gitk}
1800 set namefont $mainfont
1802 lappend namefont bold
1807 switch -regexp -- $arg {
1809 "^-b" { set boldnames 1 }
1810 "^-d" { set datemode 1 }
1812 lappend revtreeargs $arg
1823 getcommits $revtreeargs