1#!/bin/sh
2# Tcl ignores the next line -*- tcl -*- \
3exec wish "$0" -- "${1+$@}"
4
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.
9
10# CVS $Revision: 1.7 $
11
12set datemode 0
13set boldnames 0
14set revtreeargs {}
15set diffopts "-U 5 -p"
16
17set mainfont {Helvetica 9}
18set namefont $mainfont
19set textfont {Courier 9}
20if {$boldnames} {
21 lappend namefont bold
22}
23
24set colors {green red blue magenta darkgrey brown orange}
25set colorbycommitter false
26
27catch {source ~/.gitk}
28
29foreach arg $argv {
30 switch -regexp -- $arg {
31 "^$" { }
32 "^-b" { set boldnames 1 }
33 "^-c" { set colorbycommitter 1 }
34 "^-d" { set datemode 1 }
35 "^-.*" {
36 puts stderr "unrecognized option $arg"
37 exit 1
38 }
39 default {
40 lappend revtreeargs $arg
41 }
42 }
43}
44
45proc getcommits {rargs} {
46 global commits parents cdate nparents children nchildren
47 if {$rargs == {}} {
48 set rargs HEAD
49 }
50 set commits {}
51 if [catch {set clist [eval exec git-rev-tree $rargs]} err] {
52 if {[string range $err 0 4] == "usage"} {
53 puts stderr "Error reading commits: bad arguments to git-rev-tree"
54 puts stderr "Note: arguments to gitk are passed to git-rev-tree"
55 puts stderr " to allow selection of commits to be displayed"
56 } else {
57 puts stderr "Error reading commits: $err"
58 }
59 return 0
60 }
61 foreach c [split $clist "\n"] {
62 set i 0
63 set cid {}
64 foreach f $c {
65 if {$i == 0} {
66 set d $f
67 } else {
68 set id [lindex [split $f :] 0]
69 if {![info exists nchildren($id)]} {
70 set children($id) {}
71 set nchildren($id) 0
72 }
73 if {$i == 1} {
74 set cid $id
75 lappend commits $id
76 set parents($id) {}
77 set cdate($id) $d
78 set nparents($id) 0
79 } else {
80 lappend parents($cid) $id
81 incr nparents($cid)
82 incr nchildren($id)
83 lappend children($id) $cid
84 }
85 }
86 incr i
87 }
88 }
89 return 1
90}
91
92proc readcommit {id} {
93 global commitinfo
94 set inhdr 1
95 set comment {}
96 set headline {}
97 set auname {}
98 set audate {}
99 set comname {}
100 set comdate {}
101 foreach line [split [exec git-cat-file commit $id] "\n"] {
102 if {$inhdr} {
103 if {$line == {}} {
104 set inhdr 0
105 } else {
106 set tag [lindex $line 0]
107 if {$tag == "author"} {
108 set x [expr {[llength $line] - 2}]
109 set audate [lindex $line $x]
110 set auname [lrange $line 1 [expr {$x - 1}]]
111 } elseif {$tag == "committer"} {
112 set x [expr {[llength $line] - 2}]
113 set comdate [lindex $line $x]
114 set comname [lrange $line 1 [expr {$x - 1}]]
115 }
116 }
117 } else {
118 if {$comment == {}} {
119 set headline $line
120 } else {
121 append comment "\n"
122 }
123 append comment $line
124 }
125 }
126 if {$audate != {}} {
127 set audate [clock format $audate -format "%Y-%m-%d %H:%M:%S"]
128 }
129 if {$comdate != {}} {
130 set comdate [clock format $comdate -format "%Y-%m-%d %H:%M:%S"]
131 }
132 set commitinfo($id) [list $headline $auname $audate \
133 $comname $comdate $comment]
134}
135
136proc makewindow {} {
137 global canv canv2 canv3 linespc charspc ctext cflist textfont
138
139 menu .bar
140 .bar add cascade -label "File" -menu .bar.file
141 menu .bar.file
142 .bar.file add command -label "Quit" -command "set stopped 1; destroy ."
143 menu .bar.help
144 .bar add cascade -label "Help" -menu .bar.help
145 .bar.help add command -label "About gitk" -command about
146 . configure -menu .bar
147
148 panedwindow .ctop -orient vertical
149 panedwindow .ctop.clist -orient horizontal -sashpad 0 -handlesize 4
150 .ctop add .ctop.clist
151 set canv .ctop.clist.canv
152 set cscroll .ctop.clist.dates.csb
153 set height [expr 25 * $linespc + 4]
154 canvas $canv -height $height -width [expr 45 * $charspc] \
155 -bg white -bd 0 \
156 -yscrollincr $linespc -yscrollcommand "$cscroll set"
157 .ctop.clist add $canv
158 set canv2 .ctop.clist.canv2
159 canvas $canv2 -height $height -width [expr 30 * $charspc] \
160 -bg white -bd 0 -yscrollincr $linespc
161 .ctop.clist add $canv2
162 frame .ctop.clist.dates
163 .ctop.clist add .ctop.clist.dates
164 set canv3 .ctop.clist.dates.canv3
165 canvas $canv3 -height $height -width [expr 15 * $charspc] \
166 -bg white -bd 0 -yscrollincr $linespc
167 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
168 pack .ctop.clist.dates.csb -side right -fill y
169 pack $canv3 -side left -fill both -expand 1
170
171 panedwindow .ctop.cdet -orient horizontal
172 .ctop add .ctop.cdet
173 frame .ctop.cdet.left
174 set ctext .ctop.cdet.left.ctext
175 text $ctext -bg white -state disabled -font $textfont -height 32 \
176 -yscrollcommand ".ctop.cdet.left.sb set"
177 scrollbar .ctop.cdet.left.sb -command "$ctext yview"
178 pack .ctop.cdet.left.sb -side right -fill y
179 pack $ctext -side left -fill both -expand 1
180 .ctop.cdet add .ctop.cdet.left
181
182 $ctext tag conf filesep -font [concat $textfont bold]
183 $ctext tag conf hunksep -back blue -fore white
184 $ctext tag conf d0 -back "#ff8080"
185 $ctext tag conf d1 -back green
186
187 frame .ctop.cdet.right
188 set cflist .ctop.cdet.right.cfiles
189 listbox $cflist -width 30 -bg white -selectmode extended \
190 -yscrollcommand ".ctop.cdet.right.sb set"
191 scrollbar .ctop.cdet.right.sb -command "$cflist yview"
192 pack .ctop.cdet.right.sb -side right -fill y
193 pack $cflist -side left -fill both -expand 1
194 .ctop.cdet add .ctop.cdet.right
195
196 pack .ctop -side top -fill both -expand 1
197
198 bindall <1> {selcanvline %x %y}
199 bindall <B1-Motion> {selcanvline %x %y}
200 bindall <ButtonRelease-4> "allcanvs yview scroll -5 u"
201 bindall <ButtonRelease-5> "allcanvs yview scroll 5 u"
202 bindall <2> "allcanvs scan mark 0 %y"
203 bindall <B2-Motion> "allcanvs scan dragto 0 %y"
204 bind . <Key-Up> "selnextline -1"
205 bind . <Key-Down> "selnextline 1"
206 bind . p "selnextline -1"
207 bind . n "selnextline 1"
208 bind . <Key-Prior> "allcanvs yview scroll -1 p"
209 bind . <Key-Next> "allcanvs yview scroll 1 p"
210 bind . <Key-Delete> "$ctext yview scroll -1 p"
211 bind . <Key-BackSpace> "$ctext yview scroll -1 p"
212 bind . <Key-space> "$ctext yview scroll 1 p"
213 bind . b "$ctext yview scroll -1 p"
214 bind . d "$ctext yview scroll 18 u"
215 bind . u "$ctext yview scroll -18 u"
216 bind . Q "set stopped 1; destroy ."
217 bind . <Control-q> "set stopped 1; destroy ."
218 bind $cflist <<ListboxSelect>> listboxsel
219}
220
221proc allcanvs args {
222 global canv canv2 canv3
223 eval $canv $args
224 eval $canv2 $args
225 eval $canv3 $args
226}
227
228proc bindall {event action} {
229 global canv canv2 canv3
230 bind $canv $event $action
231 bind $canv2 $event $action
232 bind $canv3 $event $action
233}
234
235proc about {} {
236 set w .about
237 if {[winfo exists $w]} {
238 raise $w
239 return
240 }
241 toplevel $w
242 wm title $w "About gitk"
243 message $w.m -text {
244Gitk version 0.9
245
246Copyright © 2005 Paul Mackerras
247
248Use and redistribute under the terms of the GNU General Public License
249
250(CVS $Revision: 1.7 $)} \
251 -justify center -aspect 400
252 pack $w.m -side top -fill x -padx 20 -pady 20
253 button $w.ok -text Close -command "destroy $w"
254 pack $w.ok -side bottom
255}
256
257proc truncatetofit {str width font} {
258 if {[font measure $font $str] <= $width} {
259 return $str
260 }
261 set best 0
262 set bad [string length $str]
263 set tmp $str
264 while {$best < $bad - 1} {
265 set try [expr {int(($best + $bad) / 2)}]
266 set tmp "[string range $str 0 [expr $try-1]]..."
267 if {[font measure $font $tmp] <= $width} {
268 set best $try
269 } else {
270 set bad $try
271 }
272 }
273 return $tmp
274}
275
276proc assigncolor {id} {
277 global commitinfo colormap commcolors colors nextcolor
278 global colorbycommitter
279 global parents nparents children nchildren
280 if [info exists colormap($id)] return
281 set ncolors [llength $colors]
282 if {$colorbycommitter} {
283 if {![info exists commitinfo($id)]} {
284 readcommit $id
285 }
286 set comm [lindex $commitinfo($id) 3]
287 if {![info exists commcolors($comm)]} {
288 set commcolors($comm) [lindex $colors $nextcolor]
289 if {[incr nextcolor] >= $ncolors} {
290 set nextcolor 0
291 }
292 }
293 set colormap($id) $commcolors($comm)
294 } else {
295 if {$nparents($id) == 1 && $nchildren($id) == 1} {
296 set child [lindex $children($id) 0]
297 if {[info exists colormap($child)]
298 && $nparents($child) == 1} {
299 set colormap($id) $colormap($child)
300 return
301 }
302 }
303 set badcolors {}
304 foreach child $children($id) {
305 if {[info exists colormap($child)]
306 && [lsearch -exact $badcolors $colormap($child)] < 0} {
307 lappend badcolors $colormap($child)
308 }
309 if {[info exists parents($child)]} {
310 foreach p $parents($child) {
311 if {[info exists colormap($p)]
312 && [lsearch -exact $badcolors $colormap($p)] < 0} {
313 lappend badcolors $colormap($p)
314 }
315 }
316 }
317 }
318 if {[llength $badcolors] >= $ncolors} {
319 set badcolors {}
320 }
321 for {set i 0} {$i <= $ncolors} {incr i} {
322 set c [lindex $colors $nextcolor]
323 if {[incr nextcolor] >= $ncolors} {
324 set nextcolor 0
325 }
326 if {[lsearch -exact $badcolors $c]} break
327 }
328 set colormap($id) $c
329 }
330}
331
332proc drawgraph {start} {
333 global parents children nparents nchildren commits
334 global canv canv2 canv3 mainfont namefont canvx0 canvy0 canvy linespc
335 global datemode cdate
336 global lineid linehtag linentag linedtag commitinfo
337 global nextcolor colormap
338 global stopped
339
340 set nextcolor 0
341 assigncolor $start
342 foreach id $commits {
343 set ncleft($id) $nchildren($id)
344 }
345 set todo [list $start]
346 set level 0
347 set y2 $canvy0
348 set linestarty(0) $canvy0
349 set nullentry -1
350 set lineno -1
351 while 1 {
352 set canvy $y2
353 allcanvs conf -scrollregion [list 0 0 0 $canvy]
354 update
355 if {$stopped} return
356 incr lineno
357 set nlines [llength $todo]
358 set id [lindex $todo $level]
359 set lineid($lineno) $id
360 set actualparents {}
361 foreach p $parents($id) {
362 if {[info exists ncleft($p)]} {
363 incr ncleft($p) -1
364 lappend actualparents $p
365 }
366 }
367 if {![info exists commitinfo($id)]} {
368 readcommit $id
369 }
370 set x [expr $canvx0 + $level * $linespc]
371 set y2 [expr $canvy + $linespc]
372 if {$linestarty($level) < $canvy} {
373 set t [$canv create line $x $linestarty($level) $x $canvy \
374 -width 2 -fill $colormap($id)]
375 $canv lower $t
376 set linestarty($level) $canvy
377 }
378 set t [$canv create oval [expr $x - 4] [expr $canvy - 4] \
379 [expr $x + 3] [expr $canvy + 3] \
380 -fill blue -outline black -width 1]
381 $canv raise $t
382 set xt [expr $canvx0 + $nlines * $linespc]
383 set headline [lindex $commitinfo($id) 0]
384 set name [lindex $commitinfo($id) 1]
385 set date [lindex $commitinfo($id) 2]
386 set linehtag($lineno) [$canv create text $xt $canvy -anchor w \
387 -text $headline -font $mainfont ]
388 set linentag($lineno) [$canv2 create text 3 $canvy -anchor w \
389 -text $name -font $namefont]
390 set linedtag($lineno) [$canv3 create text 3 $canvy -anchor w \
391 -text $date -font $mainfont]
392 if {!$datemode && [llength $actualparents] == 1} {
393 set p [lindex $actualparents 0]
394 if {$ncleft($p) == 0 && [lsearch -exact $todo $p] < 0} {
395 assigncolor $p
396 set todo [lreplace $todo $level $level $p]
397 continue
398 }
399 }
400
401 set oldtodo $todo
402 set oldlevel $level
403 set lines {}
404 for {set i 0} {$i < $nlines} {incr i} {
405 if {[lindex $todo $i] == {}} continue
406 set oldstarty($i) $linestarty($i)
407 if {$i != $level} {
408 lappend lines [list $i [lindex $todo $i]]
409 }
410 }
411 unset linestarty
412 if {$nullentry >= 0} {
413 set todo [lreplace $todo $nullentry $nullentry]
414 if {$nullentry < $level} {
415 incr level -1
416 }
417 }
418
419 set todo [lreplace $todo $level $level]
420 if {$nullentry > $level} {
421 incr nullentry -1
422 }
423 set i $level
424 foreach p $actualparents {
425 set k [lsearch -exact $todo $p]
426 if {$k < 0} {
427 assigncolor $p
428 set todo [linsert $todo $i $p]
429 if {$nullentry >= $i} {
430 incr nullentry
431 }
432 }
433 lappend lines [list $oldlevel $p]
434 }
435
436 # choose which one to do next time around
437 set todol [llength $todo]
438 set level -1
439 set latest {}
440 for {set k $todol} {[incr k -1] >= 0} {} {
441 set p [lindex $todo $k]
442 if {$p == {}} continue
443 if {$ncleft($p) == 0} {
444 if {$datemode} {
445 if {$latest == {} || $cdate($p) > $latest} {
446 set level $k
447 set latest $cdate($p)
448 }
449 } else {
450 set level $k
451 break
452 }
453 }
454 }
455 if {$level < 0} {
456 if {$todo != {}} {
457 puts "ERROR: none of the pending commits can be done yet:"
458 foreach p $todo {
459 puts " $p"
460 }
461 }
462 break
463 }
464
465 # If we are reducing, put in a null entry
466 if {$todol < $nlines} {
467 if {$nullentry >= 0} {
468 set i $nullentry
469 while {$i < $todol
470 && [lindex $oldtodo $i] == [lindex $todo $i]} {
471 incr i
472 }
473 } else {
474 set i $oldlevel
475 if {$level >= $i} {
476 incr i
477 }
478 }
479 if {$i >= $todol} {
480 set nullentry -1
481 } else {
482 set nullentry $i
483 set todo [linsert $todo $nullentry {}]
484 if {$level >= $i} {
485 incr level
486 }
487 }
488 } else {
489 set nullentry -1
490 }
491
492 foreach l $lines {
493 set i [lindex $l 0]
494 set dst [lindex $l 1]
495 set j [lsearch -exact $todo $dst]
496 if {$i == $j} {
497 set linestarty($i) $oldstarty($i)
498 continue
499 }
500 set xi [expr {$canvx0 + $i * $linespc}]
501 set xj [expr {$canvx0 + $j * $linespc}]
502 set coords {}
503 if {$oldstarty($i) < $canvy} {
504 lappend coords $xi $oldstarty($i)
505 }
506 lappend coords $xi $canvy
507 if {$j < $i - 1} {
508 lappend coords [expr $xj + $linespc] $canvy
509 } elseif {$j > $i + 1} {
510 lappend coords [expr $xj - $linespc] $canvy
511 }
512 lappend coords $xj $y2
513 set t [$canv create line $coords -width 2 -fill $colormap($dst)]
514 $canv lower $t
515 if {![info exists linestarty($j)]} {
516 set linestarty($j) $y2
517 }
518 }
519 }
520}
521
522proc selcanvline {x y} {
523 global canv canvy0 ctext linespc selectedline
524 global lineid linehtag linentag linedtag
525 set ymax [lindex [$canv cget -scrollregion] 3]
526 set yfrac [lindex [$canv yview] 0]
527 set y [expr {$y + $yfrac * $ymax}]
528 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
529 if {$l < 0} {
530 set l 0
531 }
532 if {[info exists selectedline] && $selectedline == $l} return
533 selectline $l
534}
535
536proc selectline {l} {
537 global canv canv2 canv3 ctext commitinfo selectedline
538 global lineid linehtag linentag linedtag
539 global canvy canvy0 linespc nparents treepending
540 global cflist treediffs currentid
541 if {![info exists lineid($l)] || ![info exists linehtag($l)]} return
542 $canv delete secsel
543 set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \
544 -tags secsel -fill [$canv cget -selectbackground]]
545 $canv lower $t
546 $canv2 delete secsel
547 set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \
548 -tags secsel -fill [$canv2 cget -selectbackground]]
549 $canv2 lower $t
550 $canv3 delete secsel
551 set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \
552 -tags secsel -fill [$canv3 cget -selectbackground]]
553 $canv3 lower $t
554 set y [expr {$canvy0 + $l * $linespc}]
555 set ytop [expr {($y - $linespc / 2.0) / $canvy}]
556 set ybot [expr {($y + $linespc / 2.0) / $canvy}]
557 set wnow [$canv yview]
558 if {$ytop < [lindex $wnow 0]} {
559 allcanvs yview moveto $ytop
560 } elseif {$ybot > [lindex $wnow 1]} {
561 set wh [expr {[lindex $wnow 1] - [lindex $wnow 0]}]
562 allcanvs yview moveto [expr {$ybot - $wh}]
563 }
564 set selectedline $l
565
566 set id $lineid($l)
567 $ctext conf -state normal
568 $ctext delete 0.0 end
569 set info $commitinfo($id)
570 $ctext insert end "Author: [lindex $info 1] [lindex $info 2]\n"
571 $ctext insert end "Committer: [lindex $info 3] [lindex $info 4]\n"
572 $ctext insert end "\n"
573 $ctext insert end [lindex $info 5]
574 $ctext insert end "\n"
575 $ctext tag delete Comments
576 $ctext conf -state disabled
577
578 $cflist delete 0 end
579 set currentid $id
580 if {$nparents($id) == 1} {
581 if {![info exists treediffs($id)]} {
582 if {![info exists treepending]} {
583 gettreediffs $id
584 }
585 } else {
586 addtocflist $id
587 }
588 }
589}
590
591proc selnextline {dir} {
592 global selectedline
593 if {![info exists selectedline]} return
594 set l [expr $selectedline + $dir]
595 selectline $l
596}
597
598proc addtocflist {id} {
599 global currentid treediffs cflist treepending
600 if {$id != $currentid} {
601 gettreediffs $currentid
602 return
603 }
604 $cflist insert end "All files"
605 foreach f $treediffs($currentid) {
606 $cflist insert end $f
607 }
608 getblobdiffs $id
609}
610
611proc gettreediffs {id} {
612 global treediffs parents treepending
613 set treepending $id
614 set treediffs($id) {}
615 set p [lindex $parents($id) 0]
616 if [catch {set gdtf [open "|git-diff-tree -r $p $id" r]}] return
617 fconfigure $gdtf -blocking 0
618 fileevent $gdtf readable "gettreediffline $gdtf $id"
619}
620
621proc gettreediffline {gdtf id} {
622 global treediffs treepending
623 set n [gets $gdtf line]
624 if {$n < 0} {
625 if {![eof $gdtf]} return
626 close $gdtf
627 unset treepending
628 addtocflist $id
629 return
630 }
631 set type [lindex $line 1]
632 set file [lindex $line 3]
633 if {$type == "blob"} {
634 lappend treediffs($id) $file
635 }
636}
637
638proc getblobdiffs {id} {
639 global parents diffopts blobdifffd env curdifftag curtagstart
640 set p [lindex $parents($id) 0]
641 set env(GIT_DIFF_OPTS) $diffopts
642 if [catch {set bdf [open "|git-diff-tree -r -p $p $id" r]} err] {
643 puts "error getting diffs: $err"
644 return
645 }
646 fconfigure $bdf -blocking 0
647 set blobdifffd($id) $bdf
648 set curdifftag Comments
649 set curtagstart 0.0
650 fileevent $bdf readable "getblobdiffline $bdf $id"
651}
652
653proc getblobdiffline {bdf id} {
654 global currentid blobdifffd ctext curdifftag curtagstart
655 set n [gets $bdf line]
656 if {$n < 0} {
657 if {[eof $bdf]} {
658 close $bdf
659 if {$id == $currentid && $bdf == $blobdifffd($id)} {
660 $ctext tag add $curdifftag $curtagstart end
661 }
662 }
663 return
664 }
665 if {$id != $currentid || $bdf != $blobdifffd($id)} {
666 return
667 }
668 $ctext conf -state normal
669 if {[regexp {^---[ \t]+([^/])+/(.*)} $line match s1 fname]} {
670 # start of a new file
671 $ctext insert end "\n"
672 $ctext tag add $curdifftag $curtagstart end
673 set curtagstart [$ctext index "end - 1c"]
674 set curdifftag "f:$fname"
675 $ctext tag delete $curdifftag
676 set l [expr {(78 - [string length $fname]) / 2}]
677 set pad [string range "----------------------------------------" 1 $l]
678 $ctext insert end "$pad $fname $pad\n" filesep
679 } elseif {[string range $line 0 2] == "+++"} {
680 # no need to do anything with this
681 } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \
682 $line match f1l f1c f2l f2c rest]} {
683 $ctext insert end "\t" hunksep
684 $ctext insert end " $f1l " d0 " $f2l " d1
685 $ctext insert end " $rest \n" hunksep
686 } else {
687 set x [string range $line 0 0]
688 if {$x == "-" || $x == "+"} {
689 set tag [expr {$x == "+"}]
690 set line [string range $line 1 end]
691 $ctext insert end "$line\n" d$tag
692 } elseif {$x == " "} {
693 set line [string range $line 1 end]
694 $ctext insert end "$line\n"
695 } else {
696 # Something else we don't recognize
697 if {$curdifftag != "Comments"} {
698 $ctext insert end "\n"
699 $ctext tag add $curdifftag $curtagstart end
700 set curtagstart [$ctext index "end - 1c"]
701 set curdifftag Comments
702 }
703 $ctext insert end "$line\n" filesep
704 }
705 }
706 $ctext conf -state disabled
707}
708
709proc listboxsel {} {
710 global ctext cflist currentid treediffs
711 if {![info exists currentid]} return
712 set sel [$cflist curselection]
713 if {$sel == {} || [lsearch -exact $sel 0] >= 0} {
714 # show everything
715 $ctext tag conf Comments -elide 0
716 foreach f $treediffs($currentid) {
717 $ctext tag conf "f:$f" -elide 0
718 }
719 } else {
720 # just show selected files
721 $ctext tag conf Comments -elide 1
722 set i 1
723 foreach f $treediffs($currentid) {
724 set elide [expr {[lsearch -exact $sel $i] < 0}]
725 $ctext tag conf "f:$f" -elide $elide
726 incr i
727 }
728 }
729}
730
731if {![getcommits $revtreeargs]} {
732 exit 1
733}
734
735set linespc [font metrics $mainfont -linespace]
736set charspc [font measure $mainfont "m"]
737
738set canvy0 [expr 3 + 0.5 * $linespc]
739set canvx0 [expr 3 + 0.5 * $linespc]
740set namex [expr 45 * $charspc]
741set datex [expr 75 * $charspc]
742
743set stopped 0
744makewindow
745
746set start {}
747foreach id $commits {
748 if {$nchildren($id) == 0} {
749 set start $id
750 break
751 }
752}
753if {$start != {}} {
754 drawgraph $start
755}